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