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