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