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