Updated to fedora-glibc-20041124T0741
[kopensolaris-gnu/glibc.git] / sysdeps / posix / getaddrinfo.c
1 /* The Inner Net License, Version 2.00
2
3   The author(s) grant permission for redistribution and use in source and
4 binary forms, with or without modification, of the software and documentation
5 provided that the following conditions are met:
6
7 0. If you receive a version of the software that is specifically labelled
8    as not being for redistribution (check the version message and/or README),
9    you are not permitted to redistribute that version of the software in any
10    way or form.
11 1. All terms of the all other applicable copyrights and licenses must be
12    followed.
13 2. Redistributions of source code must retain the authors' copyright
14    notice(s), this list of conditions, and the following disclaimer.
15 3. Redistributions in binary form must reproduce the authors' copyright
16    notice(s), this list of conditions, and the following disclaimer in the
17    documentation and/or other materials provided with the distribution.
18 4. [The copyright holder has authorized the removal of this clause.]
19 5. Neither the name(s) of the author(s) nor the names of its contributors
20    may be used to endorse or promote products derived from this software
21    without specific prior written permission.
22
23 THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS ``AS IS'' AND ANY
24 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
27 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34   If these license terms cause you a real problem, contact the author.  */
35
36 /* This software is Copyright 1996 by Craig Metz, All Rights Reserved.  */
37
38 #include <assert.h>
39 #include <errno.h>
40 #include <ifaddrs.h>
41 #include <netdb.h>
42 #include <resolv.h>
43 #include <stdbool.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <unistd.h>
48 #include <arpa/inet.h>
49 #include <sys/socket.h>
50 #include <netinet/in.h>
51 #include <sys/types.h>
52 #include <sys/un.h>
53 #include <sys/utsname.h>
54 #include <net/if.h>
55 #include <nsswitch.h>
56 #include <not-cancel.h>
57 #include <nscd/nscd-client.h>
58 #include <nscd/nscd_proto.h>
59
60 #ifdef HAVE_LIBIDN
61 extern int __idna_to_ascii_lz (const char *input, char **output, int flags);
62 extern int __idna_to_unicode_lzlz (const char *input, char **output,
63                                    int flags);
64 # include <libidn/idna.h>
65 #endif
66
67 #define GAIH_OKIFUNSPEC 0x0100
68 #define GAIH_EAI        ~(GAIH_OKIFUNSPEC)
69
70 #ifndef UNIX_PATH_MAX
71 #define UNIX_PATH_MAX  108
72 #endif
73
74 struct gaih_service
75   {
76     const char *name;
77     int num;
78   };
79
80 struct gaih_servtuple
81   {
82     struct gaih_servtuple *next;
83     int socktype;
84     int protocol;
85     int port;
86   };
87
88 static const struct gaih_servtuple nullserv;
89
90 struct gaih_addrtuple
91   {
92     struct gaih_addrtuple *next;
93     char *name;
94     int family;
95     uint32_t addr[4];
96     uint32_t scopeid;
97   };
98
99 struct gaih_typeproto
100   {
101     int socktype;
102     int protocol;
103     char name[4];
104     int protoflag;
105   };
106
107 /* Values for `protoflag'.  */
108 #define GAI_PROTO_NOSERVICE     1
109 #define GAI_PROTO_PROTOANY      2
110
111 static const struct gaih_typeproto gaih_inet_typeproto[] =
112 {
113   { 0, 0, "", 0 },
114   { SOCK_STREAM, IPPROTO_TCP, "tcp", 0 },
115   { SOCK_DGRAM, IPPROTO_UDP, "udp", 0 },
116   { SOCK_RAW, 0, "raw", GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE },
117   { 0, 0, "", 0 }
118 };
119
120 struct gaih
121   {
122     int family;
123     int (*gaih)(const char *name, const struct gaih_service *service,
124                 const struct addrinfo *req, struct addrinfo **pai);
125   };
126
127 static const struct addrinfo default_hints =
128   {
129     .ai_flags = AI_DEFAULT,
130     .ai_family = PF_UNSPEC,
131     .ai_socktype = 0,
132     .ai_protocol = 0,
133     .ai_addrlen = 0,
134     .ai_addr = NULL,
135     .ai_canonname = NULL,
136     .ai_next = NULL
137   };
138
139
140 #if 0
141 /* Using Unix sockets this way is a security risk.  */
142 static int
143 gaih_local (const char *name, const struct gaih_service *service,
144             const struct addrinfo *req, struct addrinfo **pai)
145 {
146   struct utsname utsname;
147
148   if ((name != NULL) && (req->ai_flags & AI_NUMERICHOST))
149     return GAIH_OKIFUNSPEC | -EAI_NONAME;
150
151   if ((name != NULL) || (req->ai_flags & AI_CANONNAME))
152     if (uname (&utsname) < 0)
153       return -EAI_SYSTEM;
154
155   if (name != NULL)
156     {
157       if (strcmp(name, "localhost") &&
158           strcmp(name, "local") &&
159           strcmp(name, "unix") &&
160           strcmp(name, utsname.nodename))
161         return GAIH_OKIFUNSPEC | -EAI_NONAME;
162     }
163
164   if (req->ai_protocol || req->ai_socktype)
165     {
166       const struct gaih_typeproto *tp = gaih_inet_typeproto + 1;
167
168       while (tp->name[0]
169              && ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0
170                  || (req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
171                  || (req->ai_protocol != 0
172                      && !(tp->protoflag & GAI_PROTO_PROTOANY)
173                      && req->ai_protocol != tp->protocol)))
174         ++tp;
175
176       if (! tp->name[0])
177         {
178           if (req->ai_socktype)
179             return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE);
180           else
181             return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
182         }
183     }
184
185   *pai = malloc (sizeof (struct addrinfo) + sizeof (struct sockaddr_un)
186                  + ((req->ai_flags & AI_CANONNAME)
187                     ? (strlen(utsname.nodename) + 1): 0));
188   if (*pai == NULL)
189     return -EAI_MEMORY;
190
191   (*pai)->ai_next = NULL;
192   (*pai)->ai_flags = req->ai_flags;
193   (*pai)->ai_family = AF_LOCAL;
194   (*pai)->ai_socktype = req->ai_socktype ? req->ai_socktype : SOCK_STREAM;
195   (*pai)->ai_protocol = req->ai_protocol;
196   (*pai)->ai_addrlen = sizeof (struct sockaddr_un);
197   (*pai)->ai_addr = (void *) (*pai) + sizeof (struct addrinfo);
198
199 #if SALEN
200   ((struct sockaddr_un *) (*pai)->ai_addr)->sun_len =
201     sizeof (struct sockaddr_un);
202 #endif /* SALEN */
203
204   ((struct sockaddr_un *)(*pai)->ai_addr)->sun_family = AF_LOCAL;
205   memset(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, 0, UNIX_PATH_MAX);
206
207   if (service)
208     {
209       struct sockaddr_un *sunp = (struct sockaddr_un *) (*pai)->ai_addr;
210
211       if (strchr (service->name, '/') != NULL)
212         {
213           if (strlen (service->name) >= sizeof (sunp->sun_path))
214             return GAIH_OKIFUNSPEC | -EAI_SERVICE;
215
216           strcpy (sunp->sun_path, service->name);
217         }
218       else
219         {
220           if (strlen (P_tmpdir "/") + 1 + strlen (service->name) >=
221               sizeof (sunp->sun_path))
222             return GAIH_OKIFUNSPEC | -EAI_SERVICE;
223
224           __stpcpy (__stpcpy (sunp->sun_path, P_tmpdir "/"), service->name);
225         }
226     }
227   else
228     {
229       /* This is a dangerous use of the interface since there is a time
230          window between the test for the file and the actual creation
231          (done by the caller) in which a file with the same name could
232          be created.  */
233       char *buf = ((struct sockaddr_un *) (*pai)->ai_addr)->sun_path;
234
235       if (__builtin_expect (__path_search (buf, L_tmpnam, NULL, NULL, 0),
236                             0) != 0
237           || __builtin_expect (__gen_tempname (buf, __GT_NOCREATE), 0) != 0)
238         return -EAI_SYSTEM;
239     }
240
241   if (req->ai_flags & AI_CANONNAME)
242     (*pai)->ai_canonname = strcpy ((char *) *pai + sizeof (struct addrinfo)
243                                    + sizeof (struct sockaddr_un),
244                                    utsname.nodename);
245   else
246     (*pai)->ai_canonname = NULL;
247   return 0;
248 }
249 #endif  /* 0 */
250
251 static int
252 gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
253                const struct addrinfo *req, struct gaih_servtuple *st)
254 {
255   struct servent *s;
256   size_t tmpbuflen = 1024;
257   struct servent ts;
258   char *tmpbuf;
259   int r;
260
261   do
262     {
263       tmpbuf = __alloca (tmpbuflen);
264
265       r = __getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen,
266                              &s);
267       if (r != 0 || s == NULL)
268         {
269           if (r == ERANGE)
270             tmpbuflen *= 2;
271           else
272             return GAIH_OKIFUNSPEC | -EAI_SERVICE;
273         }
274     }
275   while (r);
276
277   st->next = NULL;
278   st->socktype = tp->socktype;
279   st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
280                   ? req->ai_protocol : tp->protocol);
281   st->port = s->s_port;
282
283   return 0;
284 }
285
286 #define gethosts(_family, _type) \
287  {                                                                            \
288   int i;                                                                      \
289   int herrno;                                                                 \
290   struct hostent th;                                                          \
291   struct hostent *h;                                                          \
292   char *localcanon = NULL;                                                    \
293   no_data = 0;                                                                \
294   while (1) {                                                                 \
295     rc = 0;                                                                   \
296     status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen,        \
297                                 &rc, &herrno, NULL, &localcanon));            \
298     if (rc != ERANGE || herrno != NETDB_INTERNAL)                             \
299       break;                                                                  \
300     tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);                \
301   }                                                                           \
302   if (status == NSS_STATUS_SUCCESS && rc == 0)                                \
303     h = &th;                                                                  \
304   else                                                                        \
305     h = NULL;                                                                 \
306   if (rc != 0)                                                                \
307     {                                                                         \
308       if (herrno == NETDB_INTERNAL)                                           \
309         {                                                                     \
310           __set_h_errno (herrno);                                             \
311           return -EAI_SYSTEM;                                                 \
312         }                                                                     \
313       if (herrno == TRY_AGAIN)                                                \
314         no_data = EAI_AGAIN;                                                  \
315       else                                                                    \
316         no_data = herrno == NO_DATA;                                          \
317     }                                                                         \
318   else if (h != NULL)                                                         \
319     {                                                                         \
320       for (i = 0; h->h_addr_list[i]; i++)                                     \
321         {                                                                     \
322           if (*pat == NULL)                                                   \
323             {                                                                 \
324               *pat = __alloca (sizeof (struct gaih_addrtuple));               \
325               (*pat)->scopeid = 0;                                            \
326             }                                                                 \
327           uint32_t *addr = (*pat)->addr;                                      \
328           (*pat)->next = NULL;                                                \
329           (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL;                 \
330           if (_family == AF_INET && req->ai_family == AF_INET6)               \
331             {                                                                 \
332               (*pat)->family = AF_INET6;                                      \
333               addr[3] = *(uint32_t *) h->h_addr_list[i];                      \
334               addr[2] = htonl (0xffff);                                       \
335               addr[1] = 0;                                                    \
336               addr[0] = 0;                                                    \
337             }                                                                 \
338           else                                                                \
339             {                                                                 \
340               (*pat)->family = _family;                                       \
341               memcpy (addr, h->h_addr_list[i], sizeof(_type));                \
342             }                                                                 \
343           pat = &((*pat)->next);                                              \
344         }                                                                     \
345                                                                               \
346       if (localcanon != NULL && canon == NULL)                                \
347         canon = strdupa (localcanon);                                         \
348                                                                               \
349       if (_family == AF_INET6 && i > 0)                                       \
350         got_ipv6 = true;                                                      \
351     }                                                                         \
352  }
353
354
355 typedef enum nss_status (*nss_gethostbyname3_r)
356   (const char *name, int af, struct hostent *host,
357    char *buffer, size_t buflen, int *errnop,
358    int *h_errnop, int32_t *ttlp, char **canonp);
359 typedef enum nss_status (*nss_getcanonname_r)
360   (const char *name, char *buffer, size_t buflen, char **result,
361    int *errnop, int *h_errnop);
362 extern service_user *__nss_hosts_database attribute_hidden;
363
364 static int
365 gaih_inet (const char *name, const struct gaih_service *service,
366            const struct addrinfo *req, struct addrinfo **pai)
367 {
368   const struct gaih_typeproto *tp = gaih_inet_typeproto;
369   struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv;
370   struct gaih_addrtuple *at = NULL;
371   int rc;
372   bool got_ipv6 = false;
373   const char *canon = NULL;
374   const char *orig_name = name;
375
376   if (req->ai_protocol || req->ai_socktype)
377     {
378       ++tp;
379
380       while (tp->name[0]
381              && ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
382                  || (req->ai_protocol != 0
383                      && !(tp->protoflag & GAI_PROTO_PROTOANY)
384                      && req->ai_protocol != tp->protocol)))
385         ++tp;
386
387       if (! tp->name[0])
388         {
389           if (req->ai_socktype)
390             return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE);
391           else
392             return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
393         }
394     }
395
396   if (service != NULL)
397     {
398       if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
399         return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
400
401       if (service->num < 0)
402         {
403           if (tp->name[0])
404             {
405               st = (struct gaih_servtuple *)
406                 __alloca (sizeof (struct gaih_servtuple));
407
408               if ((rc = gaih_inet_serv (service->name, tp, req, st)))
409                 return rc;
410             }
411           else
412             {
413               struct gaih_servtuple **pst = &st;
414               for (tp++; tp->name[0]; tp++)
415                 {
416                   struct gaih_servtuple *newp;
417
418                   if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
419                     continue;
420
421                   if (req->ai_socktype != 0
422                       && req->ai_socktype != tp->socktype)
423                     continue;
424                   if (req->ai_protocol != 0
425                       && !(tp->protoflag & GAI_PROTO_PROTOANY)
426                       && req->ai_protocol != tp->protocol)
427                     continue;
428
429                   newp = (struct gaih_servtuple *)
430                     __alloca (sizeof (struct gaih_servtuple));
431
432                   if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
433                     {
434                       if (rc & GAIH_OKIFUNSPEC)
435                         continue;
436                       return rc;
437                     }
438
439                   *pst = newp;
440                   pst = &(newp->next);
441                 }
442               if (st == (struct gaih_servtuple *) &nullserv)
443                 return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
444             }
445         }
446       else
447         {
448           if (req->ai_socktype || req->ai_protocol)
449             {
450               st = __alloca (sizeof (struct gaih_servtuple));
451               st->next = NULL;
452               st->socktype = tp->socktype;
453               st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
454                               ? req->ai_protocol : tp->protocol);
455               st->port = htons (service->num);
456             }
457           else
458             {
459               /* Neither socket type nor protocol is set.  Return all
460                  socket types we know about.  */
461               struct gaih_servtuple **lastp = &st;
462               for (tp = gaih_inet_typeproto + 1; tp->name[0]; ++tp)
463                 if ((tp->protoflag & GAI_PROTO_NOSERVICE) == 0)
464                   {
465                     struct gaih_servtuple *newp;
466
467                     newp = __alloca (sizeof (struct gaih_servtuple));
468                     newp->next = NULL;
469                     newp->socktype = tp->socktype;
470                     newp->protocol = tp->protocol;
471                     newp->port = htons (service->num);
472
473                     *lastp = newp;
474                     lastp = &newp->next;
475                   }
476             }
477         }
478     }
479   else if (req->ai_socktype || req->ai_protocol)
480     {
481       st = __alloca (sizeof (struct gaih_servtuple));
482       st->next = NULL;
483       st->socktype = tp->socktype;
484       st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
485                       ? req->ai_protocol : tp->protocol);
486       st->port = 0;
487     }
488   else
489     {
490       /* Neither socket type nor protocol is set.  Return all socket types
491          we know about.  */
492       struct gaih_servtuple **lastp = &st;
493       for (++tp; tp->name[0]; ++tp)
494         {
495           struct gaih_servtuple *newp;
496
497           newp = __alloca (sizeof (struct gaih_servtuple));
498           newp->next = NULL;
499           newp->socktype = tp->socktype;
500           newp->protocol = tp->protocol;
501           newp->port = 0;
502
503           *lastp = newp;
504           lastp = &newp->next;
505         }
506     }
507
508   if (name != NULL)
509     {
510       at = __alloca (sizeof (struct gaih_addrtuple));
511
512       at->family = AF_UNSPEC;
513       at->scopeid = 0;
514       at->next = NULL;
515
516 #ifdef HAVE_LIBIDN
517       if (req->ai_flags & AI_IDN)
518         {
519           int idn_flags = 0;
520           if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
521             idn_flags |= IDNA_ALLOW_UNASSIGNED;
522           if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
523             idn_flags |= IDNA_USE_STD3_ASCII_RULES;
524
525           char *p = NULL;
526           rc = __idna_to_ascii_lz (name, &p, idn_flags);
527           if (rc != IDNA_SUCCESS)
528             {
529               if (rc == IDNA_MALLOC_ERROR)
530                 return -EAI_MEMORY;
531               if (rc == IDNA_DLOPEN_ERROR)
532                 return -EAI_SYSTEM;
533               return -EAI_IDN_ENCODE;
534             }
535           /* In case the output string is the same as the input string
536              no new string has been allocated.  */
537           if (p != name)
538             {
539               name = strdupa (p);
540               free (p);
541             }
542         }
543 #endif
544
545       if (__inet_aton (name, (struct in_addr *) at->addr) != 0)
546         {
547           if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
548             at->family = AF_INET;
549           else if (req->ai_family == AF_INET6 && req->ai_flags & AI_V4MAPPED)
550             {
551               at->addr[3] = at->addr[0];
552               at->addr[2] = htonl (0xffff);
553               at->addr[1] = 0;
554               at->addr[0] = 0;
555               at->family = AF_INET6;
556             }
557           else
558             return -EAI_ADDRFAMILY;
559
560         dupname:
561           if (req->ai_flags & AI_CANONNAME)
562             {
563               canon = strdup (name);
564               if (canon == NULL)
565                 return -EAI_MEMORY;
566             }
567         }
568
569       if (at->family == AF_UNSPEC)
570         {
571           char *namebuf = strdupa (name);
572           char *scope_delim;
573
574           scope_delim = strchr (namebuf, SCOPE_DELIMITER);
575           if (scope_delim != NULL)
576             *scope_delim = '\0';
577
578           if (inet_pton (AF_INET6, namebuf, at->addr) > 0)
579             {
580               if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
581                 at->family = AF_INET6;
582               else if (req->ai_family == AF_INET
583                        && IN6_IS_ADDR_V4MAPPED (at->addr))
584                 {
585                   at->addr[0] = at->addr[3];
586                   at->family = AF_INET;
587                 }
588               else
589                 return -EAI_ADDRFAMILY;
590
591               if (scope_delim != NULL)
592                 {
593                   int try_numericscope = 0;
594                   if (IN6_IS_ADDR_LINKLOCAL (at->addr)
595                       || IN6_IS_ADDR_MC_LINKLOCAL (at->addr))
596                     {
597                       at->scopeid = if_nametoindex (scope_delim + 1);
598                       if (at->scopeid == 0)
599                         try_numericscope = 1;
600                     }
601                   else
602                     try_numericscope = 1;
603
604                   if (try_numericscope != 0)
605                     {
606                       char *end;
607                       assert (sizeof (uint32_t) <= sizeof (unsigned long));
608                       at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
609                                                         10);
610                       if (*end != '\0')
611                         return GAIH_OKIFUNSPEC | -EAI_NONAME;
612                     }
613                 }
614
615               goto dupname;
616             }
617         }
618
619       if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0)
620         {
621           struct gaih_addrtuple **pat = &at;
622           int no_data = 0;
623           int no_inet6_data = 0;
624           service_user *nip = NULL;
625           enum nss_status inet6_status = NSS_STATUS_UNAVAIL;
626           enum nss_status status = NSS_STATUS_UNAVAIL;
627           int no_more;
628           int old_res_options;
629
630           /* If we do not have to look for IPv4 and IPv6 together, use
631              the simple, old functions.  */
632           if (req->ai_family == AF_INET || req->ai_family == AF_INET6)
633             {
634               int family = req->ai_family;
635               size_t tmpbuflen = 512;
636               char *tmpbuf = alloca (tmpbuflen);
637               int rc;
638               struct hostent th;
639               struct hostent *h;
640               int herrno;
641
642             simple_again:
643               while (1)
644                 {
645                   rc = __gethostbyname2_r (name, family, &th, tmpbuf,
646                                            tmpbuflen, &h, &herrno);
647                   if (rc != ERANGE || herrno != NETDB_INTERNAL)
648                     break;
649                   tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
650                 }
651
652               if (rc == 0)
653                 {
654                   if (h == NULL)
655                     {
656                       if (req->ai_family == AF_INET6
657                           && (req->ai_flags & AI_V4MAPPED)
658                           && family == AF_INET6)
659                         {
660                           /* Try again, this time looking for IPv4
661                              addresses.  */
662                           family = AF_INET;
663                           goto simple_again;
664                         }
665                     }
666                   else
667                     {
668                       /* We found data, now convert it into the list.  */
669                       for (int i = 0; h->h_addr_list[i]; ++i)
670                         {
671                           if (*pat == NULL)
672                             {
673                               *pat = __alloca (sizeof (struct gaih_addrtuple));
674                               (*pat)->scopeid = 0;
675                             }
676                           (*pat)->next = NULL;
677                           (*pat)->family = req->ai_family;
678                           if (family == req->ai_family)
679                             memcpy ((*pat)->addr, h->h_addr_list[i],
680                                     h->h_length);
681                           else
682                             {
683                               int32_t *addr = (uint32_t *) (*pat)->addr;
684                               addr[3] = *(uint32_t *) h->h_addr_list[i];
685                               addr[2] = htonl (0xffff);
686                               addr[1] = 0;
687                               addr[0] = 0;
688                             }
689                           pat = &((*pat)->next);
690                         }
691                     }
692                 }
693               else
694                 {
695                   if (herrno == NETDB_INTERNAL)
696                     {
697                       __set_h_errno (herrno);
698                       return -EAI_SYSTEM;
699                     }
700                   if (herrno == TRY_AGAIN)
701                     {
702                       return -EAI_AGAIN;
703                     }
704                   /* We made requests but they turned out no data.
705                      The name is known, though.  */
706                   return (GAIH_OKIFUNSPEC | -EAI_NODATA);
707                 }
708
709               goto process_list;
710             }
711
712 #ifdef USE_NSCD
713           if (__nss_not_use_nscd_hosts > 0
714               && ++__nss_not_use_nscd_hosts > NSS_NSCD_RETRY)
715             __nss_not_use_nscd_hosts = 0;
716
717           if (!__nss_not_use_nscd_hosts)
718             {
719               /* Try to use nscd.  */
720               struct nscd_ai_result *air = NULL;
721               int herrno;
722               int err = __nscd_getai (name, &air, &herrno);
723               if (air != NULL)
724                 {
725                   /* Transform into gaih_addrtuple list.  */
726                   bool added_canon = (req->ai_flags & AI_CANONNAME) == 0;
727                   char *addrs = air->addrs;
728
729                   for (int i = 0; i < air->naddrs; ++i)
730                     {
731                       socklen_t size = (air->family[i] == AF_INET
732                                         ? INADDRSZ : IN6ADDRSZ);
733                       if (*pat == NULL)
734                         {
735                           *pat = __alloca (sizeof (struct gaih_addrtuple));
736                           (*pat)->scopeid = 0;
737                         }
738                       uint32_t *pataddr = (*pat)->addr;
739                       (*pat)->next = NULL;
740                       if (added_canon || air->canon == NULL)
741                         (*pat)->name = NULL;
742                       else
743                         canon = (*pat)->name = strdupa (air->canon);
744
745                       if (air->family[i] == AF_INET
746                           && req->ai_family == AF_INET6
747                           && (req->ai_flags & AI_V4MAPPED))
748                         {
749                           (*pat)->family = AF_INET6;
750                           pataddr[3] = *(uint32_t *) addrs;
751                           pataddr[2] = htonl (0xffff);
752                           pataddr[1] = 0;
753                           pataddr[0] = 0;
754                           pat = &((*pat)->next);
755                           added_canon = true;
756                         }
757                       else if (req->ai_family == AF_UNSPEC
758                                || air->family[i] == req->ai_family)
759                         {
760                           (*pat)->family = air->family[i];
761                           memcpy (pataddr, addrs, size);
762                           pat = &((*pat)->next);
763                           added_canon = true;
764                           if (air->family[i] == AF_INET6)
765                             got_ipv6 = true;
766                         }
767                       addrs += size;
768                     }
769
770                   free (air);
771
772                   if (at->family == AF_UNSPEC)
773                     return (GAIH_OKIFUNSPEC | -EAI_NONAME);
774
775                   goto process_list;
776                 }
777               else if (err != 0 && __nss_not_use_nscd_hosts == 0)
778                 {
779                   if (herrno == NETDB_INTERNAL && errno == ENOMEM)
780                     return -EAI_MEMORY;
781                   if (herrno == TRY_AGAIN)
782                     return -EAI_AGAIN;
783                   return -EAI_SYSTEM;
784                 }
785             }
786 #endif
787
788           if (__nss_hosts_database != NULL)
789             {
790               no_more = 0;
791               nip = __nss_hosts_database;
792             }
793           else
794             no_more = __nss_database_lookup ("hosts", NULL,
795                                              "dns [!UNAVAIL=return] files",
796                                              &nip);
797
798           if (__res_maybe_init (&_res, 0) == -1)
799             no_more = 1;
800
801           /* If we are looking for both IPv4 and IPv6 address we don't
802              want the lookup functions to automatically promote IPv4
803              addresses to IPv6 addresses.  Currently this is decided
804              by setting the RES_USE_INET6 bit in _res.options.  */
805           old_res_options = _res.options;
806           _res.options &= ~RES_USE_INET6;
807
808           size_t tmpbuflen = 512;
809           char *tmpbuf = alloca (tmpbuflen);
810
811           while (!no_more)
812             {
813               nss_gethostbyname3_r fct = NULL;
814               if (req->ai_flags & AI_CANONNAME)
815                 /* No need to use this function if we do not look for
816                    the canonical name.  The function does not exist in
817                    all NSS modules and therefore the lookup would
818                    often fail.  */
819                 fct = __nss_lookup_function (nip, "gethostbyname3_r");
820               if (fct == NULL)
821                 /* We are cheating here.  The gethostbyname2_r function does
822                    not have the same interface as gethostbyname3_r but the
823                    extra arguments the latter takes are added at the end.
824                    So the gethostbyname2_r code will just ignore them.  */
825                 fct = __nss_lookup_function (nip, "gethostbyname2_r");
826
827               if (fct != NULL)
828                 {
829                   if (req->ai_family == AF_INET6
830                       || req->ai_family == AF_UNSPEC)
831                     {
832                       gethosts (AF_INET6, struct in6_addr);
833                       no_inet6_data = no_data;
834                       inet6_status = status;
835                     }
836                   if (req->ai_family == AF_INET
837                       || req->ai_family == AF_UNSPEC
838                       || (req->ai_family == AF_INET6
839                           && (req->ai_flags & AI_V4MAPPED)
840                           /* Avoid generating the mapped addresses if we
841                              know we are not going to need them.  */
842                           && ((req->ai_flags & AI_ALL) || !got_ipv6)))
843                     {
844                       gethosts (AF_INET, struct in_addr);
845
846                       if (req->ai_family == AF_INET)
847                         {
848                           no_inet6_data = no_data;
849                           inet6_status = status;
850                         }
851                     }
852
853                   /* If we found one address for AF_INET or AF_INET6,
854                      don't continue the search.  */
855                   if (inet6_status == NSS_STATUS_SUCCESS
856                       || status == NSS_STATUS_SUCCESS)
857                     {
858                       if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
859                         {
860                           /* If we need the canonical name, get it
861                              from the same service as the result.  */
862                           nss_getcanonname_r cfct;
863                           int herrno;
864
865                           cfct = __nss_lookup_function (nip, "getcanonname_r");
866                           if (cfct != NULL)
867                             {
868                               const size_t max_fqdn_len = 256;
869                               char *buf = alloca (max_fqdn_len);
870                               char *s;
871
872                               if (DL_CALL_FCT (cfct, (at->name ?: name, buf,
873                                                       max_fqdn_len, &s, &rc,
874                                                       &herrno))
875                                   == NSS_STATUS_SUCCESS)
876                                 canon = s;
877                               else
878                                 /* Set to name now to avoid using
879                                    gethostbyaddr.  */
880                                 canon = name;
881                             }
882                         }
883
884                       break;
885                     }
886
887                   /* We can have different states for AF_INET and
888                      AF_INET6.  Try to find a useful one for both.  */
889                   if (inet6_status == NSS_STATUS_TRYAGAIN)
890                     status = NSS_STATUS_TRYAGAIN;
891                   else if (status == NSS_STATUS_UNAVAIL &&
892                            inet6_status != NSS_STATUS_UNAVAIL)
893                     status = inet6_status;
894                 }
895
896               if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
897                 break;
898
899               if (nip->next == NULL)
900                 no_more = -1;
901               else
902                 nip = nip->next;
903             }
904
905           _res.options = old_res_options;
906
907           if (no_data != 0 && no_inet6_data != 0)
908             {
909               /* If both requests timed out report this.  */
910               if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
911                 return -EAI_AGAIN;
912
913               /* We made requests but they turned out no data.  The name
914                  is known, though.  */
915               return (GAIH_OKIFUNSPEC | -EAI_NODATA);
916             }
917         }
918
919     process_list:
920       if (at->family == AF_UNSPEC)
921         return (GAIH_OKIFUNSPEC | -EAI_NONAME);
922     }
923   else
924     {
925       struct gaih_addrtuple *atr;
926       atr = at = __alloca (sizeof (struct gaih_addrtuple));
927       memset (at, '\0', sizeof (struct gaih_addrtuple));
928
929       if (req->ai_family == AF_UNSPEC)
930         {
931           at->next = __alloca (sizeof (struct gaih_addrtuple));
932           memset (at->next, '\0', sizeof (struct gaih_addrtuple));
933         }
934
935       if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
936         {
937           at->family = AF_INET6;
938           if ((req->ai_flags & AI_PASSIVE) == 0)
939             memcpy (at->addr, &in6addr_loopback, sizeof (struct in6_addr));
940           atr = at->next;
941         }
942
943       if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
944         {
945           atr->family = AF_INET;
946           if ((req->ai_flags & AI_PASSIVE) == 0)
947             atr->addr[0] = htonl (INADDR_LOOPBACK);
948         }
949     }
950
951   if (pai == NULL)
952     return 0;
953
954   {
955     struct gaih_servtuple *st2;
956     struct gaih_addrtuple *at2 = at;
957     size_t socklen;
958     sa_family_t family;
959
960     /*
961       buffer is the size of an unformatted IPv6 address in printable format.
962      */
963     while (at2 != NULL)
964       {
965         /* Only the first entry gets the canonical name.  */
966         if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
967           {
968             if (canon == NULL)
969               {
970                 struct hostent *h = NULL;
971                 int herrno;
972                 struct hostent th;
973                 size_t tmpbuflen = 512;
974                 char *tmpbuf = NULL;
975
976                 do
977                   {
978                     tmpbuf = extend_alloca (tmpbuf, tmpbuflen, tmpbuflen * 2);
979                     rc = __gethostbyaddr_r (at2->addr,
980                                             ((at2->family == AF_INET6)
981                                              ? sizeof (struct in6_addr)
982                                              : sizeof (struct in_addr)),
983                                             at2->family, &th, tmpbuf,
984                                             tmpbuflen, &h, &herrno);
985                   }
986                 while (rc == ERANGE && herrno == NETDB_INTERNAL);
987
988                 if (rc != 0 && herrno == NETDB_INTERNAL)
989                   {
990                     __set_h_errno (herrno);
991                     return -EAI_SYSTEM;
992                   }
993
994                 if (h != NULL)
995                   canon = h->h_name;
996                 else
997                   {
998                     assert (orig_name != NULL);
999                     /* If the canonical name cannot be determined, use
1000                        the passed in string.  */
1001                     canon = orig_name;
1002                   }
1003               }
1004
1005 #ifdef HAVE_LIBIDN
1006             if (req->ai_flags & AI_CANONIDN)
1007               {
1008                 int idn_flags = 0;
1009                 if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
1010                   idn_flags |= IDNA_ALLOW_UNASSIGNED;
1011                 if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
1012                   idn_flags |= IDNA_USE_STD3_ASCII_RULES;
1013
1014                 char *out;
1015                 int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
1016                 if (rc != IDNA_SUCCESS)
1017                   {
1018                     if (rc == IDNA_MALLOC_ERROR)
1019                       return -EAI_MEMORY;
1020                     if (rc == IDNA_DLOPEN_ERROR)
1021                       return -EAI_SYSTEM;
1022                     return -EAI_IDN_ENCODE;
1023                   }
1024                 /* In case the output string is the same as the input
1025                    string no new string has been allocated.  Otherwise
1026                    make a copy.  */
1027                 if (out == canon)
1028                   goto make_copy;
1029               }
1030             else
1031 #endif
1032               {
1033 #ifdef HAVE_LIBIDN
1034               make_copy:
1035 #endif
1036                 canon = strdup (canon);
1037                 if (canon == NULL)
1038                   return -EAI_MEMORY;
1039               }
1040           }
1041
1042         if (at2->family == AF_INET6)
1043           {
1044             family = AF_INET6;
1045             socklen = sizeof (struct sockaddr_in6);
1046
1047             /* If we looked up IPv4 mapped address discard them here if
1048                the caller isn't interested in all address and we have
1049                found at least one IPv6 address.  */
1050             if (got_ipv6
1051                 && (req->ai_flags & (AI_V4MAPPED|AI_ALL)) == AI_V4MAPPED
1052                 && IN6_IS_ADDR_V4MAPPED (at2->addr))
1053               goto ignore;
1054           }
1055         else
1056           {
1057             family = AF_INET;
1058             socklen = sizeof (struct sockaddr_in);
1059           }
1060
1061         for (st2 = st; st2 != NULL; st2 = st2->next)
1062           {
1063             struct addrinfo *ai;
1064             ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
1065             if (ai == NULL)
1066               return -EAI_MEMORY;
1067
1068             ai->ai_flags = req->ai_flags;
1069             ai->ai_family = family;
1070             ai->ai_socktype = st2->socktype;
1071             ai->ai_protocol = st2->protocol;
1072             ai->ai_addrlen = socklen;
1073             ai->ai_addr = (void *) (ai + 1);
1074
1075             /* We only add the canonical name once.  */
1076             ai->ai_canonname = (char *) canon;
1077             canon = NULL;
1078
1079 #if SALEN
1080             ai->ai_addr->sa_len = socklen;
1081 #endif /* SALEN */
1082             ai->ai_addr->sa_family = family;
1083
1084             if (family == AF_INET6)
1085               {
1086                 struct sockaddr_in6 *sin6p =
1087                   (struct sockaddr_in6 *) ai->ai_addr;
1088
1089                 sin6p->sin6_port = st2->port;
1090                 sin6p->sin6_flowinfo = 0;
1091                 memcpy (&sin6p->sin6_addr,
1092                         at2->addr, sizeof (struct in6_addr));
1093                 sin6p->sin6_scope_id = at2->scopeid;
1094               }
1095             else
1096               {
1097                 struct sockaddr_in *sinp =
1098                   (struct sockaddr_in *) ai->ai_addr;
1099                 sinp->sin_port = st2->port;
1100                 memcpy (&sinp->sin_addr,
1101                         at2->addr, sizeof (struct in_addr));
1102                 memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
1103               }
1104
1105             pai = &(ai->ai_next);
1106           }
1107         *pai = NULL;
1108
1109       ignore:
1110         at2 = at2->next;
1111       }
1112   }
1113   return 0;
1114 }
1115
1116 static struct gaih gaih[] =
1117   {
1118     { PF_INET6, gaih_inet },
1119     { PF_INET, gaih_inet },
1120 #if 0
1121     { PF_LOCAL, gaih_local },
1122 #endif
1123     { PF_UNSPEC, NULL }
1124   };
1125
1126 struct sort_result
1127 {
1128   struct addrinfo *dest_addr;
1129   struct sockaddr_storage source_addr;
1130   uint8_t source_addr_len;
1131   bool got_source_addr;
1132 };
1133
1134
1135 static int
1136 get_scope (const struct sockaddr_storage *ss)
1137 {
1138   int scope;
1139   if (ss->ss_family == PF_INET6)
1140     {
1141       const struct sockaddr_in6 *in6 = (const struct sockaddr_in6 *) ss;
1142
1143       if (! IN6_IS_ADDR_MULTICAST (&in6->sin6_addr))
1144         {
1145           if (IN6_IS_ADDR_LINKLOCAL (&in6->sin6_addr))
1146             scope = 2;
1147           else if (IN6_IS_ADDR_SITELOCAL (&in6->sin6_addr))
1148             scope = 5;
1149           else
1150             /* XXX Is this the correct default behavior?  */
1151             scope = 14;
1152         }
1153       else
1154         scope = in6->sin6_addr.s6_addr[1] & 0xf;
1155     }
1156   else if (ss->ss_family == PF_INET)
1157     {
1158       const struct sockaddr_in *in = (const struct sockaddr_in *) ss;
1159       const uint8_t *addr = (const uint8_t *) &in->sin_addr;
1160
1161       /* RFC 3484 specifies how to map IPv6 addresses to scopes.
1162          169.254/16 and 127/8 are link-local.  */
1163       if ((addr[0] == 169 && addr[1] == 254) || addr[0] == 127)
1164         scope = 2;
1165       else if (addr[0] == 10 || (addr[0] == 172 && addr[1] == 16)
1166                || (addr[0] == 192 && addr[1] == 168))
1167         scope = 5;
1168       else
1169         scope = 14;
1170     }
1171   else
1172     /* XXX What is a good default?  */
1173     scope = 15;
1174
1175   return scope;
1176 }
1177
1178
1179 /* XXX The system administrator should be able to install other
1180    tables.  We need to make this configurable.  The problem is that
1181    the kernel is also involved since it needs the same table.  */
1182 static const struct prefixlist
1183 {
1184   struct in6_addr prefix;
1185   unsigned int bits;
1186   int val;
1187 } default_labels[] =
1188   {
1189     /* See RFC 3484 for the details.  */
1190     { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1191                                   0x0000, 0x0000, 0x0000, 0x0001 } } },
1192       128, 0 },
1193     { { .in6_u = { .u6_addr16 = { 0x2002, 0x0000, 0x0000, 0x0000,
1194                                   0x0000, 0x0000, 0x0000, 0x0000 } } },
1195       16, 2 },
1196     { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1197                                   0x0000, 0x0000, 0x0000, 0x0000 } } },
1198       96, 3 },
1199     { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1200                                   0x0000, 0xffff, 0x0000, 0x0000 } } },
1201       96, 4 },
1202     { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1203                                   0x0000, 0x0000, 0x0000, 0x0000 } } },
1204       0, 1 }
1205   };
1206
1207
1208 static const struct prefixlist default_precedence[] =
1209   {
1210     /* See RFC 3484 for the details.  */
1211     { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1212                                   0x0000, 0x0000, 0x0000, 0x0001 } } },
1213       128, 50 },
1214     { { .in6_u = { .u6_addr16 = { 0x2002, 0x0000, 0x0000, 0x0000,
1215                                   0x0000, 0x0000, 0x0000, 0x0000 } } },
1216       16, 30 },
1217     { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1218                                   0x0000, 0x0000, 0x0000, 0x0000 } } },
1219       96, 20 },
1220     { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1221                                   0x0000, 0xffff, 0x0000, 0x0000 } } },
1222       96, 10 },
1223     { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1224                                   0x0000, 0x0000, 0x0000, 0x0000 } } },
1225       0, 40 }
1226   };
1227
1228
1229 static int
1230 match_prefix (const struct sockaddr_storage *ss, const struct prefixlist *list,
1231               int default_val)
1232 {
1233   int idx;
1234   struct sockaddr_in6 in6_mem;
1235   const struct sockaddr_in6 *in6;
1236
1237   if (ss->ss_family == PF_INET6)
1238     in6 = (const struct sockaddr_in6 *) ss;
1239   else if (ss->ss_family == PF_INET)
1240     {
1241       const struct sockaddr_in *in = (const struct sockaddr_in *) ss;
1242
1243       /* Convert to IPv6 address.  */
1244       in6_mem.sin6_family = PF_INET6;
1245       in6_mem.sin6_port = in->sin_port;
1246       in6_mem.sin6_flowinfo = 0;
1247       if (in->sin_addr.s_addr == htonl (0x7f000001))
1248         in6_mem.sin6_addr = (struct in6_addr) IN6ADDR_LOOPBACK_INIT;
1249       else
1250         {
1251           /* Construct a V4-to-6 mapped address.  */
1252           memset (&in6_mem.sin6_addr, '\0', sizeof (in6_mem.sin6_addr));
1253           in6_mem.sin6_addr.s6_addr16[5] = 0xffff;
1254           in6_mem.sin6_addr.s6_addr32[3] = in->sin_addr.s_addr;
1255           in6_mem.sin6_scope_id = 0;
1256         }
1257
1258       in6 = &in6_mem;
1259     }
1260   else
1261     return default_val;
1262
1263   for (idx = 0; ; ++idx)
1264     {
1265       unsigned int bits = list[idx].bits;
1266       uint8_t *mask = list[idx].prefix.s6_addr;
1267       uint8_t *val = in6->sin6_addr.s6_addr;
1268
1269       while (bits > 8)
1270         {
1271           if (*mask != *val)
1272             break;
1273
1274           ++mask;
1275           ++val;
1276           bits -= 8;
1277         }
1278
1279       if (bits < 8)
1280         {
1281           if ((*mask & (0xff00 >> bits)) == (*val & (0xff00 >> bits)))
1282             /* Match!  */
1283             break;
1284         }
1285     }
1286
1287   return list[idx].val;
1288 }
1289
1290
1291 static int
1292 get_label (const struct sockaddr_storage *ss)
1293 {
1294   /* XXX What is a good default value?  */
1295   return match_prefix (ss, default_labels, INT_MAX);
1296 }
1297
1298
1299 static int
1300 get_precedence (const struct sockaddr_storage *ss)
1301 {
1302   /* XXX What is a good default value?  */
1303   return match_prefix (ss, default_precedence, 0);
1304 }
1305
1306
1307 static int
1308 rfc3484_sort (const void *p1, const void *p2)
1309 {
1310   const struct sort_result *a1 = (const struct sort_result *) p1;
1311   const struct sort_result *a2 = (const struct sort_result *) p2;
1312
1313   /* Rule 1: Avoid unusable destinations.
1314      We have the got_source_addr flag set if the destination is reachable.  */
1315   if (a1->got_source_addr && ! a2->got_source_addr)
1316     return -1;
1317   if (! a1->got_source_addr && a2->got_source_addr)
1318     return 1;
1319
1320
1321   /* Rule 2: Prefer matching scope.  Only interesting if both
1322      destination addresses are IPv6.  */
1323   int a1_dst_scope
1324     = get_scope ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
1325
1326   int a2_dst_scope
1327     = get_scope ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
1328
1329   if (a1->got_source_addr)
1330     {
1331       int a1_src_scope = get_scope (&a1->source_addr);
1332       int a2_src_scope = get_scope (&a2->source_addr);
1333
1334       if (a1_dst_scope == a1_src_scope && a2_dst_scope != a2_src_scope)
1335         return -1;
1336       if (a1_dst_scope != a1_src_scope && a2_dst_scope == a2_src_scope)
1337         return 1;
1338     }
1339
1340
1341   /* Rule 3: Avoid deprecated addresses.
1342      That's something only the kernel could decide.  */
1343
1344   /* Rule 4: Prefer home addresses.
1345      Another thing only the kernel can decide.  */
1346
1347   /* Rule 5: Prefer matching label.  */
1348   if (a1->got_source_addr)
1349     {
1350       int a1_dst_label
1351         = get_label ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
1352       int a1_src_label = get_label (&a1->source_addr);
1353
1354       int a2_dst_label
1355         = get_label ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
1356       int a2_src_label = get_label (&a2->source_addr);
1357
1358       if (a1_dst_label == a1_src_label && a2_dst_label != a2_src_label)
1359         return -1;
1360       if (a1_dst_label != a1_src_label && a2_dst_label == a2_src_label)
1361         return 1;
1362     }
1363
1364
1365   /* Rule 6: Prefer higher precedence.  */
1366   int a1_prec
1367     = get_precedence ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
1368   int a2_prec
1369     = get_precedence ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
1370
1371   if (a1_prec > a2_prec)
1372     return -1;
1373   if (a1_prec < a2_prec)
1374     return 1;
1375
1376
1377   /* Rule 7: Prefer native transport.
1378      XXX How to recognize tunnels?  */
1379
1380
1381   /* Rule 8: Prefer smaller scope.  */
1382   if (a1_dst_scope < a2_dst_scope)
1383     return -1;
1384   if (a1_dst_scope > a2_dst_scope)
1385     return 1;
1386
1387
1388   /* Rule 9: Use longest matching prefix.  */
1389   if (a1->got_source_addr
1390       && a1->dest_addr->ai_family == a2->dest_addr->ai_family)
1391     {
1392       int bit1 = 0;
1393       int bit2 = 0;
1394
1395       if (a1->dest_addr->ai_family == PF_INET)
1396         {
1397           assert (a1->source_addr.ss_family == PF_INET);
1398           assert (a2->source_addr.ss_family == PF_INET);
1399
1400           struct sockaddr_in *in1_dst;
1401           struct sockaddr_in *in1_src;
1402           struct sockaddr_in *in2_dst;
1403           struct sockaddr_in *in2_src;
1404
1405           in1_dst = (struct sockaddr_in *) a1->dest_addr->ai_addr;
1406           in1_src = (struct sockaddr_in *) &a1->source_addr;
1407           in2_dst = (struct sockaddr_in *) a2->dest_addr->ai_addr;
1408           in2_src = (struct sockaddr_in *) &a2->source_addr;
1409
1410           bit1 = ffs (in1_dst->sin_addr.s_addr ^ in1_src->sin_addr.s_addr);
1411           bit2 = ffs (in2_dst->sin_addr.s_addr ^ in2_src->sin_addr.s_addr);
1412         }
1413       else if (a1->dest_addr->ai_family == PF_INET6)
1414         {
1415           assert (a1->source_addr.ss_family == PF_INET6);
1416           assert (a2->source_addr.ss_family == PF_INET6);
1417
1418           struct sockaddr_in6 *in1_dst;
1419           struct sockaddr_in6 *in1_src;
1420           struct sockaddr_in6 *in2_dst;
1421           struct sockaddr_in6 *in2_src;
1422
1423           in1_dst = (struct sockaddr_in6 *) a1->dest_addr->ai_addr;
1424           in1_src = (struct sockaddr_in6 *) &a1->source_addr;
1425           in2_dst = (struct sockaddr_in6 *) a2->dest_addr->ai_addr;
1426           in2_src = (struct sockaddr_in6 *) &a2->source_addr;
1427
1428           int i;
1429           for (i = 0; i < 4; ++i)
1430             if (in1_dst->sin6_addr.s6_addr32[i]
1431                 != in1_src->sin6_addr.s6_addr32[i]
1432                 || (in2_dst->sin6_addr.s6_addr32[i]
1433                     != in2_src->sin6_addr.s6_addr32[i]))
1434               break;
1435
1436           if (i < 4)
1437             {
1438               bit1 = ffs (in1_dst->sin6_addr.s6_addr32[i]
1439                           ^ in1_src->sin6_addr.s6_addr32[i]);
1440               bit2 = ffs (in2_dst->sin6_addr.s6_addr32[i]
1441                           ^ in2_src->sin6_addr.s6_addr32[i]);
1442             }
1443         }
1444
1445       if (bit1 > bit2)
1446         return -1;
1447       if (bit1 < bit2)
1448         return 1;
1449     }
1450
1451
1452   /* Rule 10: Otherwise, leave the order unchanged.  */
1453   return 0;
1454 }
1455
1456
1457 int
1458 getaddrinfo (const char *name, const char *service,
1459              const struct addrinfo *hints, struct addrinfo **pai)
1460 {
1461   int i = 0, j = 0, last_i = 0;
1462   int nresults = 0;
1463   struct addrinfo *p = NULL, **end;
1464   struct gaih *g = gaih, *pg = NULL;
1465   struct gaih_service gaih_service, *pservice;
1466   struct addrinfo local_hints;
1467
1468   if (name != NULL && name[0] == '*' && name[1] == 0)
1469     name = NULL;
1470
1471   if (service != NULL && service[0] == '*' && service[1] == 0)
1472     service = NULL;
1473
1474   if (name == NULL && service == NULL)
1475     return EAI_NONAME;
1476
1477   if (hints == NULL)
1478     hints = &default_hints;
1479
1480   if (hints->ai_flags
1481       & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|AI_ADDRCONFIG|AI_V4MAPPED
1482 #ifdef HAVE_LIBIDN
1483           |AI_IDN|AI_CANONIDN|AI_IDN_ALLOW_UNASSIGNED
1484           |AI_IDN_USE_STD3_ASCII_RULES
1485 #endif
1486           |AI_NUMERICSERV|AI_ALL))
1487     return EAI_BADFLAGS;
1488
1489   if ((hints->ai_flags & AI_CANONNAME) && name == NULL)
1490     return EAI_BADFLAGS;
1491
1492   if (hints->ai_flags & AI_ADDRCONFIG)
1493     {
1494       /* Determine whether we have IPv4 or IPv6 interfaces or both.
1495          We cannot cache the results since new interfaces could be
1496          added at any time.  */
1497       bool seen_ipv4;
1498       bool seen_ipv6;
1499       __check_pf (&seen_ipv4, &seen_ipv6);
1500
1501       /* Now make a decision on what we return, if anything.  */
1502       if (hints->ai_family == PF_UNSPEC && (seen_ipv4 || seen_ipv6))
1503         {
1504           /* If we haven't seen both IPv4 and IPv6 interfaces we can
1505              narrow down the search.  */
1506           if (! seen_ipv4 || ! seen_ipv6)
1507             {
1508               local_hints = *hints;
1509               local_hints.ai_family = seen_ipv4 ? PF_INET : PF_INET6;
1510               hints = &local_hints;
1511             }
1512         }
1513       else if ((hints->ai_family == PF_INET && ! seen_ipv4)
1514                || (hints->ai_family == PF_INET6 && ! seen_ipv6))
1515         /* We cannot possibly return a valid answer.  */
1516         return EAI_NONAME;
1517     }
1518
1519   if (service && service[0])
1520     {
1521       char *c;
1522       gaih_service.name = service;
1523       gaih_service.num = strtoul (gaih_service.name, &c, 10);
1524       if (*c != '\0')
1525         {
1526           if (hints->ai_flags & AI_NUMERICSERV)
1527             return EAI_NONAME;
1528
1529           gaih_service.num = -1;
1530         }
1531
1532       pservice = &gaih_service;
1533     }
1534   else
1535     pservice = NULL;
1536
1537   if (pai)
1538     end = &p;
1539   else
1540     end = NULL;
1541
1542   while (g->gaih)
1543     {
1544       if (hints->ai_family == g->family || hints->ai_family == AF_UNSPEC)
1545         {
1546           j++;
1547           if (pg == NULL || pg->gaih != g->gaih)
1548             {
1549               pg = g;
1550               i = g->gaih (name, pservice, hints, end);
1551               if (i != 0)
1552                 {
1553                   /* EAI_NODATA is a more specific result as it says that
1554                      we found a result but it is not usable.  */
1555                   if (last_i != (GAIH_OKIFUNSPEC | -EAI_NODATA))
1556                     last_i = i;
1557
1558                   if (hints->ai_family == AF_UNSPEC && (i & GAIH_OKIFUNSPEC))
1559                     {
1560                       ++g;
1561                       continue;
1562                     }
1563
1564                   freeaddrinfo (p);
1565
1566                   return -(i & GAIH_EAI);
1567                 }
1568               if (end)
1569                 while (*end)
1570                   {
1571                     end = &((*end)->ai_next);
1572                     ++nresults;
1573                   }
1574             }
1575         }
1576       ++g;
1577     }
1578
1579   if (j == 0)
1580     return EAI_FAMILY;
1581
1582   if (nresults > 1)
1583     {
1584       /* Sort results according to RFC 3484.  */
1585       struct sort_result results[nresults];
1586       struct addrinfo *q;
1587       struct addrinfo *last = NULL;
1588       char *canonname = NULL;
1589
1590       for (i = 0, q = p; q != NULL; ++i, last = q, q = q->ai_next)
1591         {
1592           results[i].dest_addr = q;
1593           results[i].got_source_addr = false;
1594
1595           /* If we just looked up the address for a different
1596              protocol, reuse the result.  */
1597           if (last != NULL && last->ai_addrlen == q->ai_addrlen
1598               && memcmp (last->ai_addr, q->ai_addr, q->ai_addrlen) == 0)
1599             {
1600               memcpy (&results[i].source_addr, &results[i - 1].source_addr,
1601                       results[i - 1].source_addr_len);
1602               results[i].source_addr_len = results[i - 1].source_addr_len;
1603               results[i].got_source_addr = results[i - 1].got_source_addr;
1604             }
1605           else
1606             {
1607               /* We overwrite the type with SOCK_DGRAM since we do not
1608                  want connect() to connect to the other side.  If we
1609                  cannot determine the source address remember this
1610                  fact.  */
1611               int fd = __socket (q->ai_family, SOCK_DGRAM, IPPROTO_IP);
1612               socklen_t sl = sizeof (results[i].source_addr);
1613               if (fd != -1
1614                   && __connect (fd, q->ai_addr, q->ai_addrlen) == 0
1615                   && __getsockname (fd,
1616                                     (struct sockaddr *) &results[i].source_addr,
1617                                     &sl) == 0)
1618                 {
1619                   results[i].source_addr_len = sl;
1620                   results[i].got_source_addr = true;
1621                 }
1622               else
1623                 /* Just make sure that if we have to process the same
1624                    address again we do not copy any memory.  */
1625                 results[i].source_addr_len = 0;
1626
1627               if (fd != -1)
1628                 close_not_cancel_no_status (fd);
1629             }
1630
1631           /* Remember the canonical name.  */
1632           if (q->ai_canonname != NULL)
1633             {
1634               assert (canonname == NULL);
1635               canonname = q->ai_canonname;
1636               q->ai_canonname = NULL;
1637             }
1638         }
1639
1640       /* We got all the source addresses we can get, now sort using
1641          the information.  */
1642       qsort (results, nresults, sizeof (results[0]), rfc3484_sort);
1643
1644       /* Queue the results up as they come out of sorting.  */
1645       q = p = results[0].dest_addr;
1646       for (i = 1; i < nresults; ++i)
1647         q = q->ai_next = results[i].dest_addr;
1648       q->ai_next = NULL;
1649
1650       /* Fill in the canonical name into the new first entry.  */
1651       p->ai_canonname = canonname;
1652     }
1653
1654   if (p)
1655     {
1656       *pai = p;
1657       return 0;
1658     }
1659
1660   if (pai == NULL && last_i == 0)
1661     return 0;
1662
1663   return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;
1664 }
1665 libc_hidden_def (getaddrinfo)
1666
1667 static_link_warning (getaddrinfo)
1668
1669 void
1670 freeaddrinfo (struct addrinfo *ai)
1671 {
1672   struct addrinfo *p;
1673
1674   while (ai != NULL)
1675     {
1676       p = ai;
1677       ai = ai->ai_next;
1678       free (p->ai_canonname);
1679       free (p);
1680     }
1681 }
1682 libc_hidden_def (freeaddrinfo)