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