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