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