1 /*
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 /*
31 * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
32 *
33 * Issues to be discussed:
34 * - Thread safe-ness must be checked.
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 * Note:
39 * - We use getipnodebyname() just for thread-safeness. There's no intent
40 * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to
41 * getipnodebyname().
42 * - The code filters out AFs that are not supported by the kernel,
43 * when globbing NULL hostname (to loopback, or wildcard). Is it the right
44 * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG
45 * in ai_flags?
46 */
47
48 #ifdef HAVE_CONFIG_H
49 #include <config.h>
50 #endif
51
52 #ifndef lint
53 static const char rcsid[] _U_ =
54 "@(#) $Header: /tcpdump/master/tcpdump/missing/getaddrinfo.c,v 1.13 2003/11/16 09:36:48 guy Exp $";
55 #endif
56
57 #include <sys/types.h>
58 #include <sys/param.h>
59 #if 0
60 #include <sys/sysctl.h>
61 #endif
62 #include <sys/socket.h>
63 #include <net/if.h>
64 #include <netinet/in.h>
65 #include <arpa/inet.h>
66 #include <arpa/nameser.h>
67 #include <netdb.h>
68 #include <resolv.h>
69 #include <string.h>
70 #include <stdlib.h>
71 #include <stddef.h>
72 #include <ctype.h>
73 #include <unistd.h>
74 #include <stdio.h>
75 #include <errno.h>
76
77 #ifndef HAVE_U_INT32_T
78 #include "bittypes.h"
79 #endif
80
81 #ifndef HAVE_SOCKADDR_STORAGE
82 #include "sockstorage.h"
83 #endif
84
85 #ifdef NEED_ADDRINFO_H
86 #include "addrinfo.h"
87 #endif
88
89 #if defined(__KAME__) && defined(INET6)
90 # define FAITH
91 #endif
92
93 #define SUCCESS 0
94 #define ANY 0
95 #define YES 1
96 #define NO 0
97
98 #ifdef FAITH
99 static int translate = NO;
100 static struct in6_addr faith_prefix = IN6ADDR_ANY_INIT;
101 #endif
102
103 static const char in_addrany[] = { 0, 0, 0, 0 };
104 static const char in6_addrany[] = {
105 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
106 };
107 static const char in_loopback[] = { 127, 0, 0, 1 };
108 static const char in6_loopback[] = {
109 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
110 };
111
112 struct sockinet {
113 u_char si_len;
114 u_char si_family;
115 u_short si_port;
116 u_int32_t si_scope_id;
117 };
118
119 static const struct afd {
120 int a_af;
121 int a_addrlen;
122 int a_socklen;
123 int a_off;
124 const char *a_addrany;
125 const char *a_loopback;
126 int a_scoped;
127 } afdl [] = {
128 #ifdef INET6
129 {PF_INET6, sizeof(struct in6_addr),
130 sizeof(struct sockaddr_in6),
131 offsetof(struct sockaddr_in6, sin6_addr),
132 in6_addrany, in6_loopback, 1},
133 #endif
134 {PF_INET, sizeof(struct in_addr),
135 sizeof(struct sockaddr_in),
136 offsetof(struct sockaddr_in, sin_addr),
137 in_addrany, in_loopback, 0},
138 {0, 0, 0, 0, NULL, NULL, 0},
139 };
140
141 struct explore {
142 int e_af;
143 int e_socktype;
144 int e_protocol;
145 const char *e_protostr;
146 int e_wild;
147 #define WILD_AF(ex) ((ex)->e_wild & 0x01)
148 #define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
149 #define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
150 };
151
152 static const struct explore explore[] = {
153 #if 0
154 { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
155 #endif
156 #ifdef INET6
157 { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
158 { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
159 { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
160 #endif
161 { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
162 { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
163 { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
164 { -1, 0, 0, NULL, 0 },
165 };
166
167 #ifdef INET6
168 #define PTON_MAX 16
169 #else
170 #define PTON_MAX 4
171 #endif
172
173
174 static int str_isnumber (const char *);
175 static int explore_fqdn (const struct addrinfo *, const char *,
176 const char *, struct addrinfo **);
177 static int explore_null (const struct addrinfo *, const char *,
178 const char *, struct addrinfo **);
179 static int explore_numeric (const struct addrinfo *, const char *,
180 const char *, struct addrinfo **);
181 static int explore_numeric_scope (const struct addrinfo *, const char *,
182 const char *, struct addrinfo **);
183 static int get_name (const char *, const struct afd *, struct addrinfo **,
184 char *, const struct addrinfo *, const char *);
185 static int get_canonname (const struct addrinfo *,
186 struct addrinfo *, const char *);
187 static struct addrinfo *get_ai (const struct addrinfo *,
188 const struct afd *, const char *);
189 static int get_portmatch (const struct addrinfo *, const char *);
190 static int get_port (struct addrinfo *, const char *, int);
191 static const struct afd *find_afd (int);
192
193 static char *ai_errlist[] = {
194 "Success",
195 "Address family for hostname not supported", /* EAI_ADDRFAMILY */
196 "Temporary failure in name resolution", /* EAI_AGAIN */
197 "Invalid value for ai_flags", /* EAI_BADFLAGS */
198 "Non-recoverable failure in name resolution", /* EAI_FAIL */
199 "ai_family not supported", /* EAI_FAMILY */
200 "Memory allocation failure", /* EAI_MEMORY */
201 "No address associated with hostname", /* EAI_NODATA */
202 "hostname nor servname provided, or not known", /* EAI_NONAME */
203 "servname not supported for ai_socktype", /* EAI_SERVICE */
204 "ai_socktype not supported", /* EAI_SOCKTYPE */
205 "System error returned in errno", /* EAI_SYSTEM */
206 "Invalid value for hints", /* EAI_BADHINTS */
207 "Resolved protocol is unknown", /* EAI_PROTOCOL */
208 "Unknown error", /* EAI_MAX */
209 };
210
211 /* XXX macros that make external reference is BAD. */
212
213 #define GET_AI(ai, afd, addr) \
214 do { \
215 /* external reference: pai, error, and label free */ \
216 (ai) = get_ai(pai, (afd), (addr)); \
217 if ((ai) == NULL) { \
218 error = EAI_MEMORY; \
219 goto free; \
220 } \
221 } while (0)
222
223 #define GET_PORT(ai, serv) \
224 do { \
225 /* external reference: error and label free */ \
226 error = get_port((ai), (serv), 0); \
227 if (error != 0) \
228 goto free; \
229 } while (0)
230
231 #define GET_CANONNAME(ai, str) \
232 do { \
233 /* external reference: pai, error and label free */ \
234 error = get_canonname(pai, (ai), (str)); \
235 if (error != 0) \
236 goto free; \
237 } while (0)
238
239 #define ERR(err) \
240 do { \
241 /* external reference: error, and label bad */ \
242 error = (err); \
243 goto bad; \
244 } while (0)
245
246 #define MATCH_FAMILY(x, y, w) \
247 ((x) == (y) || ((w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
248 #define MATCH(x, y, w) \
249 ((x) == (y) || ((w) && ((x) == ANY || (y) == ANY)))
250
251 char *
gai_strerror(ecode)252 gai_strerror(ecode)
253 int ecode;
254 {
255 if (ecode < 0 || ecode > EAI_MAX)
256 ecode = EAI_MAX;
257 return ai_errlist[ecode];
258 }
259
260 void
freeaddrinfo(ai)261 freeaddrinfo(ai)
262 struct addrinfo *ai;
263 {
264 struct addrinfo *next;
265
266 do {
267 next = ai->ai_next;
268 if (ai->ai_canonname)
269 free(ai->ai_canonname);
270 /* no need to free(ai->ai_addr) */
271 free(ai);
272 } while ((ai = next) != NULL);
273 }
274
275 static int
str_isnumber(p)276 str_isnumber(p)
277 const char *p;
278 {
279 char *q = (char *)p;
280 while (*q) {
281 if (! isdigit(*q))
282 return NO;
283 q++;
284 }
285 return YES;
286 }
287
288 int
getaddrinfo(hostname,servname,hints,res)289 getaddrinfo(hostname, servname, hints, res)
290 const char *hostname, *servname;
291 const struct addrinfo *hints;
292 struct addrinfo **res;
293 {
294 struct addrinfo sentinel;
295 struct addrinfo *cur;
296 int error = 0;
297 struct addrinfo ai;
298 struct addrinfo ai0;
299 struct addrinfo *pai;
300 const struct afd *afd;
301 const struct explore *ex;
302
303 #ifdef FAITH
304 static int firsttime = 1;
305
306 if (firsttime) {
307 /* translator hack */
308 char *q = getenv("GAI");
309 if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1)
310 translate = YES;
311 firsttime = 0;
312 }
313 #endif
314
315 sentinel.ai_next = NULL;
316 cur = &sentinel;
317 pai = &ai;
318 pai->ai_flags = 0;
319 pai->ai_family = PF_UNSPEC;
320 pai->ai_socktype = ANY;
321 pai->ai_protocol = ANY;
322 pai->ai_addrlen = 0;
323 pai->ai_canonname = NULL;
324 pai->ai_addr = NULL;
325 pai->ai_next = NULL;
326
327 if (hostname == NULL && servname == NULL)
328 return EAI_NONAME;
329 if (hints) {
330 /* error check for hints */
331 if (hints->ai_addrlen || hints->ai_canonname ||
332 hints->ai_addr || hints->ai_next)
333 ERR(EAI_BADHINTS); /* xxx */
334 if (hints->ai_flags & ~AI_MASK)
335 ERR(EAI_BADFLAGS);
336 switch (hints->ai_family) {
337 case PF_UNSPEC:
338 case PF_INET:
339 #ifdef INET6
340 case PF_INET6:
341 #endif
342 break;
343 default:
344 ERR(EAI_FAMILY);
345 }
346 memcpy(pai, hints, sizeof(*pai));
347
348 /*
349 * if both socktype/protocol are specified, check if they
350 * are meaningful combination.
351 */
352 if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
353 for (ex = explore; ex->e_af >= 0; ex++) {
354 if (pai->ai_family != ex->e_af)
355 continue;
356 if (ex->e_socktype == ANY)
357 continue;
358 if (ex->e_protocol == ANY)
359 continue;
360 if (pai->ai_socktype == ex->e_socktype
361 && pai->ai_protocol != ex->e_protocol) {
362 ERR(EAI_BADHINTS);
363 }
364 }
365 }
366 }
367
368 /*
369 * check for special cases. (1) numeric servname is disallowed if
370 * socktype/protocol are left unspecified. (2) servname is disallowed
371 * for raw and other inet{,6} sockets.
372 */
373 if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
374 #ifdef PF_INET6
375 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
376 #endif
377 ) {
378 ai0 = *pai;
379
380 if (pai->ai_family == PF_UNSPEC) {
381 #ifdef PF_INET6
382 pai->ai_family = PF_INET6;
383 #else
384 pai->ai_family = PF_INET;
385 #endif
386 }
387 error = get_portmatch(pai, servname);
388 if (error)
389 ERR(error);
390
391 *pai = ai0;
392 }
393
394 ai0 = *pai;
395
396 /* NULL hostname, or numeric hostname */
397 for (ex = explore; ex->e_af >= 0; ex++) {
398 *pai = ai0;
399
400 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
401 continue;
402 if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
403 continue;
404 if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
405 continue;
406
407 if (pai->ai_family == PF_UNSPEC)
408 pai->ai_family = ex->e_af;
409 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
410 pai->ai_socktype = ex->e_socktype;
411 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
412 pai->ai_protocol = ex->e_protocol;
413
414 if (hostname == NULL)
415 error = explore_null(pai, hostname, servname, &cur->ai_next);
416 else
417 error = explore_numeric_scope(pai, hostname, servname, &cur->ai_next);
418
419 if (error)
420 goto free;
421
422 while (cur && cur->ai_next)
423 cur = cur->ai_next;
424 }
425
426 /*
427 * XXX
428 * If numreic representation of AF1 can be interpreted as FQDN
429 * representation of AF2, we need to think again about the code below.
430 */
431 if (sentinel.ai_next)
432 goto good;
433
434 if (pai->ai_flags & AI_NUMERICHOST)
435 ERR(EAI_NONAME);
436 if (hostname == NULL)
437 ERR(EAI_NONAME);
438
439 /*
440 * hostname as alphabetical name.
441 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
442 * outer loop by AFs.
443 */
444 for (afd = afdl; afd->a_af; afd++) {
445 *pai = ai0;
446
447 if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1))
448 continue;
449
450 for (ex = explore; ex->e_af >= 0; ex++) {
451 *pai = ai0;
452
453 if (pai->ai_family == PF_UNSPEC)
454 pai->ai_family = afd->a_af;
455
456 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
457 continue;
458 if (!MATCH(pai->ai_socktype, ex->e_socktype,
459 WILD_SOCKTYPE(ex))) {
460 continue;
461 }
462 if (!MATCH(pai->ai_protocol, ex->e_protocol,
463 WILD_PROTOCOL(ex))) {
464 continue;
465 }
466
467 if (pai->ai_family == PF_UNSPEC)
468 pai->ai_family = ex->e_af;
469 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
470 pai->ai_socktype = ex->e_socktype;
471 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
472 pai->ai_protocol = ex->e_protocol;
473
474 error = explore_fqdn(pai, hostname, servname,
475 &cur->ai_next);
476
477 while (cur && cur->ai_next)
478 cur = cur->ai_next;
479 }
480 }
481
482 /* XXX */
483 if (sentinel.ai_next)
484 error = 0;
485
486 if (error)
487 goto free;
488 if (error == 0) {
489 if (sentinel.ai_next) {
490 good:
491 *res = sentinel.ai_next;
492 return SUCCESS;
493 } else
494 error = EAI_FAIL;
495 }
496 free:
497 bad:
498 if (sentinel.ai_next)
499 freeaddrinfo(sentinel.ai_next);
500 *res = NULL;
501 return error;
502 }
503
504 /*
505 * FQDN hostname, DNS lookup
506 */
507 static int
explore_fqdn(pai,hostname,servname,res)508 explore_fqdn(pai, hostname, servname, res)
509 const struct addrinfo *pai;
510 const char *hostname;
511 const char *servname;
512 struct addrinfo **res;
513 {
514 struct hostent *hp;
515 int h_error;
516 int af;
517 char **aplist = NULL, *apbuf = NULL;
518 char *ap;
519 struct addrinfo sentinel, *cur;
520 int i;
521 #ifndef USE_GETIPNODEBY
522 int naddrs;
523 #endif
524 const struct afd *afd;
525 int error;
526
527 *res = NULL;
528 sentinel.ai_next = NULL;
529 cur = &sentinel;
530
531 /*
532 * Do not filter unsupported AFs here. We need to honor content of
533 * databases (/etc/hosts, DNS and others). Otherwise we cannot
534 * replace gethostbyname() by getaddrinfo().
535 */
536
537 /*
538 * if the servname does not match socktype/protocol, ignore it.
539 */
540 if (get_portmatch(pai, servname) != 0)
541 return 0;
542
543 afd = find_afd(pai->ai_family);
544
545 /*
546 * post-RFC2553: should look at (pai->ai_flags & AI_ADDRCONFIG)
547 * rather than hardcoding it. we may need to add AI_ADDRCONFIG
548 * handling code by ourselves in case we don't have getipnodebyname().
549 */
550 #ifdef USE_GETIPNODEBY
551 hp = getipnodebyname(hostname, pai->ai_family, AI_ADDRCONFIG, &h_error);
552 #else
553 #ifdef HAVE_GETHOSTBYNAME2
554 hp = gethostbyname2(hostname, pai->ai_family);
555 #else
556 if (pai->ai_family != AF_INET)
557 return 0;
558 hp = gethostbyname(hostname);
559 #ifdef HAVE_H_ERRNO
560 h_error = h_errno;
561 #else
562 h_error = EINVAL;
563 #endif
564 #endif /*HAVE_GETHOSTBYNAME2*/
565 #endif /*USE_GETIPNODEBY*/
566
567 if (hp == NULL) {
568 switch (h_error) {
569 case HOST_NOT_FOUND:
570 case NO_DATA:
571 error = EAI_NODATA;
572 break;
573 case TRY_AGAIN:
574 error = EAI_AGAIN;
575 break;
576 case NO_RECOVERY:
577 case NETDB_INTERNAL:
578 default:
579 error = EAI_FAIL;
580 break;
581 }
582 } else if ((hp->h_name == NULL) || (hp->h_name[0] == 0)
583 || (hp->h_addr_list[0] == NULL)) {
584 #ifdef USE_GETIPNODEBY
585 freehostent(hp);
586 #endif
587 hp = NULL;
588 error = EAI_FAIL;
589 }
590
591 if (hp == NULL)
592 goto free;
593
594 #ifdef USE_GETIPNODEBY
595 aplist = hp->h_addr_list;
596 #else
597 /*
598 * hp will be overwritten if we use gethostbyname2().
599 * always deep copy for simplification.
600 */
601 for (naddrs = 0; hp->h_addr_list[naddrs] != NULL; naddrs++)
602 ;
603 naddrs++;
604 aplist = (char **)malloc(sizeof(aplist[0]) * naddrs);
605 apbuf = (char *)malloc(hp->h_length * naddrs);
606 if (aplist == NULL || apbuf == NULL) {
607 error = EAI_MEMORY;
608 goto free;
609 }
610 memset(aplist, 0, sizeof(aplist[0]) * naddrs);
611 for (i = 0; i < naddrs; i++) {
612 if (hp->h_addr_list[i] == NULL) {
613 aplist[i] = NULL;
614 continue;
615 }
616 memcpy(&apbuf[i * hp->h_length], hp->h_addr_list[i],
617 hp->h_length);
618 aplist[i] = &apbuf[i * hp->h_length];
619 }
620 #endif
621
622 for (i = 0; aplist[i] != NULL; i++) {
623 af = hp->h_addrtype;
624 ap = aplist[i];
625 #ifdef AF_INET6
626 if (af == AF_INET6
627 && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
628 af = AF_INET;
629 ap = ap + sizeof(struct in6_addr)
630 - sizeof(struct in_addr);
631 }
632 #endif
633
634 if (af != pai->ai_family)
635 continue;
636
637 if ((pai->ai_flags & AI_CANONNAME) == 0) {
638 GET_AI(cur->ai_next, afd, ap);
639 GET_PORT(cur->ai_next, servname);
640 } else {
641 /*
642 * if AI_CANONNAME and if reverse lookup
643 * fail, return ai anyway to pacify
644 * calling application.
645 *
646 * XXX getaddrinfo() is a name->address
647 * translation function, and it looks
648 * strange that we do addr->name
649 * translation here.
650 */
651 get_name(ap, afd, &cur->ai_next,
652 ap, pai, servname);
653 }
654
655 while (cur && cur->ai_next)
656 cur = cur->ai_next;
657 }
658
659 *res = sentinel.ai_next;
660 return 0;
661
662 free:
663 #ifdef USE_GETIPNODEBY
664 if (hp)
665 freehostent(hp);
666 #endif
667 if (aplist)
668 free(aplist);
669 if (apbuf)
670 free(apbuf);
671 if (sentinel.ai_next)
672 freeaddrinfo(sentinel.ai_next);
673 return error;
674 }
675
676 /*
677 * hostname == NULL.
678 * passive socket -> anyaddr (0.0.0.0 or ::)
679 * non-passive socket -> localhost (127.0.0.1 or ::1)
680 */
681 static int
explore_null(pai,hostname,servname,res)682 explore_null(pai, hostname, servname, res)
683 const struct addrinfo *pai;
684 const char *hostname;
685 const char *servname;
686 struct addrinfo **res;
687 {
688 int s;
689 const struct afd *afd;
690 struct addrinfo *cur;
691 struct addrinfo sentinel;
692 int error;
693
694 *res = NULL;
695 sentinel.ai_next = NULL;
696 cur = &sentinel;
697
698 /*
699 * filter out AFs that are not supported by the kernel
700 * XXX errno?
701 */
702 s = socket(pai->ai_family, SOCK_DGRAM, 0);
703 if (s < 0) {
704 if (errno != EMFILE)
705 return 0;
706 } else
707 close(s);
708
709 /*
710 * if the servname does not match socktype/protocol, ignore it.
711 */
712 if (get_portmatch(pai, servname) != 0)
713 return 0;
714
715 afd = find_afd(pai->ai_family);
716
717 if (pai->ai_flags & AI_PASSIVE) {
718 GET_AI(cur->ai_next, afd, afd->a_addrany);
719 /* xxx meaningless?
720 * GET_CANONNAME(cur->ai_next, "anyaddr");
721 */
722 GET_PORT(cur->ai_next, servname);
723 } else {
724 GET_AI(cur->ai_next, afd, afd->a_loopback);
725 /* xxx meaningless?
726 * GET_CANONNAME(cur->ai_next, "localhost");
727 */
728 GET_PORT(cur->ai_next, servname);
729 }
730 cur = cur->ai_next;
731
732 *res = sentinel.ai_next;
733 return 0;
734
735 free:
736 if (sentinel.ai_next)
737 freeaddrinfo(sentinel.ai_next);
738 return error;
739 }
740
741 /*
742 * numeric hostname
743 */
744 static int
explore_numeric(pai,hostname,servname,res)745 explore_numeric(pai, hostname, servname, res)
746 const struct addrinfo *pai;
747 const char *hostname;
748 const char *servname;
749 struct addrinfo **res;
750 {
751 const struct afd *afd;
752 struct addrinfo *cur;
753 struct addrinfo sentinel;
754 int error;
755 char pton[PTON_MAX];
756 int flags;
757
758 *res = NULL;
759 sentinel.ai_next = NULL;
760 cur = &sentinel;
761
762 /*
763 * if the servname does not match socktype/protocol, ignore it.
764 */
765 if (get_portmatch(pai, servname) != 0)
766 return 0;
767
768 afd = find_afd(pai->ai_family);
769 flags = pai->ai_flags;
770
771 if (inet_pton(afd->a_af, hostname, pton) == 1) {
772 u_int32_t v4a;
773 #ifdef INET6
774 u_char pfx;
775 #endif
776
777 switch (afd->a_af) {
778 case AF_INET:
779 v4a = (u_int32_t)ntohl(((struct in_addr *)pton)->s_addr);
780 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
781 flags &= ~AI_CANONNAME;
782 v4a >>= IN_CLASSA_NSHIFT;
783 if (v4a == 0 || v4a == IN_LOOPBACKNET)
784 flags &= ~AI_CANONNAME;
785 break;
786 #ifdef INET6
787 case AF_INET6:
788 pfx = ((struct in6_addr *)pton)->s6_addr[0];
789 if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
790 flags &= ~AI_CANONNAME;
791 break;
792 #endif
793 }
794
795 if (pai->ai_family == afd->a_af ||
796 pai->ai_family == PF_UNSPEC /*?*/) {
797 if ((flags & AI_CANONNAME) == 0) {
798 GET_AI(cur->ai_next, afd, pton);
799 GET_PORT(cur->ai_next, servname);
800 } else {
801 /*
802 * if AI_CANONNAME and if reverse lookup
803 * fail, return ai anyway to pacify
804 * calling application.
805 *
806 * XXX getaddrinfo() is a name->address
807 * translation function, and it looks
808 * strange that we do addr->name
809 * translation here.
810 */
811 get_name(pton, afd, &cur->ai_next,
812 pton, pai, servname);
813 }
814 while (cur && cur->ai_next)
815 cur = cur->ai_next;
816 } else
817 ERR(EAI_FAMILY); /*xxx*/
818 }
819
820 *res = sentinel.ai_next;
821 return 0;
822
823 free:
824 bad:
825 if (sentinel.ai_next)
826 freeaddrinfo(sentinel.ai_next);
827 return error;
828 }
829
830 /*
831 * numeric hostname with scope
832 */
833 static int
explore_numeric_scope(pai,hostname,servname,res)834 explore_numeric_scope(pai, hostname, servname, res)
835 const struct addrinfo *pai;
836 const char *hostname;
837 const char *servname;
838 struct addrinfo **res;
839 {
840 #ifndef SCOPE_DELIMITER
841 return explore_numeric(pai, hostname, servname, res);
842 #else
843 const struct afd *afd;
844 struct addrinfo *cur;
845 int error;
846 char *cp, *hostname2 = NULL;
847 int scope;
848 struct sockaddr_in6 *sin6;
849
850 /*
851 * if the servname does not match socktype/protocol, ignore it.
852 */
853 if (get_portmatch(pai, servname) != 0)
854 return 0;
855
856 afd = find_afd(pai->ai_family);
857 if (!afd->a_scoped)
858 return explore_numeric(pai, hostname, servname, res);
859
860 cp = strchr(hostname, SCOPE_DELIMITER);
861 if (cp == NULL)
862 return explore_numeric(pai, hostname, servname, res);
863
864 /*
865 * Handle special case of <scoped_address><delimiter><scope id>
866 */
867 hostname2 = strdup(hostname);
868 if (hostname2 == NULL)
869 return EAI_MEMORY;
870 /* terminate at the delimiter */
871 hostname2[cp - hostname] = '\0';
872
873 cp++;
874 switch (pai->ai_family) {
875 #ifdef INET6
876 case AF_INET6:
877 scope = if_nametoindex(cp);
878 if (scope == 0) {
879 free(hostname2);
880 return (EAI_NONAME);
881 }
882 break;
883 #endif
884 }
885
886 error = explore_numeric(pai, hostname2, servname, res);
887 if (error == 0) {
888 for (cur = *res; cur; cur = cur->ai_next) {
889 if (cur->ai_family != AF_INET6)
890 continue;
891 sin6 = (struct sockaddr_in6 *)cur->ai_addr;
892 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
893 IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr))
894 sin6->sin6_scope_id = scope;
895 }
896 }
897
898 free(hostname2);
899
900 return error;
901 #endif
902 }
903
904 static int
get_name(addr,afd,res,numaddr,pai,servname)905 get_name(addr, afd, res, numaddr, pai, servname)
906 const char *addr;
907 const struct afd *afd;
908 struct addrinfo **res;
909 char *numaddr;
910 const struct addrinfo *pai;
911 const char *servname;
912 {
913 struct hostent *hp = NULL;
914 struct addrinfo *cur = NULL;
915 int error = 0;
916 char *ap = NULL, *cn = NULL;
917 #ifdef USE_GETIPNODEBY
918 int h_error;
919
920 hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
921 #else
922 hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
923 #endif
924 if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
925 #ifdef USE_GETIPNODEBY
926 GET_AI(cur, afd, hp->h_addr_list[0]);
927 GET_PORT(cur, servname);
928 GET_CANONNAME(cur, hp->h_name);
929 #else
930 /* hp will be damaged if we use gethostbyaddr() */
931 if ((ap = (char *)malloc(hp->h_length)) == NULL) {
932 error = EAI_MEMORY;
933 goto free;
934 }
935 memcpy(ap, hp->h_addr_list[0], hp->h_length);
936 if ((cn = strdup(hp->h_name)) == NULL) {
937 error = EAI_MEMORY;
938 goto free;
939 }
940
941 GET_AI(cur, afd, ap);
942 GET_PORT(cur, servname);
943 GET_CANONNAME(cur, cn);
944 free(ap); ap = NULL;
945 free(cn); cn = NULL;
946 #endif
947 } else {
948 GET_AI(cur, afd, numaddr);
949 GET_PORT(cur, servname);
950 }
951
952 #ifdef USE_GETIPNODEBY
953 if (hp)
954 freehostent(hp);
955 #endif
956 *res = cur;
957 return SUCCESS;
958 free:
959 if (cur)
960 freeaddrinfo(cur);
961 if (ap)
962 free(ap);
963 if (cn)
964 free(cn);
965 #ifdef USE_GETIPNODEBY
966 if (hp)
967 freehostent(hp);
968 #endif
969 *res = NULL;
970 return error;
971 }
972
973 static int
get_canonname(pai,ai,str)974 get_canonname(pai, ai, str)
975 const struct addrinfo *pai;
976 struct addrinfo *ai;
977 const char *str;
978 {
979 if ((pai->ai_flags & AI_CANONNAME) != 0) {
980 ai->ai_canonname = (char *)malloc(strlen(str) + 1);
981 if (ai->ai_canonname == NULL)
982 return EAI_MEMORY;
983 strcpy(ai->ai_canonname, str);
984 }
985 return 0;
986 }
987
988 static struct addrinfo *
get_ai(pai,afd,addr)989 get_ai(pai, afd, addr)
990 const struct addrinfo *pai;
991 const struct afd *afd;
992 const char *addr;
993 {
994 char *p;
995 struct addrinfo *ai;
996
997 ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
998 + (afd->a_socklen));
999 if (ai == NULL)
1000 return NULL;
1001
1002 memcpy(ai, pai, sizeof(struct addrinfo));
1003 ai->ai_addr = (struct sockaddr *)(ai + 1);
1004 memset(ai->ai_addr, 0, afd->a_socklen);
1005 #ifdef HAVE_SOCKADDR_SA_LEN
1006 ai->ai_addr->sa_len = afd->a_socklen;
1007 #endif
1008 ai->ai_addrlen = afd->a_socklen;
1009 ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
1010 p = (char *)(ai->ai_addr);
1011 memcpy(p + afd->a_off, addr, afd->a_addrlen);
1012 return ai;
1013 }
1014
1015 static int
get_portmatch(ai,servname)1016 get_portmatch(ai, servname)
1017 const struct addrinfo *ai;
1018 const char *servname;
1019 {
1020
1021 /* get_port does not touch first argument. when matchonly == 1. */
1022 return get_port((struct addrinfo *)ai, servname, 1);
1023 }
1024
1025 static int
get_port(ai,servname,matchonly)1026 get_port(ai, servname, matchonly)
1027 struct addrinfo *ai;
1028 const char *servname;
1029 int matchonly;
1030 {
1031 const char *proto;
1032 struct servent *sp;
1033 int port;
1034 int allownumeric;
1035
1036 if (servname == NULL)
1037 return 0;
1038 switch (ai->ai_family) {
1039 case AF_INET:
1040 #ifdef AF_INET6
1041 case AF_INET6:
1042 #endif
1043 break;
1044 default:
1045 return 0;
1046 }
1047
1048 switch (ai->ai_socktype) {
1049 case SOCK_RAW:
1050 return EAI_SERVICE;
1051 case SOCK_DGRAM:
1052 case SOCK_STREAM:
1053 allownumeric = 1;
1054 break;
1055 case ANY:
1056 allownumeric = 0;
1057 break;
1058 default:
1059 return EAI_SOCKTYPE;
1060 }
1061
1062 if (str_isnumber(servname)) {
1063 if (!allownumeric)
1064 return EAI_SERVICE;
1065 port = htons(atoi(servname));
1066 if (port < 0 || port > 65535)
1067 return EAI_SERVICE;
1068 } else {
1069 switch (ai->ai_socktype) {
1070 case SOCK_DGRAM:
1071 proto = "udp";
1072 break;
1073 case SOCK_STREAM:
1074 proto = "tcp";
1075 break;
1076 default:
1077 proto = NULL;
1078 break;
1079 }
1080
1081 if ((sp = getservbyname(servname, proto)) == NULL)
1082 return EAI_SERVICE;
1083 port = sp->s_port;
1084 }
1085
1086 if (!matchonly) {
1087 switch (ai->ai_family) {
1088 case AF_INET:
1089 ((struct sockaddr_in *)ai->ai_addr)->sin_port = port;
1090 break;
1091 #ifdef INET6
1092 case AF_INET6:
1093 ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = port;
1094 break;
1095 #endif
1096 }
1097 }
1098
1099 return 0;
1100 }
1101
1102 static const struct afd *
find_afd(af)1103 find_afd(af)
1104 int af;
1105 {
1106 const struct afd *afd;
1107
1108 if (af == PF_UNSPEC)
1109 return NULL;
1110 for (afd = afdl; afd->a_af; afd++) {
1111 if (afd->a_af == af)
1112 return afd;
1113 }
1114 return NULL;
1115 }
1116