• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&params, 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