1 #include <sys/socket.h>
2 #include <netinet/in.h>
3 #include <netdb.h>
4 #include <net/if.h>
5 #include <arpa/inet.h>
6 #include <ctype.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <fcntl.h>
10 #include <unistd.h>
11 #include <pthread.h>
12 #include <errno.h>
13 #include <resolv.h>
14 #include "lookup.h"
15 #include "stdio_impl.h"
16 #include "syscall.h"
17 #include <dlfcn.h>
18 #define BREAK 0
19 #define CONTINUE 1
20 #if OHOS_PERMISSION_INTERNET
21 uint8_t is_allow_internet(void);
22 #endif
23 #define FIXED_HOSTS_MAX_LENGTH 2
24 #define FIXED_HOSTS_STR_MAX_LENGTH 23
25
26 char fixed_hosts[][FIXED_HOSTS_STR_MAX_LENGTH] = {
27 "127.0.0.1 localhost\r\n\0",
28 "::1 ip6-localhost\r\n\0"
29 };
30
is_valid_hostname(const char * host)31 static int is_valid_hostname(const char *host)
32 {
33 const unsigned char *s;
34 if (strnlen(host, 255)-1 >= 254 || mbstowcs(0, host, 0) == -1) return 0;
35 for (s=(void *)host; *s>=0x80 || *s=='.' || *s=='-' || isalnum(*s); s++);
36 return !*s;
37 }
38
name_from_null(struct address buf[static2],const char * name,int family,int flags)39 static int name_from_null(struct address buf[static 2], const char *name, int family, int flags)
40 {
41 int cnt = 0;
42 if (name) return 0;
43 if (flags & AI_PASSIVE) {
44 if (family != AF_INET6)
45 buf[cnt++] = (struct address){ .family = AF_INET };
46 if (family != AF_INET)
47 buf[cnt++] = (struct address){ .family = AF_INET6 };
48 } else {
49 if (family != AF_INET6)
50 buf[cnt++] = (struct address){ .family = AF_INET, .addr = { 127,0,0,1 } };
51 if (family != AF_INET)
52 buf[cnt++] = (struct address){ .family = AF_INET6, .addr = { [15] = 1 } };
53 }
54 return cnt;
55 }
56
name_from_numeric(struct address buf[static1],const char * name,int family)57 static int name_from_numeric(struct address buf[static 1], const char *name, int family)
58 {
59 return __lookup_ipliteral(buf, name, family);
60 }
61
get_hosts_str(char * line,int length,FILE * f,int * i)62 static inline int get_hosts_str(char *line, int length, FILE *f, int *i)
63 {
64 if (f) {
65 char *ret = fgets(line, length, f);
66 if (ret) {
67 size_t len = strlen(line);
68 if (len > 0 && line[len - 1] != '\n' && len < length - 1) {
69 line[len] = '\n';
70 line[len + 1] = '\0';
71 }
72 }
73 return ret;
74 }
75 if (*i < FIXED_HOSTS_MAX_LENGTH) {
76 memcpy(line, fixed_hosts[*i], strlen(fixed_hosts[*i]));
77 (*i)++;
78 return 1;
79 }
80 return NULL;
81 }
82
name_from_hosts(struct address buf[static MAXADDRS],char canon[static256],const char * name,int family)83 static int name_from_hosts(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family)
84 {
85 char line[512];
86 size_t l = strlen(name);
87 int cnt = 0, badfam = 0, have_canon = 0;
88 unsigned char _buf[1032];
89 FILE _f, *f = __fopen_rb_ca("/etc/hosts", &_f, _buf, sizeof _buf);
90 int i = 0;
91 while (i < FIXED_HOSTS_MAX_LENGTH && get_hosts_str(line, sizeof line, f, &i) && cnt < MAXADDRS) {
92 char *p, *z;
93
94 if ((p=strchr(line, '#'))) *p++='\n', *p=0;
95 for(p=line+1; (p=strstr(p, name)) &&
96 (!isspace(p[-1]) || !isspace(p[l])); p++);
97 if (!p) continue;
98
99 /* Isolate IP address to parse */
100 for (p=line; *p && !isspace(*p); p++);
101 *p++ = 0;
102 switch (name_from_numeric(buf+cnt, line, family)) {
103 case 1:
104 cnt++;
105 break;
106 case 0:
107 continue;
108 default:
109 badfam = EAI_NONAME;
110 break;
111 }
112
113 if (have_canon) continue;
114
115 /* Extract first name as canonical name */
116 for (; *p && isspace(*p); p++);
117 for (z=p; *z && !isspace(*z); z++);
118 *z = 0;
119 if (is_valid_hostname(p)) {
120 have_canon = 1;
121 memcpy(canon, p, z-p+1);
122 }
123 }
124 if (f) {
125 __fclose_ca(f);
126 }
127 return cnt ? cnt : badfam;
128 }
129
130 struct dpc_ctx {
131 struct address *addrs;
132 char *canon;
133 int cnt;
134 int rrtype;
135 };
136
137 #define RR_A 1
138 #define RR_CNAME 5
139 #define RR_AAAA 28
140 #define MAX_QUERY_SIZE 5
141 #define VALID_ANSWER 1
142 #define MIN_ANSWER_TYPE 1
143 #define MAX_ANSWER_TYPE 2
144 #define MAX_NAME_LENGTH 256
145 #define ABUF_SIZE 4800
146
dns_parse_callback(void * c,int rr,const void * data,int len,const void * packet,int plen)147 static int dns_parse_callback(void *c, int rr, const void *data, int len, const void *packet, int plen)
148 {
149 char tmp[256];
150 int family;
151 struct dpc_ctx *ctx = c;
152 if (rr == RR_CNAME) {
153 if (__dn_expand(packet, (const unsigned char *)packet + plen,
154 data, tmp, sizeof tmp) > 0 && is_valid_hostname(tmp))
155 strcpy(ctx->canon, tmp);
156 return 0;
157 }
158 if (ctx->cnt >= MAXADDRS) return 0;
159 if (rr != ctx->rrtype) return 0;
160 switch (rr) {
161 case RR_A:
162 if (len != 4) return -1;
163 family = AF_INET;
164 break;
165 case RR_AAAA:
166 if (len != 16) return -1;
167 family = AF_INET6;
168 break;
169 }
170 ctx->addrs[ctx->cnt].family = family;
171 ctx->addrs[ctx->cnt].scopeid = 0;
172 memcpy(ctx->addrs[ctx->cnt++].addr, data, len);
173 return 0;
174 }
175
176 #if OHOS_DNS_PROXY_BY_NETSYS
load_ipv6_judger(void)177 static JudgeIpv6 load_ipv6_judger(void)
178 {
179 static JudgeIpv6 ipv6_judger = NULL;
180 resolve_dns_sym((void **) &ipv6_judger, OHOS_JUDGE_IPV6_FUNC_NAME);
181 return ipv6_judger;
182 }
183 #endif
184
IsIpv6Enable(int netid)185 static int IsIpv6Enable(int netid)
186 {
187 int ret = 0;
188 #if OHOS_DNS_PROXY_BY_NETSYS
189 JudgeIpv6 func = load_ipv6_judger();
190 if (!func) {
191 return -1;
192 }
193
194 ret = func(netid);
195 if (ret < 0) {
196 return -1;
197 }
198 #endif
199 return ret;
200 }
201
IsAnswerValid(const unsigned char * answer,int alen)202 static int IsAnswerValid(const unsigned char *answer, int alen)
203 {
204 if (alen < 4 || (answer[3] & 15) == 2) {
205 return EAI_AGAIN;
206 }
207 if ((answer[3] & 15) == 3) return 0;
208 if ((answer[3] & 15) != 0) {
209 return EAI_FAIL;
210 }
211 return VALID_ANSWER;
212 }
213
name_from_dns(struct address buf[static MAXADDRS],char canon[static256],const char * name,int family,const struct resolvconf * conf,int netid)214 static int name_from_dns(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family, const struct resolvconf *conf, int netid)
215 {
216 unsigned char qbuf[2][280], abuf[2][ABUF_SIZE];
217 const unsigned char *qp[2] = { qbuf[0], qbuf[1] };
218 unsigned char *ap[2] = { abuf[0], abuf[1] };
219 int qlens[2], alens[2], qtypes[2];
220 int queryNum = 2;
221 struct dpc_ctx ctx = { .addrs = buf, .canon = canon };
222 static const struct { int af; int rr; } afrr_ipv6_enable[2] = {
223 { .af = AF_INET, .rr = RR_AAAA },
224 { .af = AF_INET6, .rr = RR_A },
225 };
226 static const struct { int af; int rr; } afrr_ipv4_only[1] = {
227 { .af = AF_INET6, .rr = RR_A },
228 };
229 struct {int af; int rr;} *afrr = afrr_ipv6_enable;
230
231 if (!IsIpv6Enable(netid) || (family == AF_INET)) {
232 if (family == AF_INET6) {
233 #ifndef __LITEOS__
234 MUSL_LOGE("%{public}s: %{public}d: Network scenario mismatch: %{public}d", __func__, __LINE__, EAI_SYSTEM);
235 #endif
236 return EAI_SYSTEM;
237 }
238 queryNum = 1;
239 afrr = afrr_ipv4_only;
240 } else {
241 queryNum = 2;
242 afrr = afrr_ipv6_enable;
243 }
244
245 int cname_count = 0;
246 const char *queryName = name;
247 int checkBuf[MAX_ANSWER_TYPE] = {VALID_ANSWER, VALID_ANSWER};
248 while (strnlen(queryName, MAX_NAME_LENGTH) != 0 && cname_count < MAX_QUERY_SIZE) {
249 int i, nq = 0;
250 for (i = 0; i < queryNum; i++) {
251 if (family != afrr[i].af) {
252 qlens[nq] = __res_mkquery(0, queryName, 1, afrr[i].rr,
253 0, 0, 0, qbuf[nq], sizeof *qbuf);
254 if (qlens[nq] == -1) {
255 #ifndef __LITEOS__
256 MUSL_LOGE("%{public}s: %{public}d: Illegal querys: %{public}d", __func__, __LINE__, EAI_NONAME);
257 #endif
258 return 0;
259 }
260 qtypes[nq] = afrr[i].rr;
261 qbuf[nq][3] = 0; /* don't need AD flag */
262 /* Ensure query IDs are distinct. */
263 if (nq && qbuf[nq][0] == qbuf[0][0])
264 qbuf[nq][0]++;
265 nq++;
266 }
267 }
268
269 if (res_msend_rc_ext(netid, nq, qp, qlens, ap, alens, sizeof *abuf, conf) < 0)
270 return EAI_SYSTEM;
271
272 for (i=0; i<nq; i++) {
273 checkBuf[i] = IsAnswerValid(abuf[i], alens[i]);
274 }
275 if (checkBuf[MIN_ANSWER_TYPE - 1] != VALID_ANSWER &&
276 (nq < MAX_ANSWER_TYPE || checkBuf[MAX_ANSWER_TYPE - 1] != VALID_ANSWER)) {
277 #ifndef __LITEOS__
278 MUSL_LOGE("%{public}s: %{public}d: Illegal answers, errno id: %{public}d",
279 __func__, __LINE__, checkBuf[MIN_ANSWER_TYPE - 1]);
280 #endif
281 return checkBuf[MIN_ANSWER_TYPE - 1];
282 }
283
284 for (i=nq-1; i>=0; i--) {
285 ctx.rrtype = qtypes[i];
286 if (alens[i] > sizeof(abuf[i])) alens[i] = sizeof abuf[i];
287 __dns_parse(abuf[i], alens[i], dns_parse_callback, &ctx);
288 }
289 if (ctx.cnt) return ctx.cnt;
290 queryName = ctx.canon;
291 cname_count++;
292 }
293 #ifndef __LITEOS__
294 MUSL_LOGE("%{public}s: %{public}d: failed to parse dns : %{public}d", __func__, __LINE__, cname_count);
295 #endif
296 return EAI_NONAME;
297 }
298
name_from_dns_search(struct address buf[static MAXADDRS],char canon[static256],const char * name,int family,int netid)299 static int name_from_dns_search(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family, int netid)
300 {
301 #if OHOS_PERMISSION_INTERNET
302 if (is_allow_internet() == 0) {
303 errno = EPERM;
304 #ifndef __LITEOS__
305 MUSL_LOGE("%{public}s: %{public}d: internet is not allowed", __func__, __LINE__);
306 #endif
307 return -1;
308 }
309 #endif
310
311 char search[256];
312 struct resolvconf conf;
313 size_t l, dots;
314 char *p, *z;
315
316 int res = get_resolv_conf_ext(&conf, search, sizeof search, netid);
317 if (res < 0) return res;
318
319 /* Count dots, suppress search when >=ndots or name ends in
320 * a dot, which is an explicit request for global scope. */
321 for (dots=l=0; name[l]; l++) if (name[l]=='.') dots++;
322 if (dots >= conf.ndots || name[l-1]=='.') *search = 0;
323
324 /* Strip final dot for canon, fail if multiple trailing dots. */
325 if (name[l-1]=='.') l--;
326 if (!l || name[l-1]=='.') {
327 #ifndef __LITEOS__
328 MUSL_LOGE("%{public}s: %{public}d: fail when multiple trailing dots: %{public}d", __func__, __LINE__, EAI_NONAME);
329 #endif
330 return EAI_NONAME;
331 }
332
333 /* This can never happen; the caller already checked length. */
334 if (l >= 256) return EAI_NONAME;
335
336 /* Name with search domain appended is setup in canon[]. This both
337 * provides the desired default canonical name (if the requested
338 * name is not a CNAME record) and serves as a buffer for passing
339 * the full requested name to name_from_dns. */
340 memcpy(canon, name, l);
341 canon[l] = '.';
342
343 for (p=search; *p; p=z) {
344 for (; isspace(*p); p++);
345 for (z=p; *z && !isspace(*z); z++);
346 if (z==p) break;
347 if (z-p < 256 - l - 1) {
348 memcpy(canon+l+1, p, z-p);
349 canon[z-p+1+l] = 0;
350 int cnt = name_from_dns(buf, canon, canon, family, &conf, netid);
351 if (cnt) return cnt;
352 }
353 }
354
355 canon[l] = 0;
356 return name_from_dns(buf, canon, name, family, &conf, netid);
357 }
358
359 static const struct policy {
360 unsigned char addr[16];
361 unsigned char len, mask;
362 unsigned char prec, label;
363 } defpolicy[] = {
364 { "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1", 15, 0xff, 50, 0 },
365 { "\0\0\0\0\0\0\0\0\0\0\xff\xff", 11, 0xff, 35, 4 },
366 { "\x20\2", 1, 0xff, 30, 2 },
367 { "\x20\1", 3, 0xff, 5, 5 },
368 { "\xfc", 0, 0xfe, 3, 13 },
369 #if 0
370 /* These are deprecated and/or returned to the address
371 * pool, so despite the RFC, treating them as special
372 * is probably wrong. */
373 { "", 11, 0xff, 1, 3 },
374 { "\xfe\xc0", 1, 0xc0, 1, 11 },
375 { "\x3f\xfe", 1, 0xff, 1, 12 },
376 #endif
377 /* Last rule must match all addresses to stop loop. */
378 { "", 0, 0, 40, 1 },
379 };
380
policyof(const struct in6_addr * a)381 static const struct policy *policyof(const struct in6_addr *a)
382 {
383 int i;
384 for (i=0; ; i++) {
385 if (memcmp(a->s6_addr, defpolicy[i].addr, defpolicy[i].len))
386 continue;
387 if ((a->s6_addr[defpolicy[i].len] & defpolicy[i].mask)
388 != defpolicy[i].addr[defpolicy[i].len])
389 continue;
390 return defpolicy+i;
391 }
392 }
393
labelof(const struct in6_addr * a)394 static int labelof(const struct in6_addr *a)
395 {
396 return policyof(a)->label;
397 }
398
scopeof(const struct in6_addr * a)399 static int scopeof(const struct in6_addr *a)
400 {
401 if (IN6_IS_ADDR_MULTICAST(a)) return a->s6_addr[1] & 15;
402 if (IN6_IS_ADDR_LINKLOCAL(a)) return 2;
403 if (IN6_IS_ADDR_LOOPBACK(a)) return 2;
404 if (IN6_IS_ADDR_SITELOCAL(a)) return 5;
405 return 14;
406 }
407
prefixmatch(const struct in6_addr * s,const struct in6_addr * d)408 static int prefixmatch(const struct in6_addr *s, const struct in6_addr *d)
409 {
410 /* FIXME: The common prefix length should be limited to no greater
411 * than the nominal length of the prefix portion of the source
412 * address. However the definition of the source prefix length is
413 * not clear and thus this limiting is not yet implemented. */
414 unsigned i;
415 for (i=0; i<128 && !((s->s6_addr[i/8]^d->s6_addr[i/8])&(128>>(i%8))); i++);
416 return i;
417 }
418
419 #define DAS_USABLE 0x40000000
420 #define DAS_MATCHINGSCOPE 0x20000000
421 #define DAS_MATCHINGLABEL 0x10000000
422 #define DAS_PREC_SHIFT 20
423 #define DAS_SCOPE_SHIFT 16
424 #define DAS_PREFIX_SHIFT 8
425 #define DAS_ORDER_SHIFT 0
426
addrcmp(const void * _a,const void * _b)427 static int addrcmp(const void *_a, const void *_b)
428 {
429 const struct address *a = _a, *b = _b;
430 return b->sortkey - a->sortkey;
431 }
432
lookup_name_ext(struct address buf[static MAXADDRS],char canon[static256],const char * name,int family,int flags,int netid)433 int lookup_name_ext(struct address buf[static MAXADDRS], char canon[static 256], const char *name,
434 int family, int flags, int netid)
435 {
436 int cnt = 0, i, j;
437
438 #if OHOS_DNS_PROXY_BY_NETSYS
439 DNS_CONFIG_PRINT("lookup_name_ext \n");
440 #endif
441
442 *canon = 0;
443 if (name) {
444 /* reject empty name and check len so it fits into temp bufs */
445 size_t l = strnlen(name, 255);
446 if (l-1 >= 254) {
447 #ifndef __LITEOS__
448 MUSL_LOGE("%{public}s: %{public}d: Illegal name length: %{public}zu", __func__, __LINE__, l);
449 #endif
450 return EAI_NONAME;
451 }
452 memcpy(canon, name, l+1);
453 }
454
455 /* Procedurally, a request for v6 addresses with the v4-mapped
456 * flag set is like a request for unspecified family, followed
457 * by filtering of the results. */
458 if (flags & AI_V4MAPPED) {
459 if (family == AF_INET6) family = AF_UNSPEC;
460 else flags -= AI_V4MAPPED;
461 }
462
463 /* Try each backend until there's at least one result. */
464 cnt = name_from_null(buf, name, family, flags);
465 if (!cnt) cnt = name_from_numeric(buf, name, family);
466 #ifndef __LITEOS__
467 if (!cnt && (flags & AI_NUMERICHOST)) {
468 MUSL_LOGE("%{public}s: %{public}d: flag is AI_NUMERICHOST but host is Illegal", __func__, __LINE__);
469 }
470 #endif
471 if (!cnt && !(flags & AI_NUMERICHOST)) {
472 cnt = predefined_host_name_from_hosts(buf, canon, name, family);
473 if (!cnt) cnt = name_from_hosts(buf, canon, name, family);
474 if (!cnt) cnt = name_from_dns_search(buf, canon, name, family, netid);
475 }
476 if (cnt<=0) return cnt ? cnt : EAI_NONAME;
477
478 /* Filter/transform results for v4-mapped lookup, if requested. */
479 if (flags & AI_V4MAPPED) {
480 if (!(flags & AI_ALL)) {
481 /* If any v6 results exist, remove v4 results. */
482 for (i=0; i<cnt && buf[i].family != AF_INET6; i++);
483 if (i<cnt) {
484 for (j=0; i<cnt; i++) {
485 if (buf[i].family == AF_INET6)
486 buf[j++] = buf[i];
487 }
488 cnt = i = j;
489 }
490 }
491 /* Translate any remaining v4 results to v6 */
492 for (i=0; i<cnt; i++) {
493 if (buf[i].family != AF_INET) continue;
494 memcpy(buf[i].addr+12, buf[i].addr, 4);
495 memcpy(buf[i].addr, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12);
496 buf[i].family = AF_INET6;
497 }
498 }
499
500 /* No further processing is needed if there are fewer than 2
501 * results or if there are only IPv4 results. */
502 if (cnt<2 || family==AF_INET) return cnt;
503 for (i=0; i<cnt; i++) if (buf[i].family != AF_INET) break;
504 if (i==cnt) return cnt;
505
506 int cs;
507 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
508
509 /* The following implements a subset of RFC 3484/6724 destination
510 * address selection by generating a single 31-bit sort key for
511 * each address. Rules 3, 4, and 7 are omitted for having
512 * excessive runtime and code size cost and dubious benefit.
513 * So far the label/precedence table cannot be customized. */
514 for (i=0; i<cnt; i++) {
515 int family = buf[i].family;
516 int key = 0;
517 struct sockaddr_in6 sa6 = { 0 }, da6 = {
518 .sin6_family = AF_INET6,
519 .sin6_scope_id = buf[i].scopeid,
520 .sin6_port = 65535
521 };
522 struct sockaddr_in sa4 = { 0 }, da4 = {
523 .sin_family = AF_INET,
524 .sin_port = 65535
525 };
526 void *sa, *da;
527 socklen_t salen, dalen;
528 if (family == AF_INET6) {
529 memcpy(da6.sin6_addr.s6_addr, buf[i].addr, 16);
530 da = &da6; dalen = sizeof da6;
531 sa = &sa6; salen = sizeof sa6;
532 } else {
533 memcpy(sa6.sin6_addr.s6_addr,
534 "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12);
535 memcpy(da6.sin6_addr.s6_addr+12, buf[i].addr, 4);
536 memcpy(da6.sin6_addr.s6_addr,
537 "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12);
538 memcpy(da6.sin6_addr.s6_addr+12, buf[i].addr, 4);
539 memcpy(&da4.sin_addr, buf[i].addr, 4);
540 da = &da4; dalen = sizeof da4;
541 sa = &sa4; salen = sizeof sa4;
542 }
543 const struct policy *dpolicy = policyof(&da6.sin6_addr);
544 int dscope = scopeof(&da6.sin6_addr);
545 int dlabel = dpolicy->label;
546 int dprec = dpolicy->prec;
547 int prefixlen = 0;
548 int fd = socket(family, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_UDP);
549 if (fd >= 0) {
550 if (!connect(fd, da, dalen)) {
551 key |= DAS_USABLE;
552 if (!getsockname(fd, sa, &salen)) {
553 if (family == AF_INET) memcpy(
554 sa6.sin6_addr.s6_addr+12,
555 &sa4.sin_addr, 4);
556 if (dscope == scopeof(&sa6.sin6_addr))
557 key |= DAS_MATCHINGSCOPE;
558 if (dlabel == labelof(&sa6.sin6_addr))
559 key |= DAS_MATCHINGLABEL;
560 prefixlen = prefixmatch(&sa6.sin6_addr,
561 &da6.sin6_addr);
562 }
563 }
564 close(fd);
565 }
566 key |= dprec << DAS_PREC_SHIFT;
567 key |= (15-dscope) << DAS_SCOPE_SHIFT;
568 key |= prefixlen << DAS_PREFIX_SHIFT;
569 key |= (MAXADDRS-i) << DAS_ORDER_SHIFT;
570 buf[i].sortkey = key;
571 }
572 qsort(buf, cnt, sizeof *buf, addrcmp);
573
574 pthread_setcancelstate(cs, 0);
575
576 return cnt;
577 }
578
__lookup_name(struct address buf[static MAXADDRS],char canon[static256],const char * name,int family,int flags)579 int __lookup_name(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family, int flags)
580 {
581 return lookup_name_ext(buf, canon, name, family, flags, 0);
582 }
583
584 typedef struct _linknode {
585 struct _linknode *_next;
586 void *_data;
587 }linknode;
588
589 typedef struct _linkList {
590 linknode *_phead;
591 int _count;
592 }linkList;
593
594 static linkList *create_linklist(void);
595 static int destory_linklist(linkList *plist);
596 static int linklist_size(linkList *plist);
597 static linknode *get_linknode(linkList *plist, int index);
598 static int linklist_append_last(linkList *plist, void *pdata);
599 static int linklist_delete(linkList *plist, int index);
600 static int linklist_delete_first(linkList *plist);
601 static int linklist_delete_last(linkList *plist);
602
603 typedef struct {
604 char* host;
605 char* ip;
606 }host_ip_pair;
607
608 static const char GROUP_SEPARATOR[] = "|";
609 static const char SEPARATOR[] = ",";
610
611 static linkList *host_ips_list_ = NULL;
612
strsep(char ** s,const char * ct)613 static char *strsep(char **s, const char *ct)
614 {
615 char *sbegin = *s;
616 char *end;
617 if (sbegin == NULL) {
618 return NULL;
619 }
620 end = strpbrk(sbegin, ct);
621 if (end) {
622 *end++ = '\0';
623 }
624 *s = end;
625 return sbegin;
626 }
627
predefined_host_clear_all_hosts(void)628 int predefined_host_clear_all_hosts(void)
629 {
630 if (host_ips_list_ != NULL) {
631 linknode *pnode = host_ips_list_->_phead;
632 while (pnode != NULL) {
633 free(pnode->_data);
634 pnode->_data = NULL;
635 pnode = pnode->_next;
636 }
637
638 destory_linklist(host_ips_list_);
639 free(host_ips_list_);
640 host_ips_list_ = NULL;
641 return 0;
642 }
643 return -1;
644 }
645
predefined_host_remove_host(const char * host)646 int predefined_host_remove_host(const char *host)
647 {
648 int remove_cnt = 0;
649 if (host_ips_list_ != NULL) {
650 linknode *pnode = NULL;
651 host_ip_pair *pinfo = NULL;
652 int cnt = linklist_size(host_ips_list_);
653
654 for (int i = cnt - 1; i >= 0; i--) {
655 pnode = get_linknode(host_ips_list_, i);
656 if (pnode != NULL) {
657 pinfo = (host_ip_pair*)pnode->_data;
658 if (strcmp(pinfo->host, host) == 0) {
659 free(pinfo);
660 linklist_delete(host_ips_list_, i);
661 remove_cnt++;
662 }
663 }
664 }
665 }
666
667 return remove_cnt == 0 ? -1 : 0;
668 }
669
_predefined_host_is_contain_host_ip(const char * host,const char * ip,int is_check_ip)670 static int _predefined_host_is_contain_host_ip(const char* host, const char* ip, int is_check_ip)
671 {
672 if (host_ips_list_ != NULL) {
673 linknode *pnode = host_ips_list_->_phead;
674
675 while (pnode != NULL) {
676 host_ip_pair *pinfo = (host_ip_pair*)pnode->_data;
677 if (strcmp(pinfo->host, host) == 0) {
678 if (is_check_ip) {
679 if (strcmp(pinfo->ip, ip) == 0) {
680 return 1;
681 }
682 } else {
683 return 1;
684 }
685 }
686 pnode = pnode->_next;
687 }
688 }
689 return 0;
690 }
691
predefined_host_is_contain_host(const char * host)692 int predefined_host_is_contain_host(const char *host)
693 {
694 return _predefined_host_is_contain_host_ip(host, NULL, 0);
695 }
696
_predefined_host_add_record(char * host,char * ip)697 static int _predefined_host_add_record(char* host, char* ip)
698 {
699 int head_len = sizeof(host_ip_pair);
700 int host_len = strlen(host);
701 int ip_len = strlen(ip);
702 int total = host_len + 1 + ip_len + 1 + head_len;
703 char *pdata = calloc(1, total);
704 host_ip_pair *pinfo = (host_ip_pair*)pdata;
705
706 if (pdata == NULL) {
707 return EAI_NONAME;
708 }
709
710 char* i_host = (char*)(pdata + head_len);
711 char* i_ip = (char*)(pdata + head_len + host_len + 1);
712
713 memcpy(i_host, host, host_len + 1);
714 memcpy(i_ip, ip, ip_len + 1);
715
716 pinfo->host = i_host;
717 pinfo->ip = i_ip;
718
719 linklist_append_last(host_ips_list_, pdata);
720 return 0;
721 }
722
_predefined_host_parse_host_ips(char * params)723 static int _predefined_host_parse_host_ips(char* params)
724 {
725 char* cmd = NULL;
726 int ret = 0;
727 int cnt = 0;
728
729 while ((cmd = strsep(¶ms, GROUP_SEPARATOR)) != NULL) {
730 char* host = strsep(&cmd, SEPARATOR);
731 char* ip = NULL;
732
733 while ((ip = strsep(&cmd, SEPARATOR)) != NULL) {
734 cnt++;
735 if (!_predefined_host_is_contain_host_ip(host, ip, 1)) {
736 ret = _predefined_host_add_record(host, ip);
737 if (ret != 0) {
738 return ret;
739 }
740 }
741 }
742 }
743
744 return cnt > 0 ? 0 : -1;
745 }
746
predefined_host_lookup_ip(const char * host,const char * serv,const struct addrinfo * hint,struct addrinfo ** res)747 int predefined_host_lookup_ip(const char* host, const char* serv,
748 const struct addrinfo* hint, struct addrinfo** res)
749 {
750 int status = -1;
751 if (host_ips_list_ == NULL) {
752 return -1;
753 }
754 linknode *pnode = host_ips_list_->_phead;
755 while (pnode != NULL) {
756 host_ip_pair *pinfo = (host_ip_pair*)pnode->_data;
757 if (strcmp(pinfo->host, host) == 0) {
758 status = getaddrinfo(pinfo->ip, NULL, hint, res);
759 if (status == 0) {
760 return status;
761 }
762 }
763 pnode = pnode->_next;
764 }
765 return status;
766 }
767
predefined_host_set_hosts(const char * host_ips)768 int predefined_host_set_hosts(const char* host_ips)
769 {
770 if (host_ips == NULL) {
771 return EAI_NONAME;
772 }
773
774 int len = strlen(host_ips);
775 if (len == 0) {
776 return EAI_NONAME;
777 }
778
779 if (host_ips_list_ == NULL) {
780 host_ips_list_ = create_linklist();
781 if (host_ips_list_ == NULL) {
782 return EAI_MEMORY;
783 }
784 }
785
786 char *host_ips_str = calloc(1, len + 1);
787 if (host_ips_str == NULL) {
788 return EAI_MEMORY;
789 }
790
791 memcpy(host_ips_str, host_ips, len + 1);
792
793 int ret = _predefined_host_parse_host_ips(host_ips_str);
794
795 free(host_ips_str);
796
797 return ret;
798 }
799
predefined_host_set_host(const char * host,const char * ip)800 int predefined_host_set_host(const char* host, const char* ip)
801 {
802 if (host == NULL || strlen(host) == 0 || ip == NULL || strlen(ip) == 0) {
803 return -1;
804 }
805
806 if (host_ips_list_ == NULL) {
807 host_ips_list_ = create_linklist();
808 if (host_ips_list_ == NULL) {
809 return EAI_NONAME;
810 }
811 }
812
813 if (_predefined_host_is_contain_host_ip(host, ip, 1)) {
814 return 0;
815 }
816
817 return _predefined_host_add_record(host, ip);
818 }
819
predefined_host_name_from_hosts(struct address buf[static MAXADDRS],char canon[static256],const char * name,int family)820 int predefined_host_name_from_hosts(
821 struct address buf[static MAXADDRS],
822 char canon[static 256], const char *name, int family)
823 {
824 int size = 256;
825 int cnt = 0;
826 if (host_ips_list_ != NULL) {
827 linknode *pnode = host_ips_list_->_phead;
828
829 while (pnode != NULL && cnt < MAXADDRS) {
830 host_ip_pair *pinfo = (host_ip_pair*)pnode->_data;
831 if (strcmp(pinfo->host, name) == 0) {
832 if (__lookup_ipliteral(buf+cnt, pinfo->ip, family) == 1) {
833 cnt++;
834 }
835 }
836 pnode = pnode->_next;
837 }
838 }
839
840 if (cnt > 0) {
841 memcpy(canon, name, size);
842 }
843 return cnt;
844 }
845
free_linknodedata(linknode * pnode)846 static inline void free_linknodedata(linknode *pnode)
847 {
848 if (NULL != pnode) {
849 free(pnode);
850 }
851 }
852
create_linknode(void * data)853 static linknode *create_linknode(void *data)
854 {
855 linknode *pnode = (linknode *)calloc(1, sizeof(linknode));
856 if (NULL == pnode) {
857 return NULL;
858 }
859 pnode->_data = data;
860 pnode->_next = NULL;
861
862 return pnode;
863 }
864
create_linklist(void)865 static linkList *create_linklist(void)
866 {
867 linkList *plist = (linkList *)calloc(1, sizeof(linkList));
868 if (NULL == plist) {
869 return NULL;
870 }
871 plist->_phead = NULL;
872 plist->_count = 0;
873
874 return plist;
875 }
876
destory_linklist(linkList * plist)877 static int destory_linklist(linkList *plist)
878 {
879 if (NULL == plist) {
880 return -1;
881 }
882
883 linknode *pnode = plist->_phead;
884 linknode *ptmp = NULL;
885 while (pnode != NULL) {
886 ptmp = pnode;
887 pnode = pnode->_next;
888 free_linknodedata(ptmp);
889 }
890
891 plist->_phead = NULL;
892 plist->_count = 0;
893
894 return 0;
895 }
896
linklist_size(linkList * plist)897 static int linklist_size(linkList *plist)
898 {
899 if (NULL == plist) {
900 return 0;
901 }
902
903 return plist->_count;
904 }
905
get_linknode(linkList * plist,int index)906 static linknode *get_linknode(linkList *plist, int index)
907 {
908 if (index < 0 || index >= plist->_count) {
909 return NULL;
910 }
911
912 int i = 0;
913 linknode *pnode = plist->_phead;
914 if (NULL == pnode) {
915 return NULL;
916 }
917 while ((i++) < index && NULL != pnode) {
918 pnode = pnode->_next;
919 }
920
921 return pnode;
922 }
923
linklist_append_last(linkList * plist,void * pdata)924 static int linklist_append_last(linkList *plist, void *pdata)
925 {
926 if (NULL == plist) {
927 return -1;
928 }
929
930 linknode *pnode = create_linknode(pdata);
931 if (NULL == pnode) {
932 return -1;
933 }
934
935 if (NULL == plist->_phead) {
936 plist->_phead = pnode;
937 plist->_count++;
938 } else {
939 linknode *plastnode = get_linknode(plist, plist->_count - 1);
940 if (NULL == plastnode) {
941 return -1;
942 }
943 plastnode->_next = pnode;
944 plist->_count++;
945 }
946
947 return 0;
948 }
949
linklist_delete(linkList * plist,int index)950 static int linklist_delete(linkList *plist, int index)
951 {
952 if (NULL == plist || NULL == plist->_phead || plist->_count <= 0) {
953 return -1;
954 }
955
956 if (index == 0) {
957 return linklist_delete_first(plist);
958 } else if (index == (plist->_count - 1)) {
959 return linklist_delete_last(plist);
960 } else {
961 linknode *pindex = get_linknode(plist, index);
962 if (NULL == pindex) {
963 return -1;
964 }
965 linknode *preindex = get_linknode(plist, index - 1);
966 if (NULL == preindex) {
967 return -1;
968 }
969
970 preindex->_next = pindex->_next;
971
972 free_linknodedata(pindex);
973 plist->_count--;
974 }
975
976 return 0;
977 }
978
linklist_delete_first(linkList * plist)979 static int linklist_delete_first(linkList *plist)
980 {
981 if (NULL == plist || NULL == plist->_phead || plist->_count <= 0) {
982 return -1;
983 }
984
985 linknode *phead = plist->_phead;
986 plist->_phead = plist->_phead->_next;
987
988 free_linknodedata(phead);
989 plist->_count--;
990
991 return 0;
992 }
993
linklist_delete_last(linkList * plist)994 static int linklist_delete_last(linkList *plist)
995 {
996 if (NULL == plist || NULL == plist->_phead || plist->_count <= 0) {
997 return -1;
998 }
999
1000 linknode *plastsecondnode = get_linknode(plist, plist->_count - 2);
1001 if (NULL != plastsecondnode) {
1002 linknode *plastnode = plastsecondnode->_next;
1003 plastsecondnode->_next = NULL;
1004
1005 free_linknodedata(plastnode);
1006 plist->_count--;
1007 } else {
1008 linknode *plastnode = get_linknode(plist, plist->_count - 1);
1009 plist->_phead = NULL;
1010 plist->_count = 0;
1011
1012 free_linknodedata(plastnode);
1013 }
1014
1015 return 0;
1016 }
1017