getaddrinfo.c revision 1.96.4.3 1 /* $NetBSD: getaddrinfo.c,v 1.96.4.3 2015/11/17 09:28:05 bouyer Exp $ */
2 /* $KAME: getaddrinfo.c,v 1.29 2000/08/31 17:26:57 itojun Exp $ */
3
4 /*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 /*
34 * Issues to be discussed:
35 * - Return values. There are nonstandard return values defined and used
36 * in the source code. This is because RFC2553 is silent about which error
37 * code must be returned for which situation.
38 * - IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2
39 * says to use inet_aton() to convert IPv4 numeric to binary (alows
40 * classful form as a result).
41 * current code - disallow classful form for IPv4 (due to use of inet_pton).
42 * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is
43 * invalid.
44 * current code - SEGV on freeaddrinfo(NULL)
45 * Note:
46 * - The code filters out AFs that are not supported by the kernel,
47 * when globbing NULL hostname (to loopback, or wildcard). Is it the right
48 * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG
49 * in ai_flags?
50 * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
51 * (1) what should we do against numeric hostname (2) what should we do
52 * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready?
53 * non-loopback address configured? global address configured?
54 */
55
56 #include <sys/cdefs.h>
57 #if defined(LIBC_SCCS) && !defined(lint)
58 __RCSID("$NetBSD: getaddrinfo.c,v 1.96.4.3 2015/11/17 09:28:05 bouyer Exp $");
59 #endif /* LIBC_SCCS and not lint */
60
61 #include "namespace.h"
62 #include <sys/types.h>
63 #include <sys/param.h>
64 #include <sys/socket.h>
65 #include <net/if.h>
66 #include <netinet/in.h>
67 #include <arpa/inet.h>
68 #include <arpa/nameser.h>
69 #include <assert.h>
70 #include <ctype.h>
71 #include <errno.h>
72 #include <netdb.h>
73 #include <resolv.h>
74 #include <stddef.h>
75 #include <stdio.h>
76 #include <stdlib.h>
77 #include <string.h>
78 #include <unistd.h>
79 #include <ifaddrs.h>
80
81 #include <syslog.h>
82 #include <stdarg.h>
83 #include <nsswitch.h>
84
85 #ifdef YP
86 #include <rpc/rpc.h>
87 #include <rpcsvc/yp_prot.h>
88 #include <rpcsvc/ypclnt.h>
89 #endif
90
91 #include "servent.h"
92
93 #ifdef __weak_alias
94 __weak_alias(getaddrinfo,_getaddrinfo)
95 __weak_alias(freeaddrinfo,_freeaddrinfo)
96 __weak_alias(gai_strerror,_gai_strerror)
97 #endif
98
99 #define SUCCESS 0
100 #define ANY 0
101 #define YES 1
102 #define NO 0
103
104 static const char in_addrany[] = { 0, 0, 0, 0 };
105 static const char in_loopback[] = { 127, 0, 0, 1 };
106 #ifdef INET6
107 static const char in6_addrany[] = {
108 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
109 };
110 static const char in6_loopback[] = {
111 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
112 };
113 #endif
114
115 static const struct afd {
116 int a_af;
117 int a_addrlen;
118 int a_socklen;
119 int a_off;
120 const char *a_addrany;
121 const char *a_loopback;
122 int a_scoped;
123 } afdl [] = {
124 #ifdef INET6
125 {PF_INET6, sizeof(struct in6_addr),
126 sizeof(struct sockaddr_in6),
127 offsetof(struct sockaddr_in6, sin6_addr),
128 in6_addrany, in6_loopback, 1},
129 #endif
130 {PF_INET, sizeof(struct in_addr),
131 sizeof(struct sockaddr_in),
132 offsetof(struct sockaddr_in, sin_addr),
133 in_addrany, in_loopback, 0},
134 {0, 0, 0, 0, NULL, NULL, 0},
135 };
136
137 struct explore {
138 int e_af;
139 int e_socktype;
140 int e_protocol;
141 const char *e_protostr;
142 int e_wild;
143 #define WILD_AF(ex) ((ex)->e_wild & 0x01)
144 #define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
145 #define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
146 };
147
148 static const struct explore explore[] = {
149 #if 0
150 { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
151 #endif
152 #ifdef INET6
153 { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
154 { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
155 { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
156 #endif
157 { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
158 { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
159 { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
160 { PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
161 { PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
162 { PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 },
163 { -1, 0, 0, NULL, 0 },
164 };
165
166 #ifdef INET6
167 #define PTON_MAX 16
168 #else
169 #define PTON_MAX 4
170 #endif
171
172 static const ns_src default_dns_files[] = {
173 { NSSRC_FILES, NS_SUCCESS },
174 { NSSRC_DNS, NS_SUCCESS },
175 { 0, 0 }
176 };
177
178 #define MAXPACKET (64*1024)
179
180 typedef union {
181 HEADER hdr;
182 u_char buf[MAXPACKET];
183 } querybuf;
184
185 struct res_target {
186 struct res_target *next;
187 const char *name; /* domain name */
188 int qclass, qtype; /* class and type of query */
189 u_char *answer; /* buffer to put answer */
190 int anslen; /* size of answer buffer */
191 int n; /* result length */
192 };
193
194 static int str2number(const char *);
195 static int explore_fqdn(const struct addrinfo *, const char *,
196 const char *, struct addrinfo **, struct servent_data *);
197 static int explore_null(const struct addrinfo *,
198 const char *, struct addrinfo **, struct servent_data *);
199 static int explore_numeric(const struct addrinfo *, const char *,
200 const char *, struct addrinfo **, const char *, struct servent_data *);
201 static int explore_numeric_scope(const struct addrinfo *, const char *,
202 const char *, struct addrinfo **, struct servent_data *);
203 static int get_canonname(const struct addrinfo *,
204 struct addrinfo *, const char *);
205 static struct addrinfo *get_ai(const struct addrinfo *,
206 const struct afd *, const char *);
207 static int get_portmatch(const struct addrinfo *, const char *,
208 struct servent_data *);
209 static int get_port(const struct addrinfo *, const char *, int,
210 struct servent_data *);
211 static const struct afd *find_afd(int);
212 static int addrconfig(uint64_t *);
213 #ifdef INET6
214 static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *);
215 #endif
216
217 static struct addrinfo *getanswer(res_state, const querybuf *, int,
218 const char *, int, const struct addrinfo *);
219 static void aisort(struct addrinfo *s, res_state res);
220 static int _dns_getaddrinfo(void *, void *, va_list);
221 static void _sethtent(FILE **);
222 static void _endhtent(FILE **);
223 static struct addrinfo *_gethtent(FILE **, const char *,
224 const struct addrinfo *);
225 static int _files_getaddrinfo(void *, void *, va_list);
226 #ifdef YP
227 static struct addrinfo *_yphostent(char *, const struct addrinfo *);
228 static int _yp_getaddrinfo(void *, void *, va_list);
229 #endif
230
231 static int res_queryN(const char *, struct res_target *, res_state);
232 static int res_searchN(const char *, struct res_target *, res_state);
233 static int res_querydomainN(const char *, const char *,
234 struct res_target *, res_state);
235
236 static const char * const ai_errlist[] = {
237 "Success",
238 "Address family for hostname not supported", /* EAI_ADDRFAMILY */
239 "Temporary failure in name resolution", /* EAI_AGAIN */
240 "Invalid value for ai_flags", /* EAI_BADFLAGS */
241 "Non-recoverable failure in name resolution", /* EAI_FAIL */
242 "ai_family not supported", /* EAI_FAMILY */
243 "Memory allocation failure", /* EAI_MEMORY */
244 "No address associated with hostname", /* EAI_NODATA */
245 "hostname nor servname provided, or not known", /* EAI_NONAME */
246 "servname not supported for ai_socktype", /* EAI_SERVICE */
247 "ai_socktype not supported", /* EAI_SOCKTYPE */
248 "System error returned in errno", /* EAI_SYSTEM */
249 "Invalid value for hints", /* EAI_BADHINTS */
250 "Resolved protocol is unknown", /* EAI_PROTOCOL */
251 "Argument buffer overflow", /* EAI_OVERFLOW */
252 "Unknown error", /* EAI_MAX */
253 };
254
255 /* XXX macros that make external reference is BAD. */
256
257 #define GET_AI(ai, afd, addr) \
258 do { \
259 /* external reference: pai, error, and label free */ \
260 (ai) = get_ai(pai, (afd), (addr)); \
261 if ((ai) == NULL) { \
262 error = EAI_MEMORY; \
263 goto free; \
264 } \
265 } while (/*CONSTCOND*/0)
266
267 #define GET_PORT(ai, serv, svd) \
268 do { \
269 /* external reference: error and label free */ \
270 error = get_port((ai), (serv), 0, (svd)); \
271 if (error != 0) \
272 goto free; \
273 } while (/*CONSTCOND*/0)
274
275 #define GET_CANONNAME(ai, str) \
276 do { \
277 /* external reference: pai, error and label free */ \
278 error = get_canonname(pai, (ai), (str)); \
279 if (error != 0) \
280 goto free; \
281 } while (/*CONSTCOND*/0)
282
283 #define ERR(err) \
284 do { \
285 /* external reference: error, and label bad */ \
286 error = (err); \
287 goto bad; \
288 /*NOTREACHED*/ \
289 } while (/*CONSTCOND*/0)
290
291 #define MATCH_FAMILY(x, y, w) \
292 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || \
293 (y) == PF_UNSPEC)))
294 #define MATCH(x, y, w) \
295 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
296
297 const char *
298 gai_strerror(int ecode)
299 {
300 if (ecode < 0 || ecode > EAI_MAX)
301 ecode = EAI_MAX;
302 return ai_errlist[ecode];
303 }
304
305 void
306 freeaddrinfo(struct addrinfo *ai)
307 {
308 struct addrinfo *next;
309
310 _DIAGASSERT(ai != NULL);
311
312 do {
313 next = ai->ai_next;
314 if (ai->ai_canonname)
315 free(ai->ai_canonname);
316 /* no need to free(ai->ai_addr) */
317 free(ai);
318 ai = next;
319 } while (ai);
320 }
321
322 static int
323 str2number(const char *p)
324 {
325 char *ep;
326 unsigned long v;
327
328 _DIAGASSERT(p != NULL);
329
330 if (*p == '\0')
331 return -1;
332 ep = NULL;
333 errno = 0;
334 v = strtoul(p, &ep, 10);
335 if (errno == 0 && ep && *ep == '\0' && v <= UINT_MAX)
336 return v;
337 else
338 return -1;
339 }
340
341 int
342 getaddrinfo(const char *hostname, const char *servname,
343 const struct addrinfo *hints, struct addrinfo **res)
344 {
345 struct addrinfo sentinel;
346 struct addrinfo *cur;
347 int error = 0;
348 struct addrinfo ai;
349 struct addrinfo ai0;
350 struct addrinfo *pai;
351 const struct explore *ex;
352 struct servent_data svd;
353 uint64_t mask = (uint64_t)~0ULL;
354
355 /* hostname is allowed to be NULL */
356 /* servname is allowed to be NULL */
357 /* hints is allowed to be NULL */
358 _DIAGASSERT(res != NULL);
359
360 (void)memset(&svd, 0, sizeof(svd));
361 memset(&sentinel, 0, sizeof(sentinel));
362 cur = &sentinel;
363 memset(&ai, 0, sizeof(ai));
364 pai = &ai;
365 pai->ai_flags = 0;
366 pai->ai_family = PF_UNSPEC;
367 pai->ai_socktype = ANY;
368 pai->ai_protocol = ANY;
369 pai->ai_addrlen = 0;
370 pai->ai_canonname = NULL;
371 pai->ai_addr = NULL;
372 pai->ai_next = NULL;
373
374 if (hostname == NULL && servname == NULL)
375 return EAI_NONAME;
376 if (hints) {
377 /* error check for hints */
378 if (hints->ai_addrlen || hints->ai_canonname ||
379 hints->ai_addr || hints->ai_next)
380 ERR(EAI_BADHINTS); /* xxx */
381 if (hints->ai_flags & ~AI_MASK)
382 ERR(EAI_BADFLAGS);
383 switch (hints->ai_family) {
384 case PF_UNSPEC:
385 case PF_INET:
386 #ifdef INET6
387 case PF_INET6:
388 #endif
389 break;
390 default:
391 ERR(EAI_FAMILY);
392 }
393 memcpy(pai, hints, sizeof(*pai));
394
395 /*
396 * if both socktype/protocol are specified, check if they
397 * are meaningful combination.
398 */
399 if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
400 for (ex = explore; ex->e_af >= 0; ex++) {
401 if (pai->ai_family != ex->e_af)
402 continue;
403 if (ex->e_socktype == ANY)
404 continue;
405 if (ex->e_protocol == ANY)
406 continue;
407 if (pai->ai_socktype == ex->e_socktype
408 && pai->ai_protocol != ex->e_protocol) {
409 ERR(EAI_BADHINTS);
410 }
411 }
412 }
413 }
414
415 if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && addrconfig(&mask) == -1)
416 ERR(EAI_FAIL);
417
418 /*
419 * check for special cases. (1) numeric servname is disallowed if
420 * socktype/protocol are left unspecified. (2) servname is disallowed
421 * for raw and other inet{,6} sockets.
422 */
423 if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
424 #ifdef PF_INET6
425 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
426 #endif
427 ) {
428 ai0 = *pai; /* backup *pai */
429
430 if (pai->ai_family == PF_UNSPEC) {
431 #ifdef PF_INET6
432 pai->ai_family = PF_INET6;
433 #else
434 pai->ai_family = PF_INET;
435 #endif
436 }
437 error = get_portmatch(pai, servname, &svd);
438 if (error)
439 ERR(error);
440
441 *pai = ai0;
442 }
443
444 ai0 = *pai;
445
446 /* NULL hostname, or numeric hostname */
447 for (ex = explore; ex->e_af >= 0; ex++) {
448 *pai = ai0;
449
450 /* ADDRCONFIG check */
451 if ((((uint64_t)1 << ex->e_af) & mask) == 0)
452 continue;
453
454 /* PF_UNSPEC entries are prepared for DNS queries only */
455 if (ex->e_af == PF_UNSPEC)
456 continue;
457
458 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
459 continue;
460 if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
461 continue;
462 if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
463 continue;
464 if (pai->ai_family == PF_UNSPEC)
465 pai->ai_family = ex->e_af;
466 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
467 pai->ai_socktype = ex->e_socktype;
468 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
469 pai->ai_protocol = ex->e_protocol;
470
471 if (hostname == NULL)
472 error = explore_null(pai, servname, &cur->ai_next,
473 &svd);
474 else
475 error = explore_numeric_scope(pai, hostname, servname,
476 &cur->ai_next, &svd);
477
478 if (error)
479 goto free;
480
481 while (cur->ai_next)
482 cur = cur->ai_next;
483 }
484
485 /*
486 * XXX
487 * If numeric representation of AF1 can be interpreted as FQDN
488 * representation of AF2, we need to think again about the code below.
489 */
490 if (sentinel.ai_next)
491 goto good;
492
493 if (hostname == NULL)
494 ERR(EAI_NODATA);
495 if (pai->ai_flags & AI_NUMERICHOST)
496 ERR(EAI_NONAME);
497
498 /*
499 * hostname as alphabetical name.
500 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
501 * outer loop by AFs.
502 */
503 for (ex = explore; ex->e_af >= 0; ex++) {
504 *pai = ai0;
505
506
507 /* ADDRCONFIG check */
508 /* PF_UNSPEC entries are prepared for DNS queries only */
509 if (ex->e_af != PF_UNSPEC &&
510 (((uint64_t)1 << ex->e_af) & mask) == 0)
511 continue;
512
513 /* require exact match for family field */
514 if (pai->ai_family != ex->e_af)
515 continue;
516
517 if (!MATCH(pai->ai_socktype, ex->e_socktype,
518 WILD_SOCKTYPE(ex))) {
519 continue;
520 }
521 if (!MATCH(pai->ai_protocol, ex->e_protocol,
522 WILD_PROTOCOL(ex))) {
523 continue;
524 }
525
526 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
527 pai->ai_socktype = ex->e_socktype;
528 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
529 pai->ai_protocol = ex->e_protocol;
530
531 error = explore_fqdn(pai, hostname, servname, &cur->ai_next,
532 &svd);
533
534 while (cur && cur->ai_next)
535 cur = cur->ai_next;
536 }
537
538 /* XXX */
539 if (sentinel.ai_next)
540 error = 0;
541
542 if (error)
543 goto free;
544
545 if (sentinel.ai_next) {
546 good:
547 endservent_r(&svd);
548 *res = sentinel.ai_next;
549 return SUCCESS;
550 } else
551 error = EAI_FAIL;
552 free:
553 bad:
554 endservent_r(&svd);
555 if (sentinel.ai_next)
556 freeaddrinfo(sentinel.ai_next);
557 *res = NULL;
558 return error;
559 }
560
561 /*
562 * FQDN hostname, DNS lookup
563 */
564 static int
565 explore_fqdn(const struct addrinfo *pai, const char *hostname,
566 const char *servname, struct addrinfo **res, struct servent_data *svd)
567 {
568 struct addrinfo *result;
569 struct addrinfo *cur;
570 int error = 0;
571 static const ns_dtab dtab[] = {
572 NS_FILES_CB(_files_getaddrinfo, NULL)
573 { NSSRC_DNS, _dns_getaddrinfo, NULL }, /* force -DHESIOD */
574 NS_NIS_CB(_yp_getaddrinfo, NULL)
575 NS_NULL_CB
576 };
577
578 _DIAGASSERT(pai != NULL);
579 /* hostname may be NULL */
580 /* servname may be NULL */
581 _DIAGASSERT(res != NULL);
582
583 result = NULL;
584
585 /*
586 * if the servname does not match socktype/protocol, ignore it.
587 */
588 if (get_portmatch(pai, servname, svd) != 0)
589 return 0;
590
591 switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo",
592 default_dns_files, hostname, pai)) {
593 case NS_TRYAGAIN:
594 error = EAI_AGAIN;
595 goto free;
596 case NS_UNAVAIL:
597 error = EAI_FAIL;
598 goto free;
599 case NS_NOTFOUND:
600 error = EAI_NODATA;
601 goto free;
602 case NS_SUCCESS:
603 error = 0;
604 for (cur = result; cur; cur = cur->ai_next) {
605 GET_PORT(cur, servname, svd);
606 /* canonname should be filled already */
607 }
608 break;
609 }
610
611 *res = result;
612
613 return 0;
614
615 free:
616 if (result)
617 freeaddrinfo(result);
618 return error;
619 }
620
621 /*
622 * hostname == NULL.
623 * passive socket -> anyaddr (0.0.0.0 or ::)
624 * non-passive socket -> localhost (127.0.0.1 or ::1)
625 */
626 static int
627 explore_null(const struct addrinfo *pai, const char *servname,
628 struct addrinfo **res, struct servent_data *svd)
629 {
630 int s;
631 const struct afd *afd;
632 struct addrinfo *cur;
633 struct addrinfo sentinel;
634 int error;
635
636 _DIAGASSERT(pai != NULL);
637 /* servname may be NULL */
638 _DIAGASSERT(res != NULL);
639
640 *res = NULL;
641 sentinel.ai_next = NULL;
642 cur = &sentinel;
643
644 /*
645 * filter out AFs that are not supported by the kernel
646 * XXX errno?
647 */
648 s = socket(pai->ai_family, SOCK_DGRAM, 0);
649 if (s < 0) {
650 if (errno != EMFILE)
651 return 0;
652 } else
653 close(s);
654
655 /*
656 * if the servname does not match socktype/protocol, ignore it.
657 */
658 if (get_portmatch(pai, servname, svd) != 0)
659 return 0;
660
661 afd = find_afd(pai->ai_family);
662 if (afd == NULL)
663 return 0;
664
665 if (pai->ai_flags & AI_PASSIVE) {
666 GET_AI(cur->ai_next, afd, afd->a_addrany);
667 /* xxx meaningless?
668 * GET_CANONNAME(cur->ai_next, "anyaddr");
669 */
670 GET_PORT(cur->ai_next, servname, svd);
671 } else {
672 GET_AI(cur->ai_next, afd, afd->a_loopback);
673 /* xxx meaningless?
674 * GET_CANONNAME(cur->ai_next, "localhost");
675 */
676 GET_PORT(cur->ai_next, servname, svd);
677 }
678 cur = cur->ai_next;
679
680 *res = sentinel.ai_next;
681 return 0;
682
683 free:
684 if (sentinel.ai_next)
685 freeaddrinfo(sentinel.ai_next);
686 return error;
687 }
688
689 /*
690 * numeric hostname
691 */
692 static int
693 explore_numeric(const struct addrinfo *pai, const char *hostname,
694 const char *servname, struct addrinfo **res, const char *canonname,
695 struct servent_data *svd)
696 {
697 const struct afd *afd;
698 struct addrinfo *cur;
699 struct addrinfo sentinel;
700 int error;
701 char pton[PTON_MAX];
702
703 _DIAGASSERT(pai != NULL);
704 /* hostname may be NULL */
705 /* servname may be NULL */
706 _DIAGASSERT(res != NULL);
707
708 *res = NULL;
709 sentinel.ai_next = NULL;
710 cur = &sentinel;
711
712 /*
713 * if the servname does not match socktype/protocol, ignore it.
714 */
715 if (get_portmatch(pai, servname, svd) != 0)
716 return 0;
717
718 afd = find_afd(pai->ai_family);
719 if (afd == NULL)
720 return 0;
721
722 switch (afd->a_af) {
723 #if 0 /*X/Open spec*/
724 case AF_INET:
725 if (inet_aton(hostname, (struct in_addr *)pton) == 1) {
726 if (pai->ai_family == afd->a_af ||
727 pai->ai_family == PF_UNSPEC /*?*/) {
728 GET_AI(cur->ai_next, afd, pton);
729 GET_PORT(cur->ai_next, servname, svd);
730 if ((pai->ai_flags & AI_CANONNAME)) {
731 /*
732 * Set the numeric address itself as
733 * the canonical name, based on a
734 * clarification in rfc2553bis-03.
735 */
736 GET_CANONNAME(cur->ai_next, canonname);
737 }
738 while (cur && cur->ai_next)
739 cur = cur->ai_next;
740 } else
741 ERR(EAI_FAMILY); /*xxx*/
742 }
743 break;
744 #endif
745 default:
746 if (inet_pton(afd->a_af, hostname, pton) == 1) {
747 if (pai->ai_family == afd->a_af ||
748 pai->ai_family == PF_UNSPEC /*?*/) {
749 GET_AI(cur->ai_next, afd, pton);
750 GET_PORT(cur->ai_next, servname, svd);
751 if ((pai->ai_flags & AI_CANONNAME)) {
752 /*
753 * Set the numeric address itself as
754 * the canonical name, based on a
755 * clarification in rfc2553bis-03.
756 */
757 GET_CANONNAME(cur->ai_next, canonname);
758 }
759 while (cur->ai_next)
760 cur = cur->ai_next;
761 } else
762 ERR(EAI_FAMILY); /*xxx*/
763 }
764 break;
765 }
766
767 *res = sentinel.ai_next;
768 return 0;
769
770 free:
771 bad:
772 if (sentinel.ai_next)
773 freeaddrinfo(sentinel.ai_next);
774 return error;
775 }
776
777 /*
778 * numeric hostname with scope
779 */
780 static int
781 explore_numeric_scope(const struct addrinfo *pai, const char *hostname,
782 const char *servname, struct addrinfo **res, struct servent_data *svd)
783 {
784 #if !defined(SCOPE_DELIMITER) || !defined(INET6)
785 return explore_numeric(pai, hostname, servname, res, hostname, svd);
786 #else
787 const struct afd *afd;
788 struct addrinfo *cur;
789 int error;
790 char *cp, *hostname2 = NULL, *scope, *addr;
791 struct sockaddr_in6 *sin6;
792
793 _DIAGASSERT(pai != NULL);
794 /* hostname may be NULL */
795 /* servname may be NULL */
796 _DIAGASSERT(res != NULL);
797
798 /*
799 * if the servname does not match socktype/protocol, ignore it.
800 */
801 if (get_portmatch(pai, servname, svd) != 0)
802 return 0;
803
804 afd = find_afd(pai->ai_family);
805 if (afd == NULL)
806 return 0;
807
808 if (!afd->a_scoped)
809 return explore_numeric(pai, hostname, servname, res, hostname,
810 svd);
811
812 cp = strchr(hostname, SCOPE_DELIMITER);
813 if (cp == NULL)
814 return explore_numeric(pai, hostname, servname, res, hostname,
815 svd);
816
817 /*
818 * Handle special case of <scoped_address><delimiter><scope id>
819 */
820 hostname2 = strdup(hostname);
821 if (hostname2 == NULL)
822 return EAI_MEMORY;
823 /* terminate at the delimiter */
824 hostname2[cp - hostname] = '\0';
825 addr = hostname2;
826 scope = cp + 1;
827
828 error = explore_numeric(pai, addr, servname, res, hostname, svd);
829 if (error == 0) {
830 u_int32_t scopeid;
831
832 for (cur = *res; cur; cur = cur->ai_next) {
833 if (cur->ai_family != AF_INET6)
834 continue;
835 sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
836 if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) {
837 free(hostname2);
838 return(EAI_NODATA); /* XXX: is return OK? */
839 }
840 sin6->sin6_scope_id = scopeid;
841 }
842 }
843
844 free(hostname2);
845
846 return error;
847 #endif
848 }
849
850 static int
851 get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str)
852 {
853
854 _DIAGASSERT(pai != NULL);
855 _DIAGASSERT(ai != NULL);
856 _DIAGASSERT(str != NULL);
857
858 if ((pai->ai_flags & AI_CANONNAME) != 0) {
859 ai->ai_canonname = strdup(str);
860 if (ai->ai_canonname == NULL)
861 return EAI_MEMORY;
862 }
863 return 0;
864 }
865
866 struct addrinfo *
867 allocaddrinfo(socklen_t addrlen)
868 {
869 struct addrinfo *ai;
870
871 ai = calloc(sizeof(struct addrinfo) + addrlen, 1);
872 if (ai) {
873 ai->ai_addr = (void *)(ai+1);
874 ai->ai_addrlen = ai->ai_addr->sa_len = addrlen;
875 }
876
877 return ai;
878 }
879
880 static struct addrinfo *
881 get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
882 {
883 char *p;
884 struct addrinfo *ai;
885 struct sockaddr *save;
886
887 _DIAGASSERT(pai != NULL);
888 _DIAGASSERT(afd != NULL);
889 _DIAGASSERT(addr != NULL);
890
891 ai = allocaddrinfo((socklen_t)afd->a_socklen);
892 if (ai == NULL)
893 return NULL;
894
895 save = ai->ai_addr;
896 memcpy(ai, pai, sizeof(struct addrinfo));
897
898 /* since we just overwrote all of ai, we have
899 to restore ai_addr and ai_addrlen */
900 ai->ai_addr = save;
901 ai->ai_addrlen = (socklen_t)afd->a_socklen;
902
903 ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
904 p = (char *)(void *)(ai->ai_addr);
905 memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
906 return ai;
907 }
908
909 static int
910 get_portmatch(const struct addrinfo *ai, const char *servname,
911 struct servent_data *svd)
912 {
913
914 _DIAGASSERT(ai != NULL);
915 /* servname may be NULL */
916
917 return get_port(ai, servname, 1, svd);
918 }
919
920 static int
921 get_port(const struct addrinfo *ai, const char *servname, int matchonly,
922 struct servent_data *svd)
923 {
924 const char *proto;
925 struct servent *sp;
926 int port;
927 int allownumeric;
928
929 _DIAGASSERT(ai != NULL);
930 /* servname may be NULL */
931
932 if (servname == NULL)
933 return 0;
934 switch (ai->ai_family) {
935 case AF_INET:
936 #ifdef AF_INET6
937 case AF_INET6:
938 #endif
939 break;
940 default:
941 return 0;
942 }
943
944 switch (ai->ai_socktype) {
945 case SOCK_RAW:
946 return EAI_SERVICE;
947 case SOCK_DGRAM:
948 case SOCK_STREAM:
949 allownumeric = 1;
950 break;
951 case ANY:
952 /*
953 * This was 0. It is now 1 so that queries specifying
954 * a NULL hint, or hint without socktype (but, hopefully,
955 * with protocol) and numeric address actually work.
956 */
957 allownumeric = 1;
958 break;
959 default:
960 return EAI_SOCKTYPE;
961 }
962
963 port = str2number(servname);
964 if (port >= 0) {
965 if (!allownumeric)
966 return EAI_SERVICE;
967 if (port < 0 || port > 65535)
968 return EAI_SERVICE;
969 port = htons(port);
970 } else {
971 struct servent sv;
972 if (ai->ai_flags & AI_NUMERICSERV)
973 return EAI_NONAME;
974
975 switch (ai->ai_socktype) {
976 case SOCK_DGRAM:
977 proto = "udp";
978 break;
979 case SOCK_STREAM:
980 proto = "tcp";
981 break;
982 default:
983 proto = NULL;
984 break;
985 }
986
987 sp = getservbyname_r(servname, proto, &sv, svd);
988 if (sp == NULL)
989 return EAI_SERVICE;
990 port = sp->s_port;
991 }
992
993 if (!matchonly) {
994 switch (ai->ai_family) {
995 case AF_INET:
996 ((struct sockaddr_in *)(void *)
997 ai->ai_addr)->sin_port = port;
998 break;
999 #ifdef INET6
1000 case AF_INET6:
1001 ((struct sockaddr_in6 *)(void *)
1002 ai->ai_addr)->sin6_port = port;
1003 break;
1004 #endif
1005 }
1006 }
1007
1008 return 0;
1009 }
1010
1011 static const struct afd *
1012 find_afd(int af)
1013 {
1014 const struct afd *afd;
1015
1016 if (af == PF_UNSPEC)
1017 return NULL;
1018 for (afd = afdl; afd->a_af; afd++) {
1019 if (afd->a_af == af)
1020 return afd;
1021 }
1022 return NULL;
1023 }
1024
1025 /*
1026 * AI_ADDRCONFIG check: Build a mask containing a bit set for each address
1027 * family configured in the system.
1028 *
1029 */
1030 static int
1031 addrconfig(uint64_t *mask)
1032 {
1033 struct ifaddrs *ifaddrs, *ifa;
1034
1035 if (getifaddrs(&ifaddrs) == -1)
1036 return -1;
1037
1038 *mask = 0;
1039 for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next)
1040 if (ifa->ifa_addr && (ifa->ifa_flags & IFF_UP)) {
1041 _DIAGASSERT(ifa->ifa_addr->sa_family < 64);
1042 *mask |= (uint64_t)1 << ifa->ifa_addr->sa_family;
1043 }
1044
1045 freeifaddrs(ifaddrs);
1046 return 0;
1047 }
1048
1049 #ifdef INET6
1050 /* convert a string to a scope identifier. XXX: IPv6 specific */
1051 static int
1052 ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid)
1053 {
1054 u_long lscopeid;
1055 struct in6_addr *a6;
1056 char *ep;
1057
1058 _DIAGASSERT(scope != NULL);
1059 _DIAGASSERT(sin6 != NULL);
1060 _DIAGASSERT(scopeid != NULL);
1061
1062 a6 = &sin6->sin6_addr;
1063
1064 /* empty scopeid portion is invalid */
1065 if (*scope == '\0')
1066 return -1;
1067
1068 if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) {
1069 /*
1070 * We currently assume a one-to-one mapping between links
1071 * and interfaces, so we simply use interface indices for
1072 * like-local scopes.
1073 */
1074 *scopeid = if_nametoindex(scope);
1075 if (*scopeid == 0)
1076 goto trynumeric;
1077 return 0;
1078 }
1079
1080 /* still unclear about literal, allow numeric only - placeholder */
1081 if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
1082 goto trynumeric;
1083 if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
1084 goto trynumeric;
1085 else
1086 goto trynumeric; /* global */
1087
1088 /* try to convert to a numeric id as a last resort */
1089 trynumeric:
1090 errno = 0;
1091 lscopeid = strtoul(scope, &ep, 10);
1092 *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL);
1093 if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid)
1094 return 0;
1095 else
1096 return -1;
1097 }
1098 #endif
1099
1100 /* code duplicate with gethnamaddr.c */
1101
1102 static const char AskedForGot[] =
1103 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
1104
1105 #define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0U || \
1106 (ok)(nm) != 0)
1107
1108 static struct addrinfo *
1109 getanswer(res_state res, const querybuf *answer, int anslen, const char *qname,
1110 int qtype, const struct addrinfo *pai)
1111 {
1112 struct addrinfo sentinel, *cur;
1113 struct addrinfo ai;
1114 const struct afd *afd;
1115 char *canonname;
1116 const HEADER *hp;
1117 const u_char *cp;
1118 int n;
1119 const u_char *eom;
1120 char *bp, *ep;
1121 int type, class, ancount, qdcount;
1122 int haveanswer, had_error;
1123 char tbuf[MAXDNAME];
1124 int (*name_ok) (const char *);
1125 char hostbuf[8*1024];
1126
1127 _DIAGASSERT(answer != NULL);
1128 _DIAGASSERT(qname != NULL);
1129 _DIAGASSERT(pai != NULL);
1130 _DIAGASSERT(res != NULL);
1131
1132 memset(&sentinel, 0, sizeof(sentinel));
1133 cur = &sentinel;
1134
1135 canonname = NULL;
1136 eom = answer->buf + anslen;
1137 switch (qtype) {
1138 case T_A:
1139 case T_AAAA:
1140 case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/
1141 name_ok = res_hnok;
1142 break;
1143 default:
1144 return NULL; /* XXX should be abort(); */
1145 }
1146 /*
1147 * find first satisfactory answer
1148 */
1149 hp = &answer->hdr;
1150 ancount = ntohs(hp->ancount);
1151 qdcount = ntohs(hp->qdcount);
1152 bp = hostbuf;
1153 ep = hostbuf + sizeof hostbuf;
1154 cp = answer->buf + HFIXEDSZ;
1155 if (qdcount != 1) {
1156 h_errno = NO_RECOVERY;
1157 return (NULL);
1158 }
1159 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1160 if ((n < 0) || !maybe_ok(res, bp, name_ok)) {
1161 h_errno = NO_RECOVERY;
1162 return (NULL);
1163 }
1164 cp += n + QFIXEDSZ;
1165 if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
1166 /* res_send() has already verified that the query name is the
1167 * same as the one we sent; this just gets the expanded name
1168 * (i.e., with the succeeding search-domain tacked on).
1169 */
1170 n = strlen(bp) + 1; /* for the \0 */
1171 if (n >= MAXHOSTNAMELEN) {
1172 h_errno = NO_RECOVERY;
1173 return (NULL);
1174 }
1175 canonname = bp;
1176 bp += n;
1177 /* The qname can be abbreviated, but h_name is now absolute. */
1178 qname = canonname;
1179 }
1180 haveanswer = 0;
1181 had_error = 0;
1182 while (ancount-- > 0 && cp < eom && !had_error) {
1183 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1184 if ((n < 0) || !maybe_ok(res, bp, name_ok)) {
1185 had_error++;
1186 continue;
1187 }
1188 cp += n; /* name */
1189 type = _getshort(cp);
1190 cp += INT16SZ; /* type */
1191 class = _getshort(cp);
1192 cp += INT16SZ + INT32SZ; /* class, TTL */
1193 n = _getshort(cp);
1194 cp += INT16SZ; /* len */
1195 if (class != C_IN) {
1196 /* XXX - debug? syslog? */
1197 cp += n;
1198 continue; /* XXX - had_error++ ? */
1199 }
1200 if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
1201 type == T_CNAME) {
1202 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
1203 if ((n < 0) || !maybe_ok(res, tbuf, name_ok)) {
1204 had_error++;
1205 continue;
1206 }
1207 cp += n;
1208 /* Get canonical name. */
1209 n = strlen(tbuf) + 1; /* for the \0 */
1210 if (n > ep - bp || n >= MAXHOSTNAMELEN) {
1211 had_error++;
1212 continue;
1213 }
1214 strlcpy(bp, tbuf, (size_t)(ep - bp));
1215 canonname = bp;
1216 bp += n;
1217 continue;
1218 }
1219 if (qtype == T_ANY) {
1220 if (!(type == T_A || type == T_AAAA)) {
1221 cp += n;
1222 continue;
1223 }
1224 } else if (type != qtype) {
1225 if (type != T_KEY && type != T_SIG) {
1226 struct syslog_data sd = SYSLOG_DATA_INIT;
1227 syslog_r(LOG_NOTICE|LOG_AUTH, &sd,
1228 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
1229 qname, p_class(C_IN), p_type(qtype),
1230 p_type(type));
1231 }
1232 cp += n;
1233 continue; /* XXX - had_error++ ? */
1234 }
1235 switch (type) {
1236 case T_A:
1237 case T_AAAA:
1238 if (strcasecmp(canonname, bp) != 0) {
1239 struct syslog_data sd = SYSLOG_DATA_INIT;
1240 syslog_r(LOG_NOTICE|LOG_AUTH, &sd,
1241 AskedForGot, canonname, bp);
1242 cp += n;
1243 continue; /* XXX - had_error++ ? */
1244 }
1245 if (type == T_A && n != INADDRSZ) {
1246 cp += n;
1247 continue;
1248 }
1249 if (type == T_AAAA && n != IN6ADDRSZ) {
1250 cp += n;
1251 continue;
1252 }
1253 if (type == T_AAAA) {
1254 struct in6_addr in6;
1255 memcpy(&in6, cp, IN6ADDRSZ);
1256 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
1257 cp += n;
1258 continue;
1259 }
1260 }
1261 if (!haveanswer) {
1262 int nn;
1263
1264 canonname = bp;
1265 nn = strlen(bp) + 1; /* for the \0 */
1266 bp += nn;
1267 }
1268
1269 /* don't overwrite pai */
1270 ai = *pai;
1271 ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;
1272 afd = find_afd(ai.ai_family);
1273 if (afd == NULL) {
1274 cp += n;
1275 continue;
1276 }
1277 cur->ai_next = get_ai(&ai, afd, (const char *)cp);
1278 if (cur->ai_next == NULL)
1279 had_error++;
1280 while (cur && cur->ai_next)
1281 cur = cur->ai_next;
1282 cp += n;
1283 break;
1284 default:
1285 abort();
1286 }
1287 if (!had_error)
1288 haveanswer++;
1289 }
1290 if (haveanswer) {
1291 if (!canonname)
1292 (void)get_canonname(pai, sentinel.ai_next, qname);
1293 else
1294 (void)get_canonname(pai, sentinel.ai_next, canonname);
1295 h_errno = NETDB_SUCCESS;
1296 return sentinel.ai_next;
1297 }
1298
1299 h_errno = NO_RECOVERY;
1300 return NULL;
1301 }
1302
1303 #define SORTEDADDR(p) (((struct sockaddr_in *)(void *)(p->ai_next->ai_addr))->sin_addr.s_addr)
1304 #define SORTMATCH(p, s) ((SORTEDADDR(p) & (s).mask) == (s).addr.s_addr)
1305
1306 static void
1307 aisort(struct addrinfo *s, res_state res)
1308 {
1309 struct addrinfo head, *t, *p;
1310 int i;
1311
1312 head.ai_next = NULL;
1313 t = &head;
1314
1315 for (i = 0; i < res->nsort; i++) {
1316 p = s;
1317 while (p->ai_next) {
1318 if ((p->ai_next->ai_family != AF_INET)
1319 || SORTMATCH(p, res->sort_list[i])) {
1320 t->ai_next = p->ai_next;
1321 t = t->ai_next;
1322 p->ai_next = p->ai_next->ai_next;
1323 } else {
1324 p = p->ai_next;
1325 }
1326 }
1327 }
1328
1329 /* add rest of list and reset s to the new list*/
1330 t->ai_next = s->ai_next;
1331 s->ai_next = head.ai_next;
1332 }
1333
1334 /*ARGSUSED*/
1335 static int
1336 _dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
1337 {
1338 struct addrinfo *ai;
1339 querybuf *buf, *buf2;
1340 const char *name;
1341 const struct addrinfo *pai;
1342 struct addrinfo sentinel, *cur;
1343 struct res_target q, q2;
1344 res_state res;
1345
1346 name = va_arg(ap, char *);
1347 pai = va_arg(ap, const struct addrinfo *);
1348
1349 memset(&q, 0, sizeof(q));
1350 memset(&q2, 0, sizeof(q2));
1351 memset(&sentinel, 0, sizeof(sentinel));
1352 cur = &sentinel;
1353
1354 buf = malloc(sizeof(*buf));
1355 if (buf == NULL) {
1356 h_errno = NETDB_INTERNAL;
1357 return NS_NOTFOUND;
1358 }
1359 buf2 = malloc(sizeof(*buf2));
1360 if (buf2 == NULL) {
1361 free(buf);
1362 h_errno = NETDB_INTERNAL;
1363 return NS_NOTFOUND;
1364 }
1365
1366 switch (pai->ai_family) {
1367 case AF_UNSPEC:
1368 /* prefer IPv6 */
1369 q.name = name;
1370 q.qclass = C_IN;
1371 q.qtype = T_AAAA;
1372 q.answer = buf->buf;
1373 q.anslen = sizeof(buf->buf);
1374 q.next = &q2;
1375 q2.name = name;
1376 q2.qclass = C_IN;
1377 q2.qtype = T_A;
1378 q2.answer = buf2->buf;
1379 q2.anslen = sizeof(buf2->buf);
1380 break;
1381 case AF_INET:
1382 q.name = name;
1383 q.qclass = C_IN;
1384 q.qtype = T_A;
1385 q.answer = buf->buf;
1386 q.anslen = sizeof(buf->buf);
1387 break;
1388 case AF_INET6:
1389 q.name = name;
1390 q.qclass = C_IN;
1391 q.qtype = T_AAAA;
1392 q.answer = buf->buf;
1393 q.anslen = sizeof(buf->buf);
1394 break;
1395 default:
1396 free(buf);
1397 free(buf2);
1398 return NS_UNAVAIL;
1399 }
1400
1401 res = __res_get_state();
1402 if (res == NULL) {
1403 free(buf);
1404 free(buf2);
1405 return NS_NOTFOUND;
1406 }
1407
1408 if (res_searchN(name, &q, res) < 0) {
1409 __res_put_state(res);
1410 free(buf);
1411 free(buf2);
1412 return NS_NOTFOUND;
1413 }
1414 ai = getanswer(res, buf, q.n, q.name, q.qtype, pai);
1415 if (ai) {
1416 cur->ai_next = ai;
1417 while (cur && cur->ai_next)
1418 cur = cur->ai_next;
1419 }
1420 if (q.next) {
1421 ai = getanswer(res, buf2, q2.n, q2.name, q2.qtype, pai);
1422 if (ai)
1423 cur->ai_next = ai;
1424 }
1425 free(buf);
1426 free(buf2);
1427 if (sentinel.ai_next == NULL) {
1428 __res_put_state(res);
1429 switch (h_errno) {
1430 case HOST_NOT_FOUND:
1431 return NS_NOTFOUND;
1432 case TRY_AGAIN:
1433 return NS_TRYAGAIN;
1434 default:
1435 return NS_UNAVAIL;
1436 }
1437 }
1438
1439 if (res->nsort)
1440 aisort(&sentinel, res);
1441
1442 __res_put_state(res);
1443
1444 *((struct addrinfo **)rv) = sentinel.ai_next;
1445 return NS_SUCCESS;
1446 }
1447
1448 static void
1449 _sethtent(FILE **hostf)
1450 {
1451
1452 if (!*hostf)
1453 *hostf = fopen(_PATH_HOSTS, "re");
1454 else
1455 rewind(*hostf);
1456 }
1457
1458 static void
1459 _endhtent(FILE **hostf)
1460 {
1461
1462 if (*hostf) {
1463 (void) fclose(*hostf);
1464 *hostf = NULL;
1465 }
1466 }
1467
1468 static struct addrinfo *
1469 _gethtent(FILE **hostf, const char *name, const struct addrinfo *pai)
1470 {
1471 char *p;
1472 char *cp, *tname, *cname;
1473 struct addrinfo hints, *res0, *res;
1474 int error;
1475 const char *addr;
1476 char hostbuf[8*1024];
1477
1478 _DIAGASSERT(name != NULL);
1479 _DIAGASSERT(pai != NULL);
1480
1481 if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "re")))
1482 return (NULL);
1483 again:
1484 if (!(p = fgets(hostbuf, sizeof hostbuf, *hostf)))
1485 return (NULL);
1486 if (*p == '#')
1487 goto again;
1488 if (!(cp = strpbrk(p, "#\n")))
1489 goto again;
1490 *cp = '\0';
1491 if (!(cp = strpbrk(p, " \t")))
1492 goto again;
1493 *cp++ = '\0';
1494 addr = p;
1495 /* if this is not something we're looking for, skip it. */
1496 cname = NULL;
1497 while (cp && *cp) {
1498 if (*cp == ' ' || *cp == '\t') {
1499 cp++;
1500 continue;
1501 }
1502 if (!cname)
1503 cname = cp;
1504 tname = cp;
1505 if ((cp = strpbrk(cp, " \t")) != NULL)
1506 *cp++ = '\0';
1507 if (strcasecmp(name, tname) == 0)
1508 goto found;
1509 }
1510 goto again;
1511
1512 found:
1513 hints = *pai;
1514 hints.ai_flags = AI_NUMERICHOST;
1515 error = getaddrinfo(addr, NULL, &hints, &res0);
1516 if (error)
1517 goto again;
1518 for (res = res0; res; res = res->ai_next) {
1519 /* cover it up */
1520 res->ai_flags = pai->ai_flags;
1521
1522 if (pai->ai_flags & AI_CANONNAME) {
1523 if (get_canonname(pai, res, cname) != 0) {
1524 freeaddrinfo(res0);
1525 goto again;
1526 }
1527 }
1528 }
1529 return res0;
1530 }
1531
1532 /*ARGSUSED*/
1533 static int
1534 _files_getaddrinfo(void *rv, void *cb_data, va_list ap)
1535 {
1536 const char *name;
1537 const struct addrinfo *pai;
1538 struct addrinfo sentinel, *cur;
1539 struct addrinfo *p;
1540 #ifndef _REENTRANT
1541 static
1542 #endif
1543 FILE *hostf = NULL;
1544
1545 name = va_arg(ap, char *);
1546 pai = va_arg(ap, const struct addrinfo *);
1547
1548 memset(&sentinel, 0, sizeof(sentinel));
1549 cur = &sentinel;
1550
1551 _sethtent(&hostf);
1552 while ((p = _gethtent(&hostf, name, pai)) != NULL) {
1553 cur->ai_next = p;
1554 while (cur && cur->ai_next)
1555 cur = cur->ai_next;
1556 }
1557 _endhtent(&hostf);
1558
1559 *((struct addrinfo **)rv) = sentinel.ai_next;
1560 if (sentinel.ai_next == NULL)
1561 return NS_NOTFOUND;
1562 return NS_SUCCESS;
1563 }
1564
1565 #ifdef YP
1566 /*ARGSUSED*/
1567 static struct addrinfo *
1568 _yphostent(char *line, const struct addrinfo *pai)
1569 {
1570 struct addrinfo sentinel, *cur;
1571 struct addrinfo hints, *res, *res0;
1572 int error;
1573 char *p;
1574 const char *addr, *canonname;
1575 char *nextline;
1576 char *cp;
1577
1578 _DIAGASSERT(line != NULL);
1579 _DIAGASSERT(pai != NULL);
1580
1581 p = line;
1582 addr = canonname = NULL;
1583
1584 memset(&sentinel, 0, sizeof(sentinel));
1585 cur = &sentinel;
1586
1587 nextline:
1588 /* terminate line */
1589 cp = strchr(p, '\n');
1590 if (cp) {
1591 *cp++ = '\0';
1592 nextline = cp;
1593 } else
1594 nextline = NULL;
1595
1596 cp = strpbrk(p, " \t");
1597 if (cp == NULL) {
1598 if (canonname == NULL)
1599 return (NULL);
1600 else
1601 goto done;
1602 }
1603 *cp++ = '\0';
1604
1605 addr = p;
1606
1607 while (cp && *cp) {
1608 if (*cp == ' ' || *cp == '\t') {
1609 cp++;
1610 continue;
1611 }
1612 if (!canonname)
1613 canonname = cp;
1614 if ((cp = strpbrk(cp, " \t")) != NULL)
1615 *cp++ = '\0';
1616 }
1617
1618 hints = *pai;
1619 hints.ai_flags = AI_NUMERICHOST;
1620 error = getaddrinfo(addr, NULL, &hints, &res0);
1621 if (error == 0) {
1622 for (res = res0; res; res = res->ai_next) {
1623 /* cover it up */
1624 res->ai_flags = pai->ai_flags;
1625
1626 if (pai->ai_flags & AI_CANONNAME)
1627 (void)get_canonname(pai, res, canonname);
1628 }
1629 } else
1630 res0 = NULL;
1631 if (res0) {
1632 cur->ai_next = res0;
1633 while (cur->ai_next)
1634 cur = cur->ai_next;
1635 }
1636
1637 if (nextline) {
1638 p = nextline;
1639 goto nextline;
1640 }
1641
1642 done:
1643 return sentinel.ai_next;
1644 }
1645
1646 /*ARGSUSED*/
1647 static int
1648 _yp_getaddrinfo(void *rv, void *cb_data, va_list ap)
1649 {
1650 struct addrinfo sentinel, *cur;
1651 struct addrinfo *ai = NULL;
1652 char *ypbuf;
1653 int ypbuflen, r;
1654 const char *name;
1655 const struct addrinfo *pai;
1656 char *ypdomain;
1657
1658 if (_yp_check(&ypdomain) == 0)
1659 return NS_UNAVAIL;
1660
1661 name = va_arg(ap, char *);
1662 pai = va_arg(ap, const struct addrinfo *);
1663
1664 memset(&sentinel, 0, sizeof(sentinel));
1665 cur = &sentinel;
1666
1667 /* hosts.byname is only for IPv4 (Solaris8) */
1668 if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) {
1669 r = yp_match(ypdomain, "hosts.byname", name,
1670 (int)strlen(name), &ypbuf, &ypbuflen);
1671 if (r == 0) {
1672 struct addrinfo ai4;
1673
1674 ai4 = *pai;
1675 ai4.ai_family = AF_INET;
1676 ai = _yphostent(ypbuf, &ai4);
1677 if (ai) {
1678 cur->ai_next = ai;
1679 while (cur && cur->ai_next)
1680 cur = cur->ai_next;
1681 }
1682 }
1683 free(ypbuf);
1684 }
1685
1686 /* ipnodes.byname can hold both IPv4/v6 */
1687 r = yp_match(ypdomain, "ipnodes.byname", name,
1688 (int)strlen(name), &ypbuf, &ypbuflen);
1689 if (r == 0) {
1690 ai = _yphostent(ypbuf, pai);
1691 if (ai)
1692 cur->ai_next = ai;
1693 free(ypbuf);
1694 }
1695
1696 if (sentinel.ai_next == NULL) {
1697 h_errno = HOST_NOT_FOUND;
1698 return NS_NOTFOUND;
1699 }
1700 *((struct addrinfo **)rv) = sentinel.ai_next;
1701 return NS_SUCCESS;
1702 }
1703 #endif
1704
1705 /* resolver logic */
1706
1707 /*
1708 * Formulate a normal query, send, and await answer.
1709 * Returned answer is placed in supplied buffer "answer".
1710 * Perform preliminary check of answer, returning success only
1711 * if no error is indicated and the answer count is nonzero.
1712 * Return the size of the response on success, -1 on error.
1713 * Error number is left in h_errno.
1714 *
1715 * Caller must parse answer and determine whether it answers the question.
1716 */
1717 static int
1718 res_queryN(const char *name, /* domain name */ struct res_target *target,
1719 res_state res)
1720 {
1721 u_char buf[MAXPACKET];
1722 HEADER *hp;
1723 int n;
1724 struct res_target *t;
1725 int rcode;
1726 int ancount;
1727
1728 _DIAGASSERT(name != NULL);
1729 /* XXX: target may be NULL??? */
1730
1731 rcode = NOERROR;
1732 ancount = 0;
1733
1734 for (t = target; t; t = t->next) {
1735 int class, type;
1736 u_char *answer;
1737 int anslen;
1738
1739 hp = (HEADER *)(void *)t->answer;
1740 hp->rcode = NOERROR; /* default */
1741
1742 /* make it easier... */
1743 class = t->qclass;
1744 type = t->qtype;
1745 answer = t->answer;
1746 anslen = t->anslen;
1747 #ifdef DEBUG
1748 if (res->options & RES_DEBUG)
1749 printf(";; res_nquery(%s, %d, %d)\n", name, class, type);
1750 #endif
1751
1752 n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL,
1753 buf, sizeof(buf));
1754 #ifdef RES_USE_EDNS0
1755 if (n > 0 && (res->options & RES_USE_EDNS0) != 0)
1756 n = res_nopt(res, n, buf, sizeof(buf), anslen);
1757 #endif
1758 if (n <= 0) {
1759 #ifdef DEBUG
1760 if (res->options & RES_DEBUG)
1761 printf(";; res_nquery: mkquery failed\n");
1762 #endif
1763 h_errno = NO_RECOVERY;
1764 return n;
1765 }
1766 n = res_nsend(res, buf, n, answer, anslen);
1767 #if 0
1768 if (n < 0) {
1769 #ifdef DEBUG
1770 if (res->options & RES_DEBUG)
1771 printf(";; res_query: send error\n");
1772 #endif
1773 h_errno = TRY_AGAIN;
1774 return n;
1775 }
1776 #endif
1777
1778 if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
1779 rcode = hp->rcode; /* record most recent error */
1780 #ifdef DEBUG
1781 if (res->options & RES_DEBUG)
1782 printf(";; rcode = %u, ancount=%u\n", hp->rcode,
1783 ntohs(hp->ancount));
1784 #endif
1785 continue;
1786 }
1787
1788 ancount += ntohs(hp->ancount);
1789
1790 t->n = n;
1791 }
1792
1793 if (ancount == 0) {
1794 switch (rcode) {
1795 case NXDOMAIN:
1796 h_errno = HOST_NOT_FOUND;
1797 break;
1798 case SERVFAIL:
1799 h_errno = TRY_AGAIN;
1800 break;
1801 case NOERROR:
1802 h_errno = NO_DATA;
1803 break;
1804 case FORMERR:
1805 case NOTIMP:
1806 case REFUSED:
1807 default:
1808 h_errno = NO_RECOVERY;
1809 break;
1810 }
1811 return -1;
1812 }
1813 return ancount;
1814 }
1815
1816 /*
1817 * Formulate a normal query, send, and retrieve answer in supplied buffer.
1818 * Return the size of the response on success, -1 on error.
1819 * If enabled, implement search rules until answer or unrecoverable failure
1820 * is detected. Error code, if any, is left in h_errno.
1821 */
1822 static int
1823 res_searchN(const char *name, struct res_target *target, res_state res)
1824 {
1825 const char *cp, * const *domain;
1826 HEADER *hp;
1827 u_int dots;
1828 char buf[MAXHOSTNAMELEN];
1829 int trailing_dot, ret, saved_herrno;
1830 int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
1831
1832 _DIAGASSERT(name != NULL);
1833 _DIAGASSERT(target != NULL);
1834
1835 hp = (HEADER *)(void *)target->answer; /*XXX*/
1836
1837 errno = 0;
1838 h_errno = HOST_NOT_FOUND; /* default, if we never query */
1839 dots = 0;
1840 for (cp = name; *cp; cp++)
1841 dots += (*cp == '.');
1842 trailing_dot = 0;
1843 if (cp > name && *--cp == '.')
1844 trailing_dot++;
1845
1846 /*
1847 * if there aren't any dots, it could be a user-level alias
1848 */
1849 if (!dots && (cp = res_hostalias(res, name, buf, sizeof(buf))) != NULL) {
1850 ret = res_queryN(cp, target, res);
1851 return ret;
1852 }
1853
1854 /*
1855 * If there are dots in the name already, let's just give it a try
1856 * 'as is'. The threshold can be set with the "ndots" option.
1857 */
1858 saved_herrno = -1;
1859 if (dots >= res->ndots) {
1860 ret = res_querydomainN(name, NULL, target, res);
1861 if (ret > 0)
1862 return (ret);
1863 saved_herrno = h_errno;
1864 tried_as_is++;
1865 }
1866
1867 /*
1868 * We do at least one level of search if
1869 * - there is no dot and RES_DEFNAME is set, or
1870 * - there is at least one dot, there is no trailing dot,
1871 * and RES_DNSRCH is set.
1872 */
1873 if ((!dots && (res->options & RES_DEFNAMES)) ||
1874 (dots && !trailing_dot && (res->options & RES_DNSRCH))) {
1875 int done = 0;
1876
1877 for (domain = (const char * const *)res->dnsrch;
1878 *domain && !done;
1879 domain++) {
1880
1881 ret = res_querydomainN(name, *domain, target, res);
1882 if (ret > 0)
1883 return ret;
1884
1885 /*
1886 * If no server present, give up.
1887 * If name isn't found in this domain,
1888 * keep trying higher domains in the search list
1889 * (if that's enabled).
1890 * On a NO_DATA error, keep trying, otherwise
1891 * a wildcard entry of another type could keep us
1892 * from finding this entry higher in the domain.
1893 * If we get some other error (negative answer or
1894 * server failure), then stop searching up,
1895 * but try the input name below in case it's
1896 * fully-qualified.
1897 */
1898 if (errno == ECONNREFUSED) {
1899 h_errno = TRY_AGAIN;
1900 return -1;
1901 }
1902
1903 switch (h_errno) {
1904 case NO_DATA:
1905 got_nodata++;
1906 /* FALLTHROUGH */
1907 case HOST_NOT_FOUND:
1908 /* keep trying */
1909 break;
1910 case TRY_AGAIN:
1911 if (hp->rcode == SERVFAIL) {
1912 /* try next search element, if any */
1913 got_servfail++;
1914 break;
1915 }
1916 /* FALLTHROUGH */
1917 default:
1918 /* anything else implies that we're done */
1919 done++;
1920 }
1921 /*
1922 * if we got here for some reason other than DNSRCH,
1923 * we only wanted one iteration of the loop, so stop.
1924 */
1925 if (!(res->options & RES_DNSRCH))
1926 done++;
1927 }
1928 }
1929
1930 /*
1931 * if we have not already tried the name "as is", do that now.
1932 * note that we do this regardless of how many dots were in the
1933 * name or whether it ends with a dot.
1934 */
1935 if (!tried_as_is) {
1936 ret = res_querydomainN(name, NULL, target, res);
1937 if (ret > 0)
1938 return ret;
1939 }
1940
1941 /*
1942 * if we got here, we didn't satisfy the search.
1943 * if we did an initial full query, return that query's h_errno
1944 * (note that we wouldn't be here if that query had succeeded).
1945 * else if we ever got a nodata, send that back as the reason.
1946 * else send back meaningless h_errno, that being the one from
1947 * the last DNSRCH we did.
1948 */
1949 if (saved_herrno != -1)
1950 h_errno = saved_herrno;
1951 else if (got_nodata)
1952 h_errno = NO_DATA;
1953 else if (got_servfail)
1954 h_errno = TRY_AGAIN;
1955 return -1;
1956 }
1957
1958 /*
1959 * Perform a call on res_query on the concatenation of name and domain,
1960 * removing a trailing dot from name if domain is NULL.
1961 */
1962 static int
1963 res_querydomainN(const char *name, const char *domain,
1964 struct res_target *target, res_state res)
1965 {
1966 char nbuf[MAXDNAME];
1967 const char *longname = nbuf;
1968 size_t n, d;
1969
1970 _DIAGASSERT(name != NULL);
1971 /* XXX: target may be NULL??? */
1972
1973 #ifdef DEBUG
1974 if (res->options & RES_DEBUG)
1975 printf(";; res_querydomain(%s, %s)\n",
1976 name, domain?domain:"<Nil>");
1977 #endif
1978 if (domain == NULL) {
1979 /*
1980 * Check for trailing '.';
1981 * copy without '.' if present.
1982 */
1983 n = strlen(name);
1984 if (n + 1 > sizeof(nbuf)) {
1985 h_errno = NO_RECOVERY;
1986 return -1;
1987 }
1988 if (n > 0 && name[--n] == '.') {
1989 strncpy(nbuf, name, n);
1990 nbuf[n] = '\0';
1991 } else
1992 longname = name;
1993 } else {
1994 n = strlen(name);
1995 d = strlen(domain);
1996 if (n + 1 + d + 1 > sizeof(nbuf)) {
1997 h_errno = NO_RECOVERY;
1998 return -1;
1999 }
2000 snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
2001 }
2002 return res_queryN(longname, target, res);
2003 }
2004