Rename patches to -akaros instead of -ros
[akaros.git] / tools / compilers / gcc-glibc / glibc-2.14.1-akaros / sysdeps / akaros / 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 /* AKAROS note: this is the sysdeps/posix one (not to be confused with the
39  * posix/ stub one.  Needed for something or other in the network related
40  * subdirs */
41 #include <assert.h>
42 #include <ctype.h>
43 #include <errno.h>
44 #include <ifaddrs.h>
45 #include <netdb.h>
46 #include <nss.h>
47 #include <resolv.h>
48 #include <stdbool.h>
49 #include <stdio.h>
50 #include <stdio_ext.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <arpa/inet.h>
54 #include <net/if.h>
55 #include <netinet/in.h>
56 #include <sys/socket.h>
57 #include <sys/stat.h>
58 #include <sys/types.h>
59 #include <sys/un.h>
60 #include <sys/utsname.h>
61 #include <unistd.h>
62 #include <nsswitch.h>
63 #include <bits/libc-lock.h>
64 #include <not-cancel.h>
65 #include <nscd/nscd-client.h>
66 #include <nscd/nscd_proto.h>
67 #include <resolv/res_hconf.h>
68
69 #ifdef HAVE_LIBIDN
70 extern int __idna_to_ascii_lz (const char *input, char **output, int flags);
71 extern int __idna_to_unicode_lzlz (const char *input, char **output,
72                                    int flags);
73 # include <libidn/idna.h>
74 #endif
75
76 #define GAIH_OKIFUNSPEC 0x0100
77 #define GAIH_EAI        ~(GAIH_OKIFUNSPEC)
78
79 #ifndef UNIX_PATH_MAX
80 # define UNIX_PATH_MAX  108
81 #endif
82
83 struct gaih_service
84   {
85     const char *name;
86     int num;
87   };
88
89 struct gaih_servtuple
90   {
91     struct gaih_servtuple *next;
92     int socktype;
93     int protocol;
94     int port;
95   };
96
97 static const struct gaih_servtuple nullserv;
98
99
100 struct gaih_typeproto
101   {
102     int socktype;
103     int protocol;
104     uint8_t protoflag;
105     bool defaultflag;
106     char name[8];
107   };
108
109 /* Values for `protoflag'.  */
110 #define GAI_PROTO_NOSERVICE     1
111 #define GAI_PROTO_PROTOANY      2
112
113 static const struct gaih_typeproto gaih_inet_typeproto[] =
114 {
115   { 0, 0, 0, false, "" },
116   { SOCK_STREAM, IPPROTO_TCP, 0, true, "tcp" },
117   { SOCK_DGRAM, IPPROTO_UDP, 0, true, "udp" },
118 #if defined SOCK_DCCP && defined IPPROTO_DCCP
119   { SOCK_DCCP, IPPROTO_DCCP, 0, false, "dccp" },
120 #endif
121 #ifdef IPPROTO_UDPLITE
122   { SOCK_DGRAM, IPPROTO_UDPLITE, 0, false, "udplite" },
123 #endif
124 #ifdef IPPROTO_SCTP
125   { SOCK_STREAM, IPPROTO_SCTP, 0, false, "sctp" },
126   { SOCK_SEQPACKET, IPPROTO_SCTP, 0, false, "sctp" },
127 #endif
128   { SOCK_RAW, 0, GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE, true, "raw" },
129   { 0, 0, 0, false, "" }
130 };
131
132 struct gaih
133   {
134     int family;
135     int (*gaih)(const char *name, const struct gaih_service *service,
136                 const struct addrinfo *req, struct addrinfo **pai,
137                 unsigned int *naddrs);
138   };
139
140 static const struct addrinfo default_hints =
141   {
142     .ai_flags = AI_DEFAULT,
143     .ai_family = PF_UNSPEC,
144     .ai_socktype = 0,
145     .ai_protocol = 0,
146     .ai_addrlen = 0,
147     .ai_addr = NULL,
148     .ai_canonname = NULL,
149     .ai_next = NULL
150   };
151
152
153 static int
154 gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
155                 const struct addrinfo *req, struct gaih_servtuple *st)
156 {
157   struct servent *s;
158   size_t tmpbuflen = 1024;
159   struct servent ts;
160   char *tmpbuf;
161   int r;
162
163   do
164     {
165       tmpbuf = __alloca (tmpbuflen);
166
167       r = __getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen,
168                              &s);
169       if (r != 0 || s == NULL)
170         {
171           if (r == ERANGE)
172             tmpbuflen *= 2;
173           else
174             return GAIH_OKIFUNSPEC | -EAI_SERVICE;
175         }
176     }
177   while (r);
178
179   st->next = NULL;
180   st->socktype = tp->socktype;
181   st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
182                   ? req->ai_protocol : tp->protocol);
183   st->port = s->s_port;
184
185   return 0;
186 }
187
188 #define gethosts(_family, _type) \
189  {                                                                            \
190   int i;                                                                      \
191   int herrno;                                                                 \
192   struct hostent th;                                                          \
193   struct hostent *h;                                                          \
194   char *localcanon = NULL;                                                    \
195   no_data = 0;                                                                \
196   while (1) {                                                                 \
197     rc = 0;                                                                   \
198     status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen,        \
199                                 &rc, &herrno, NULL, &localcanon));            \
200     if (rc != ERANGE || herrno != NETDB_INTERNAL)                             \
201       break;                                                                  \
202     tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);                \
203   }                                                                           \
204   if (status == NSS_STATUS_SUCCESS && rc == 0)                                \
205     h = &th;                                                                  \
206   else                                                                        \
207     h = NULL;                                                                 \
208   if (rc != 0)                                                                \
209     {                                                                         \
210       if (herrno == NETDB_INTERNAL)                                           \
211         {                                                                     \
212           __set_h_errno (herrno);                                             \
213           _res.options = old_res_options;                                     \
214           return -EAI_SYSTEM;                                                 \
215         }                                                                     \
216       if (herrno == TRY_AGAIN)                                                \
217         no_data = EAI_AGAIN;                                                  \
218       else                                                                    \
219         no_data = herrno == NO_DATA;                                          \
220     }                                                                         \
221   else if (h != NULL)                                                         \
222     {                                                                         \
223       for (i = 0; h->h_addr_list[i]; i++)                                     \
224         {                                                                     \
225           if (*pat == NULL)                                                   \
226             {                                                                 \
227               *pat = __alloca (sizeof (struct gaih_addrtuple));               \
228               (*pat)->scopeid = 0;                                            \
229             }                                                                 \
230           uint32_t *addr = (*pat)->addr;                                      \
231           (*pat)->next = NULL;                                                \
232           (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL;                 \
233           if (_family == AF_INET && req->ai_family == AF_INET6)               \
234             {                                                                 \
235               (*pat)->family = AF_INET6;                                      \
236               addr[3] = *(uint32_t *) h->h_addr_list[i];                      \
237               addr[2] = htonl (0xffff);                                       \
238               addr[1] = 0;                                                    \
239               addr[0] = 0;                                                    \
240             }                                                                 \
241           else                                                                \
242             {                                                                 \
243               (*pat)->family = _family;                                       \
244               memcpy (addr, h->h_addr_list[i], sizeof(_type));                \
245             }                                                                 \
246           pat = &((*pat)->next);                                              \
247         }                                                                     \
248                                                                               \
249       if (localcanon != NULL && canon == NULL)                                \
250         canon = strdupa (localcanon);                                         \
251                                                                               \
252       if (_family == AF_INET6 && i > 0)                                       \
253         got_ipv6 = true;                                                      \
254     }                                                                         \
255  }
256
257
258 typedef enum nss_status (*nss_gethostbyname4_r)
259   (const char *name, struct gaih_addrtuple **pat,
260    char *buffer, size_t buflen, int *errnop,
261    int *h_errnop, int32_t *ttlp);
262 typedef enum nss_status (*nss_gethostbyname3_r)
263   (const char *name, int af, struct hostent *host,
264    char *buffer, size_t buflen, int *errnop,
265    int *h_errnop, int32_t *ttlp, char **canonp);
266 typedef enum nss_status (*nss_getcanonname_r)
267   (const char *name, char *buffer, size_t buflen, char **result,
268    int *errnop, int *h_errnop);
269 extern service_user *__nss_hosts_database attribute_hidden;
270
271
272 static int
273 gaih_inet (const char *name, const struct gaih_service *service,
274            const struct addrinfo *req, struct addrinfo **pai,
275            unsigned int *naddrs)
276 {
277   const struct gaih_typeproto *tp = gaih_inet_typeproto;
278   struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv;
279   struct gaih_addrtuple *at = NULL;
280   int rc;
281   bool got_ipv6 = false;
282   const char *canon = NULL;
283   const char *orig_name = name;
284
285   if (req->ai_protocol || req->ai_socktype)
286     {
287       ++tp;
288
289       while (tp->name[0]
290              && ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
291                  || (req->ai_protocol != 0
292                      && !(tp->protoflag & GAI_PROTO_PROTOANY)
293                      && req->ai_protocol != tp->protocol)))
294         ++tp;
295
296       if (! tp->name[0])
297         {
298           if (req->ai_socktype)
299             return GAIH_OKIFUNSPEC | -EAI_SOCKTYPE;
300           else
301             return GAIH_OKIFUNSPEC | -EAI_SERVICE;
302         }
303     }
304
305   int port = 0;
306   if (service != NULL)
307     {
308       if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
309         return GAIH_OKIFUNSPEC | -EAI_SERVICE;
310
311       if (service->num < 0)
312         {
313           if (tp->name[0])
314             {
315               st = (struct gaih_servtuple *)
316                 __alloca (sizeof (struct gaih_servtuple));
317
318               if ((rc = gaih_inet_serv (service->name, tp, req, st)))
319                 return rc;
320             }
321           else
322             {
323               struct gaih_servtuple **pst = &st;
324               for (tp++; tp->name[0]; tp++)
325                 {
326                   struct gaih_servtuple *newp;
327
328                   if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
329                     continue;
330
331                   if (req->ai_socktype != 0
332                       && req->ai_socktype != tp->socktype)
333                     continue;
334                   if (req->ai_protocol != 0
335                       && !(tp->protoflag & GAI_PROTO_PROTOANY)
336                       && req->ai_protocol != tp->protocol)
337                     continue;
338
339                   newp = (struct gaih_servtuple *)
340                     __alloca (sizeof (struct gaih_servtuple));
341
342                   if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
343                     {
344                       if (rc & GAIH_OKIFUNSPEC)
345                         continue;
346                       return rc;
347                     }
348
349                   *pst = newp;
350                   pst = &(newp->next);
351                 }
352               if (st == (struct gaih_servtuple *) &nullserv)
353                 return GAIH_OKIFUNSPEC | -EAI_SERVICE;
354             }
355         }
356       else
357         {
358           port = htons (service->num);
359           goto got_port;
360         }
361     }
362   else
363     {
364     got_port:
365
366       if (req->ai_socktype || req->ai_protocol)
367         {
368           st = __alloca (sizeof (struct gaih_servtuple));
369           st->next = NULL;
370           st->socktype = tp->socktype;
371           st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
372                           ? req->ai_protocol : tp->protocol);
373           st->port = port;
374         }
375       else
376         {
377           /* Neither socket type nor protocol is set.  Return all socket types
378              we know about.  */
379           struct gaih_servtuple **lastp = &st;
380           for (++tp; tp->name[0]; ++tp)
381             if (tp->defaultflag)
382               {
383                 struct gaih_servtuple *newp;
384
385                 newp = __alloca (sizeof (struct gaih_servtuple));
386                 newp->next = NULL;
387                 newp->socktype = tp->socktype;
388                 newp->protocol = tp->protocol;
389                 newp->port = port;
390
391                 *lastp = newp;
392                 lastp = &newp->next;
393               }
394         }
395     }
396
397   if (name != NULL)
398     {
399       at = __alloca (sizeof (struct gaih_addrtuple));
400
401       at->family = AF_UNSPEC;
402       at->scopeid = 0;
403       at->next = NULL;
404
405 #ifdef HAVE_LIBIDN
406       if (req->ai_flags & AI_IDN)
407         {
408           int idn_flags = 0;
409           if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
410             idn_flags |= IDNA_ALLOW_UNASSIGNED;
411           if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
412             idn_flags |= IDNA_USE_STD3_ASCII_RULES;
413
414           char *p = NULL;
415           rc = __idna_to_ascii_lz (name, &p, idn_flags);
416           if (rc != IDNA_SUCCESS)
417             {
418               if (rc == IDNA_MALLOC_ERROR)
419                 return -EAI_MEMORY;
420               if (rc == IDNA_DLOPEN_ERROR)
421                 return -EAI_SYSTEM;
422               return -EAI_IDN_ENCODE;
423             }
424           /* In case the output string is the same as the input string
425              no new string has been allocated.  */
426           if (p != name)
427             {
428               name = strdupa (p);
429               free (p);
430             }
431         }
432 #endif
433
434       if (__inet_aton (name, (struct in_addr *) at->addr) != 0)
435         {
436           if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
437             at->family = AF_INET;
438           else if (req->ai_family == AF_INET6 && (req->ai_flags & AI_V4MAPPED))
439             {
440               at->addr[3] = at->addr[0];
441               at->addr[2] = htonl (0xffff);
442               at->addr[1] = 0;
443               at->addr[0] = 0;
444               at->family = AF_INET6;
445             }
446           else
447             return -EAI_ADDRFAMILY;
448
449           if (req->ai_flags & AI_CANONNAME)
450             canon = name;
451         }
452       else if (at->family == AF_UNSPEC)
453         {
454           char *namebuf = (char *) name;
455           char *scope_delim = strchr (name, SCOPE_DELIMITER);
456
457           if (__builtin_expect (scope_delim != NULL, 0))
458             {
459               namebuf = alloca (scope_delim - name + 1);
460               *((char *) __mempcpy (namebuf, name, scope_delim - name)) = '\0';
461             }
462
463           if (inet_pton (AF_INET6, namebuf, at->addr) > 0)
464             {
465               if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
466                 at->family = AF_INET6;
467               else if (req->ai_family == AF_INET
468                        && IN6_IS_ADDR_V4MAPPED (at->addr))
469                 {
470                   at->addr[0] = at->addr[3];
471                   at->family = AF_INET;
472                 }
473               else
474                 return -EAI_ADDRFAMILY;
475
476               if (scope_delim != NULL)
477                 {
478                   int try_numericscope = 0;
479                   if (IN6_IS_ADDR_LINKLOCAL (at->addr)
480                       || IN6_IS_ADDR_MC_LINKLOCAL (at->addr))
481                     {
482                       at->scopeid = if_nametoindex (scope_delim + 1);
483                       if (at->scopeid == 0)
484                         try_numericscope = 1;
485                     }
486                   else
487                     try_numericscope = 1;
488
489                   if (try_numericscope != 0)
490                     {
491                       char *end;
492                       assert (sizeof (uint32_t) <= sizeof (unsigned long));
493                       at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
494                                                         10);
495                       if (*end != '\0')
496                         return GAIH_OKIFUNSPEC | -EAI_NONAME;
497                     }
498                 }
499
500               if (req->ai_flags & AI_CANONNAME)
501                 canon = name;
502             }
503         }
504
505       if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0)
506         {
507           struct gaih_addrtuple **pat = &at;
508           int no_data = 0;
509           int no_inet6_data = 0;
510           service_user *nip = NULL;
511           enum nss_status inet6_status = NSS_STATUS_UNAVAIL;
512           enum nss_status status = NSS_STATUS_UNAVAIL;
513           int no_more;
514           int old_res_options;
515
516           /* If we do not have to look for IPv4 and IPv6 together, use
517              the simple, old functions.  */
518           if (req->ai_family == AF_INET
519               || (req->ai_family == AF_INET6
520                   && ((req->ai_flags & AI_V4MAPPED) == 0
521                       || (req->ai_flags & AI_ALL) == 0)))
522             {
523               int family = req->ai_family;
524               size_t tmpbuflen = 512;
525               char *tmpbuf = alloca (tmpbuflen);
526               int rc;
527               struct hostent th;
528               struct hostent *h;
529               int herrno;
530
531             simple_again:
532               while (1)
533                 {
534                   rc = __gethostbyname2_r (name, family, &th, tmpbuf,
535                                            tmpbuflen, &h, &herrno);
536                   if (rc != ERANGE || herrno != NETDB_INTERNAL)
537                     break;
538                   tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
539                 }
540
541               if (rc == 0)
542                 {
543                   if (h == NULL)
544                     {
545                       if (req->ai_family == AF_INET6
546                           && (req->ai_flags & AI_V4MAPPED)
547                           && family == AF_INET6)
548                         {
549                           /* Try again, this time looking for IPv4
550                              addresses.  */
551                           family = AF_INET;
552                           goto simple_again;
553                         }
554                     }
555                   else
556                     {
557                       /* We found data, now convert it into the list.  */
558                       for (int i = 0; h->h_addr_list[i]; ++i)
559                         {
560                           if (*pat == NULL)
561                             {
562                               *pat = __alloca (sizeof (struct gaih_addrtuple));
563                               (*pat)->scopeid = 0;
564                             }
565                           (*pat)->next = NULL;
566                           (*pat)->family = req->ai_family;
567                           if (family == req->ai_family)
568                             memcpy ((*pat)->addr, h->h_addr_list[i],
569                                     h->h_length);
570                           else
571                             {
572                               uint32_t *addr = (uint32_t *) (*pat)->addr;
573                               addr[3] = *(uint32_t *) h->h_addr_list[i];
574                               addr[2] = htonl (0xffff);
575                               addr[1] = 0;
576                               addr[0] = 0;
577                             }
578                           pat = &((*pat)->next);
579                         }
580                     }
581                 }
582               else
583                 {
584                   if (herrno == NETDB_INTERNAL)
585                     {
586                       __set_h_errno (herrno);
587                       return -EAI_SYSTEM;
588                     }
589                   if (herrno == TRY_AGAIN)
590                     {
591                       return -EAI_AGAIN;
592                     }
593                   /* We made requests but they turned out no data.
594                      The name is known, though.  */
595                   return GAIH_OKIFUNSPEC | -EAI_NODATA;
596                 }
597
598               goto process_list;
599             }
600
601 #ifdef USE_NSCD
602           if (__nss_not_use_nscd_hosts > 0
603               && ++__nss_not_use_nscd_hosts > NSS_NSCD_RETRY)
604             __nss_not_use_nscd_hosts = 0;
605
606           if (!__nss_not_use_nscd_hosts)
607             {
608               /* Try to use nscd.  */
609               struct nscd_ai_result *air = NULL;
610               int herrno;
611               int err = __nscd_getai (name, &air, &herrno);
612               if (air != NULL)
613                 {
614                   /* Transform into gaih_addrtuple list.  */
615                   bool added_canon = (req->ai_flags & AI_CANONNAME) == 0;
616                   char *addrs = air->addrs;
617
618                   for (int i = 0; i < air->naddrs; ++i)
619                     {
620                       socklen_t size = (air->family[i] == AF_INET
621                                         ? INADDRSZ : IN6ADDRSZ);
622                       if (*pat == NULL)
623                         {
624                           *pat = __alloca (sizeof (struct gaih_addrtuple));
625                           (*pat)->scopeid = 0;
626                         }
627                       uint32_t *pataddr = (*pat)->addr;
628                       (*pat)->next = NULL;
629                       if (added_canon || air->canon == NULL)
630                         (*pat)->name = NULL;
631                       else
632                         canon = (*pat)->name = strdupa (air->canon);
633
634                       if (air->family[i] == AF_INET
635                           && req->ai_family == AF_INET6
636                           && (req->ai_flags & AI_V4MAPPED))
637                         {
638                           (*pat)->family = AF_INET6;
639                           pataddr[3] = *(uint32_t *) addrs;
640                           pataddr[2] = htonl (0xffff);
641                           pataddr[1] = 0;
642                           pataddr[0] = 0;
643                           pat = &((*pat)->next);
644                           added_canon = true;
645                         }
646                       else if (req->ai_family == AF_UNSPEC
647                                || air->family[i] == req->ai_family)
648                         {
649                           (*pat)->family = air->family[i];
650                           memcpy (pataddr, addrs, size);
651                           pat = &((*pat)->next);
652                           added_canon = true;
653                           if (air->family[i] == AF_INET6)
654                             got_ipv6 = true;
655                         }
656                       addrs += size;
657                     }
658
659                   free (air);
660
661                   if (at->family == AF_UNSPEC)
662                     return GAIH_OKIFUNSPEC | -EAI_NONAME;
663
664                   goto process_list;
665                 }
666               else if (err == 0)
667                 /* The database contains a negative entry.  */
668                 return 0;
669               else if (__nss_not_use_nscd_hosts == 0)
670                 {
671                   if (herrno == NETDB_INTERNAL && errno == ENOMEM)
672                     return -EAI_MEMORY;
673                   if (herrno == TRY_AGAIN)
674                     return -EAI_AGAIN;
675                   return -EAI_SYSTEM;
676                 }
677             }
678 #endif
679
680           if (__nss_hosts_database != NULL)
681             {
682               no_more = 0;
683               nip = __nss_hosts_database;
684             }
685           else
686             no_more = __nss_database_lookup ("hosts", NULL,
687                                              "dns [!UNAVAIL=return] files",
688                                              &nip);
689
690           /* Initialize configurations.  */
691           if (__builtin_expect (!_res_hconf.initialized, 0))
692             _res_hconf_init ();
693           if (__res_maybe_init (&_res, 0) == -1)
694             no_more = 1;
695
696           /* If we are looking for both IPv4 and IPv6 address we don't
697              want the lookup functions to automatically promote IPv4
698              addresses to IPv6 addresses.  Currently this is decided
699              by setting the RES_USE_INET6 bit in _res.options.  */
700           old_res_options = _res.options;
701           _res.options &= ~RES_USE_INET6;
702
703           size_t tmpbuflen = 1024;
704           char *tmpbuf = alloca (tmpbuflen);
705
706           while (!no_more)
707             {
708               nss_gethostbyname4_r fct4
709                 = __nss_lookup_function (nip, "gethostbyname4_r");
710               if (fct4 != NULL)
711                 {
712                   int herrno;
713
714                   while (1)
715                     {
716                       rc = 0;
717                       status = DL_CALL_FCT (fct4, (name, pat, tmpbuf,
718                                                    tmpbuflen, &rc, &herrno,
719                                                    NULL));
720                       if (status == NSS_STATUS_SUCCESS)
721                         break;
722                       if (status != NSS_STATUS_TRYAGAIN
723                           || rc != ERANGE || herrno != NETDB_INTERNAL)
724                         {
725                           if (herrno == NETDB_INTERNAL)
726                             {
727                               __set_h_errno (herrno);
728                               _res.options = old_res_options;
729                               return -EAI_SYSTEM;
730                             }
731                           if (herrno == TRY_AGAIN)
732                             no_data = EAI_AGAIN;
733                           else
734                             no_data = herrno == NO_DATA;
735                           break;
736                         }
737                       tmpbuf = extend_alloca (tmpbuf,
738                                               tmpbuflen, 2 * tmpbuflen);
739                     }
740
741                   no_inet6_data = no_data;
742
743                   if (status == NSS_STATUS_SUCCESS)
744                     {
745                       if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
746                         canon = (*pat)->name;
747
748                       while (*pat != NULL)
749                         pat = &((*pat)->next);
750                     }
751                 }
752               else
753                 {
754                   nss_gethostbyname3_r fct = NULL;
755                   if (req->ai_flags & AI_CANONNAME)
756                     /* No need to use this function if we do not look for
757                        the canonical name.  The function does not exist in
758                        all NSS modules and therefore the lookup would
759                        often fail.  */
760                     fct = __nss_lookup_function (nip, "gethostbyname3_r");
761                   if (fct == NULL)
762                     /* We are cheating here.  The gethostbyname2_r
763                        function does not have the same interface as
764                        gethostbyname3_r but the extra arguments the
765                        latter takes are added at the end.  So the
766                        gethostbyname2_r code will just ignore them.  */
767                     fct = __nss_lookup_function (nip, "gethostbyname2_r");
768
769                   if (fct != NULL)
770                     {
771                       if (req->ai_family == AF_INET6
772                           || req->ai_family == AF_UNSPEC)
773                         {
774                           gethosts (AF_INET6, struct in6_addr);
775                           no_inet6_data = no_data;
776                           inet6_status = status;
777                         }
778                       if (req->ai_family == AF_INET
779                           || req->ai_family == AF_UNSPEC
780                           || (req->ai_family == AF_INET6
781                               && (req->ai_flags & AI_V4MAPPED)
782                               /* Avoid generating the mapped addresses if we
783                                  know we are not going to need them.  */
784                               && ((req->ai_flags & AI_ALL) || !got_ipv6)))
785                         {
786                           gethosts (AF_INET, struct in_addr);
787
788                           if (req->ai_family == AF_INET)
789                             {
790                               no_inet6_data = no_data;
791                               inet6_status = status;
792                             }
793                         }
794
795                       /* If we found one address for AF_INET or AF_INET6,
796                          don't continue the search.  */
797                       if (inet6_status == NSS_STATUS_SUCCESS
798                           || status == NSS_STATUS_SUCCESS)
799                         {
800                           if ((req->ai_flags & AI_CANONNAME) != 0
801                               && canon == NULL)
802                             {
803                               /* If we need the canonical name, get it
804                                  from the same service as the result.  */
805                               nss_getcanonname_r cfct;
806                               int herrno;
807
808                               cfct = __nss_lookup_function (nip,
809                                                             "getcanonname_r");
810                               if (cfct != NULL)
811                                 {
812                                   const size_t max_fqdn_len = 256;
813                                   char *buf = alloca (max_fqdn_len);
814                                   char *s;
815
816                                   if (DL_CALL_FCT (cfct, (at->name ?: name,
817                                                           buf, max_fqdn_len,
818                                                           &s, &rc, &herrno))
819                                       == NSS_STATUS_SUCCESS)
820                                     canon = s;
821                                   else
822                                     /* Set to name now to avoid using
823                                        gethostbyaddr.  */
824                                     canon = name;
825                                 }
826                             }
827
828                           break;
829                         }
830
831                       /* We can have different states for AF_INET and
832                          AF_INET6.  Try to find a useful one for both.  */
833                       if (inet6_status == NSS_STATUS_TRYAGAIN)
834                         status = NSS_STATUS_TRYAGAIN;
835                       else if (status == NSS_STATUS_UNAVAIL
836                                && inet6_status != NSS_STATUS_UNAVAIL)
837                         status = inet6_status;
838                     }
839                   else
840                     status = NSS_STATUS_UNAVAIL;
841                 }
842
843               if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
844                 break;
845
846               if (nip->next == NULL)
847                 no_more = -1;
848               else
849                 nip = nip->next;
850             }
851
852           _res.options = old_res_options;
853
854           if (no_data != 0 && no_inet6_data != 0)
855             {
856               /* If both requests timed out report this.  */
857               if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
858                 return -EAI_AGAIN;
859
860               /* We made requests but they turned out no data.  The name
861                  is known, though.  */
862               return GAIH_OKIFUNSPEC | -EAI_NODATA;
863             }
864         }
865
866     process_list:
867       if (at->family == AF_UNSPEC)
868         return GAIH_OKIFUNSPEC | -EAI_NONAME;
869     }
870   else
871     {
872       struct gaih_addrtuple *atr;
873       atr = at = __alloca (sizeof (struct gaih_addrtuple));
874       memset (at, '\0', sizeof (struct gaih_addrtuple));
875
876       if (req->ai_family == AF_UNSPEC)
877         {
878           at->next = __alloca (sizeof (struct gaih_addrtuple));
879           memset (at->next, '\0', sizeof (struct gaih_addrtuple));
880         }
881
882       if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
883         {
884           at->family = AF_INET6;
885           if ((req->ai_flags & AI_PASSIVE) == 0)
886             memcpy (at->addr, &in6addr_loopback, sizeof (struct in6_addr));
887           atr = at->next;
888         }
889
890       if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
891         {
892           atr->family = AF_INET;
893           if ((req->ai_flags & AI_PASSIVE) == 0)
894             atr->addr[0] = htonl (INADDR_LOOPBACK);
895         }
896     }
897
898   {
899     struct gaih_servtuple *st2;
900     struct gaih_addrtuple *at2 = at;
901     size_t socklen;
902     sa_family_t family;
903
904     /*
905       buffer is the size of an unformatted IPv6 address in printable format.
906      */
907     while (at2 != NULL)
908       {
909         /* Only the first entry gets the canonical name.  */
910         if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
911           {
912             if (canon == NULL)
913               {
914                 struct hostent *h = NULL;
915                 int herrno;
916                 struct hostent th;
917                 size_t tmpbuflen = 512;
918                 char *tmpbuf = NULL;
919
920                 do
921                   {
922                     tmpbuf = extend_alloca (tmpbuf, tmpbuflen, tmpbuflen * 2);
923                     rc = __gethostbyaddr_r (at2->addr,
924                                             ((at2->family == AF_INET6)
925                                              ? sizeof (struct in6_addr)
926                                              : sizeof (struct in_addr)),
927                                             at2->family, &th, tmpbuf,
928                                             tmpbuflen, &h, &herrno);
929                   }
930                 while (rc == ERANGE && herrno == NETDB_INTERNAL);
931
932                 if (rc != 0 && herrno == NETDB_INTERNAL)
933                   {
934                     __set_h_errno (herrno);
935                     return -EAI_SYSTEM;
936                   }
937
938                 if (h != NULL)
939                   canon = h->h_name;
940                 else
941                   {
942                     assert (orig_name != NULL);
943                     /* If the canonical name cannot be determined, use
944                        the passed in string.  */
945                     canon = orig_name;
946                   }
947               }
948
949 #ifdef HAVE_LIBIDN
950             if (req->ai_flags & AI_CANONIDN)
951               {
952                 int idn_flags = 0;
953                 if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
954                   idn_flags |= IDNA_ALLOW_UNASSIGNED;
955                 if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
956                   idn_flags |= IDNA_USE_STD3_ASCII_RULES;
957
958                 char *out;
959                 int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
960                 if (rc != IDNA_SUCCESS)
961                   {
962                     if (rc == IDNA_MALLOC_ERROR)
963                       return -EAI_MEMORY;
964                     if (rc == IDNA_DLOPEN_ERROR)
965                       return -EAI_SYSTEM;
966                     return -EAI_IDN_ENCODE;
967                   }
968                 /* In case the output string is the same as the input
969                    string no new string has been allocated and we
970                    make a copy.  */
971                 if (out == canon)
972                   goto make_copy;
973               }
974             else
975 #endif
976               {
977 #ifdef HAVE_LIBIDN
978               make_copy:
979 #endif
980                 canon = strdup (canon);
981                 if (canon == NULL)
982                   return -EAI_MEMORY;
983               }
984           }
985
986         family = at2->family;
987         if (family == AF_INET6)
988           {
989             socklen = sizeof (struct sockaddr_in6);
990
991             /* If we looked up IPv4 mapped address discard them here if
992                the caller isn't interested in all address and we have
993                found at least one IPv6 address.  */
994             if (got_ipv6
995                 && (req->ai_flags & (AI_V4MAPPED|AI_ALL)) == AI_V4MAPPED
996                 && IN6_IS_ADDR_V4MAPPED (at2->addr))
997               goto ignore;
998           }
999         else
1000           socklen = sizeof (struct sockaddr_in);
1001
1002         for (st2 = st; st2 != NULL; st2 = st2->next)
1003           {
1004             struct addrinfo *ai;
1005             ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
1006             if (ai == NULL)
1007               {
1008                 free ((char *) canon);
1009                 return -EAI_MEMORY;
1010               }
1011
1012             ai->ai_flags = req->ai_flags;
1013             ai->ai_family = family;
1014             ai->ai_socktype = st2->socktype;
1015             ai->ai_protocol = st2->protocol;
1016             ai->ai_addrlen = socklen;
1017             ai->ai_addr = (void *) (ai + 1);
1018
1019             /* We only add the canonical name once.  */
1020             ai->ai_canonname = (char *) canon;
1021             canon = NULL;
1022
1023 #ifdef _HAVE_SA_LEN
1024             ai->ai_addr->sa_len = socklen;
1025 #endif /* _HAVE_SA_LEN */
1026             ai->ai_addr->sa_family = family;
1027
1028             /* In case of an allocation error the list must be NULL
1029                terminated.  */
1030             ai->ai_next = NULL;
1031
1032             if (family == AF_INET6)
1033               {
1034                 struct sockaddr_in6 *sin6p =
1035                   (struct sockaddr_in6 *) ai->ai_addr;
1036
1037                 sin6p->sin6_port = st2->port;
1038                 sin6p->sin6_flowinfo = 0;
1039                 memcpy (&sin6p->sin6_addr,
1040                         at2->addr, sizeof (struct in6_addr));
1041                 sin6p->sin6_scope_id = at2->scopeid;
1042               }
1043             else
1044               {
1045                 struct sockaddr_in *sinp =
1046                   (struct sockaddr_in *) ai->ai_addr;
1047                 sinp->sin_port = st2->port;
1048                 memcpy (&sinp->sin_addr,
1049                         at2->addr, sizeof (struct in_addr));
1050                 memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
1051               }
1052
1053             pai = &(ai->ai_next);
1054           }
1055
1056         ++*naddrs;
1057
1058       ignore:
1059         at2 = at2->next;
1060       }
1061   }
1062   return 0;
1063 }
1064
1065
1066 struct sort_result
1067 {
1068   struct addrinfo *dest_addr;
1069   /* Using sockaddr_storage is for now overkill.  We only support IPv4
1070      and IPv6 so far.  If this changes at some point we can adjust the
1071      type here.  */
1072   struct sockaddr_in6 source_addr;
1073   uint8_t source_addr_len;
1074   bool got_source_addr;
1075   uint8_t source_addr_flags;
1076   uint8_t prefixlen;
1077   uint32_t index;
1078   int32_t native;
1079 };
1080
1081 struct sort_result_combo
1082 {
1083   struct sort_result *results;
1084   int nresults;
1085 };
1086
1087
1088 #if __BYTE_ORDER == __BIG_ENDIAN
1089 # define htonl_c(n) n
1090 #else
1091 # define htonl_c(n) __bswap_constant_32 (n)
1092 #endif
1093
1094 static const struct scopeentry
1095 {
1096   union
1097   {
1098     char addr[4];
1099     uint32_t addr32;
1100   };
1101   uint32_t netmask;
1102   int32_t scope;
1103 } default_scopes[] =
1104   {
1105     /* Link-local addresses: scope 2.  */
1106     { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
1107     { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
1108     /* Site-local addresses: scope 5.  */
1109     { { { 10, 0, 0, 0 } }, htonl_c (0xff000000), 5 },
1110     { { { 172, 16, 0, 0 } }, htonl_c (0xfff00000), 5 },
1111     { { { 192, 168, 0, 0 } }, htonl_c (0xffff0000), 5 },
1112     /* Default: scope 14.  */
1113     { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
1114   };
1115
1116 /* The label table.  */
1117 static const struct scopeentry *scopes;
1118
1119
1120 static int
1121 get_scope (const struct sockaddr_in6 *in6)
1122 {
1123   int scope;
1124   if (in6->sin6_family == PF_INET6)
1125     {
1126       if (! IN6_IS_ADDR_MULTICAST (&in6->sin6_addr))
1127         {
1128           if (IN6_IS_ADDR_LINKLOCAL (&in6->sin6_addr)
1129               /* RFC 4291 2.5.3 says that the loopback address is to be
1130                  treated like a link-local address.  */
1131               || IN6_IS_ADDR_LOOPBACK (&in6->sin6_addr))
1132             scope = 2;
1133           else if (IN6_IS_ADDR_SITELOCAL (&in6->sin6_addr))
1134             scope = 5;
1135           else
1136             /* XXX Is this the correct default behavior?  */
1137             scope = 14;
1138         }
1139       else
1140         scope = in6->sin6_addr.s6_addr[1] & 0xf;
1141     }
1142   else if (in6->sin6_family == PF_INET)
1143     {
1144       const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
1145
1146       size_t cnt = 0;
1147       while (1)
1148         {
1149           if ((in->sin_addr.s_addr & scopes[cnt].netmask)
1150               == scopes[cnt].addr32)
1151             return scopes[cnt].scope;
1152
1153           ++cnt;
1154         }
1155       /* NOTREACHED */
1156     }
1157   else
1158     /* XXX What is a good default?  */
1159     scope = 15;
1160
1161   return scope;
1162 }
1163
1164
1165 struct prefixentry
1166 {
1167   struct in6_addr prefix;
1168   unsigned int bits;
1169   int val;
1170 };
1171
1172
1173 /* The label table.  */
1174 static const struct prefixentry *labels;
1175
1176 /* Default labels.  */
1177 static const struct prefixentry default_labels[] =
1178   {
1179     /* See RFC 3484 for the details.  */
1180     { { .__in6_u
1181         = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1182                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1183       }, 128, 0 },
1184     { { .__in6_u
1185         = { .__u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1186                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1187       }, 16, 2 },
1188     { { .__in6_u
1189         = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1190                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1191       }, 96, 3 },
1192     { { .__in6_u
1193         = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1194                             0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1195       }, 96, 4 },
1196     /* The next two entries differ from RFC 3484.  We need to treat
1197        IPv6 site-local addresses special because they are never NATed,
1198        unlike site-locale IPv4 addresses.  If this would not happen, on
1199        machines which have only IPv4 and IPv6 site-local addresses, the
1200        sorting would prefer the IPv6 site-local addresses, causing
1201        unnecessary delays when trying to connect to a global IPv6 address
1202        through a site-local IPv6 address.  */
1203     { { .__in6_u
1204         = { .__u6_addr8 = { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1205                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1206       }, 10, 5 },
1207     { { .__in6_u
1208         = { .__u6_addr8 = { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1209                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1210       }, 7, 6 },
1211     /* Additional rule for Teredo tunnels.  */
1212     { { .__in6_u
1213         = { .__u6_addr8 = { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1214                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1215       }, 32, 7 },
1216     { { .__in6_u
1217         = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1218                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1219       }, 0, 1 }
1220   };
1221
1222
1223 /* The precedence table.  */
1224 static const struct prefixentry *precedence;
1225
1226 /* The default precedences.  */
1227 static const struct prefixentry default_precedence[] =
1228   {
1229     /* See RFC 3484 for the details.  */
1230     { { .__in6_u
1231         = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1232                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
1233       }, 128, 50 },
1234     { { .__in6_u
1235         = { .__u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1236                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1237       }, 16, 30 },
1238     { { .__in6_u
1239         = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1240                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1241       }, 96, 20 },
1242     { { .__in6_u
1243         = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1244                             0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
1245       }, 96, 10 },
1246     { { .__in6_u
1247         = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1248                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
1249       }, 0, 40 }
1250   };
1251
1252
1253 static int
1254 match_prefix (const struct sockaddr_in6 *in6,
1255               const struct prefixentry *list, int default_val)
1256 {
1257   int idx;
1258   struct sockaddr_in6 in6_mem;
1259
1260   if (in6->sin6_family == PF_INET)
1261     {
1262       const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
1263
1264       /* Construct a V4-to-6 mapped address.  */
1265       in6_mem.sin6_family = PF_INET6;
1266       in6_mem.sin6_port = in->sin_port;
1267       in6_mem.sin6_flowinfo = 0;
1268       memset (&in6_mem.sin6_addr, '\0', sizeof (in6_mem.sin6_addr));
1269       in6_mem.sin6_addr.s6_addr16[5] = 0xffff;
1270       in6_mem.sin6_addr.s6_addr32[3] = in->sin_addr.s_addr;
1271       in6_mem.sin6_scope_id = 0;
1272
1273       in6 = &in6_mem;
1274     }
1275   else if (in6->sin6_family != PF_INET6)
1276     return default_val;
1277
1278   for (idx = 0; ; ++idx)
1279     {
1280       unsigned int bits = list[idx].bits;
1281       const uint8_t *mask = list[idx].prefix.s6_addr;
1282       const uint8_t *val = in6->sin6_addr.s6_addr;
1283
1284       while (bits >= 8)
1285         {
1286           if (*mask != *val)
1287             break;
1288
1289           ++mask;
1290           ++val;
1291           bits -= 8;
1292         }
1293
1294       if (bits < 8)
1295         {
1296           if ((*mask & (0xff00 >> bits)) == (*val & (0xff00 >> bits)))
1297             /* Match!  */
1298             break;
1299         }
1300     }
1301
1302   return list[idx].val;
1303 }
1304
1305
1306 static int
1307 get_label (const struct sockaddr_in6 *in6)
1308 {
1309   /* XXX What is a good default value?  */
1310   return match_prefix (in6, labels, INT_MAX);
1311 }
1312
1313
1314 static int
1315 get_precedence (const struct sockaddr_in6 *in6)
1316 {
1317   /* XXX What is a good default value?  */
1318   return match_prefix (in6, precedence, 0);
1319 }
1320
1321
1322 /* Find last bit set in a word.  */
1323 static int
1324 fls (uint32_t a)
1325 {
1326   uint32_t mask;
1327   int n;
1328   for (n = 0, mask = 1 << 31; n < 32; mask >>= 1, ++n)
1329     if ((a & mask) != 0)
1330       break;
1331   return n;
1332 }
1333
1334
1335 static int
1336 rfc3484_sort (const void *p1, const void *p2, void *arg)
1337 {
1338   const size_t idx1 = *(const size_t *) p1;
1339   const size_t idx2 = *(const size_t *) p2;
1340   struct sort_result_combo *src = (struct sort_result_combo *) arg;
1341   struct sort_result *a1 = &src->results[idx1];
1342   struct sort_result *a2 = &src->results[idx2];
1343
1344   /* Rule 1: Avoid unusable destinations.
1345      We have the got_source_addr flag set if the destination is reachable.  */
1346   if (a1->got_source_addr && ! a2->got_source_addr)
1347     return -1;
1348   if (! a1->got_source_addr && a2->got_source_addr)
1349     return 1;
1350
1351
1352   /* Rule 2: Prefer matching scope.  Only interesting if both
1353      destination addresses are IPv6.  */
1354   int a1_dst_scope
1355     = get_scope ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1356
1357   int a2_dst_scope
1358     = get_scope ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1359
1360   if (a1->got_source_addr)
1361     {
1362       int a1_src_scope = get_scope (&a1->source_addr);
1363       int a2_src_scope = get_scope (&a2->source_addr);
1364
1365       if (a1_dst_scope == a1_src_scope && a2_dst_scope != a2_src_scope)
1366         return -1;
1367       if (a1_dst_scope != a1_src_scope && a2_dst_scope == a2_src_scope)
1368         return 1;
1369     }
1370
1371
1372   /* Rule 3: Avoid deprecated addresses.  */
1373   if (a1->got_source_addr)
1374     {
1375       if (!(a1->source_addr_flags & in6ai_deprecated)
1376           && (a2->source_addr_flags & in6ai_deprecated))
1377         return -1;
1378       if ((a1->source_addr_flags & in6ai_deprecated)
1379           && !(a2->source_addr_flags & in6ai_deprecated))
1380         return 1;
1381     }
1382
1383   /* Rule 4: Prefer home addresses.  */
1384   if (a1->got_source_addr)
1385     {
1386       if (!(a1->source_addr_flags & in6ai_homeaddress)
1387           && (a2->source_addr_flags & in6ai_homeaddress))
1388         return 1;
1389       if ((a1->source_addr_flags & in6ai_homeaddress)
1390           && !(a2->source_addr_flags & in6ai_homeaddress))
1391         return -1;
1392     }
1393
1394   /* Rule 5: Prefer matching label.  */
1395   if (a1->got_source_addr)
1396     {
1397       int a1_dst_label
1398         = get_label ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1399       int a1_src_label = get_label (&a1->source_addr);
1400
1401       int a2_dst_label
1402         = get_label ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1403       int a2_src_label = get_label (&a2->source_addr);
1404
1405       if (a1_dst_label == a1_src_label && a2_dst_label != a2_src_label)
1406         return -1;
1407       if (a1_dst_label != a1_src_label && a2_dst_label == a2_src_label)
1408         return 1;
1409     }
1410
1411
1412   /* Rule 6: Prefer higher precedence.  */
1413   int a1_prec
1414     = get_precedence ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
1415   int a2_prec
1416     = get_precedence ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
1417
1418   if (a1_prec > a2_prec)
1419     return -1;
1420   if (a1_prec < a2_prec)
1421     return 1;
1422
1423
1424   /* Rule 7: Prefer native transport.  */
1425   if (a1->got_source_addr)
1426     {
1427       /* The same interface index means the same interface which means
1428          there is no difference in transport.  This should catch many
1429          (most?) cases.  */
1430       if (a1->index != a2->index)
1431         {
1432           int a1_native = a1->native;
1433           int a2_native = a2->native;
1434
1435           if (a1_native == -1 || a2_native == -1)
1436             {
1437               uint32_t a1_index;
1438               if (a1_native == -1)
1439                 {
1440                   /* If we do not have the information use 'native' as
1441                      the default.  */
1442                   a1_native = 0;
1443                   a1_index = a1->index;
1444                 }
1445               else
1446                 a1_index = 0xffffffffu;
1447
1448               uint32_t a2_index;
1449               if (a2_native == -1)
1450                 {
1451                   /* If we do not have the information use 'native' as
1452                      the default.  */
1453                   a2_native = 0;
1454                   a2_index = a2->index;
1455                 }
1456               else
1457                 a2_index = 0xffffffffu;
1458
1459               __check_native (a1_index, &a1_native, a2_index, &a2_native);
1460
1461               /* Fill in the results in all the records.  */
1462               for (int i = 0; i < src->nresults; ++i)
1463                 if (src->results[i].index == a1_index)
1464                   {
1465                     assert (src->results[i].native == -1
1466                             || src->results[i].native == a1_native);
1467                     src->results[i].native = a1_native;
1468                   }
1469                 else if (src->results[i].index == a2_index)
1470                   {
1471                     assert (src->results[i].native == -1
1472                             || src->results[i].native == a2_native);
1473                     src->results[i].native = a2_native;
1474                   }
1475             }
1476
1477           if (a1_native && !a2_native)
1478             return -1;
1479           if (!a1_native && a2_native)
1480             return 1;
1481         }
1482     }
1483
1484
1485   /* Rule 8: Prefer smaller scope.  */
1486   if (a1_dst_scope < a2_dst_scope)
1487     return -1;
1488   if (a1_dst_scope > a2_dst_scope)
1489     return 1;
1490
1491
1492   /* Rule 9: Use longest matching prefix.  */
1493   if (a1->got_source_addr
1494       && a1->dest_addr->ai_family == a2->dest_addr->ai_family)
1495     {
1496       int bit1 = 0;
1497       int bit2 = 0;
1498
1499       if (a1->dest_addr->ai_family == PF_INET)
1500         {
1501           assert (a1->source_addr.sin6_family == PF_INET);
1502           assert (a2->source_addr.sin6_family == PF_INET);
1503
1504           /* Outside of subnets, as defined by the network masks,
1505              common address prefixes for IPv4 addresses make no sense.
1506              So, define a non-zero value only if source and
1507              destination address are on the same subnet.  */
1508           struct sockaddr_in *in1_dst
1509             = (struct sockaddr_in *) a1->dest_addr->ai_addr;
1510           in_addr_t in1_dst_addr = ntohl (in1_dst->sin_addr.s_addr);
1511           struct sockaddr_in *in1_src
1512             = (struct sockaddr_in *) &a1->source_addr;
1513           in_addr_t in1_src_addr = ntohl (in1_src->sin_addr.s_addr);
1514           in_addr_t netmask1 = 0xffffffffu << (32 - a1->prefixlen);
1515
1516           if ((in1_src_addr & netmask1) == (in1_dst_addr & netmask1))
1517             bit1 = fls (in1_dst_addr ^ in1_src_addr);
1518
1519           struct sockaddr_in *in2_dst
1520             = (struct sockaddr_in *) a2->dest_addr->ai_addr;
1521           in_addr_t in2_dst_addr = ntohl (in2_dst->sin_addr.s_addr);
1522           struct sockaddr_in *in2_src
1523             = (struct sockaddr_in *) &a2->source_addr;
1524           in_addr_t in2_src_addr = ntohl (in2_src->sin_addr.s_addr);
1525           in_addr_t netmask2 = 0xffffffffu << (32 - a2->prefixlen);
1526
1527           if ((in2_src_addr & netmask2) == (in2_dst_addr & netmask2))
1528             bit2 = fls (in2_dst_addr ^ in2_src_addr);
1529         }
1530       else if (a1->dest_addr->ai_family == PF_INET6)
1531         {
1532           assert (a1->source_addr.sin6_family == PF_INET6);
1533           assert (a2->source_addr.sin6_family == PF_INET6);
1534
1535           struct sockaddr_in6 *in1_dst;
1536           struct sockaddr_in6 *in1_src;
1537           struct sockaddr_in6 *in2_dst;
1538           struct sockaddr_in6 *in2_src;
1539
1540           in1_dst = (struct sockaddr_in6 *) a1->dest_addr->ai_addr;
1541           in1_src = (struct sockaddr_in6 *) &a1->source_addr;
1542           in2_dst = (struct sockaddr_in6 *) a2->dest_addr->ai_addr;
1543           in2_src = (struct sockaddr_in6 *) &a2->source_addr;
1544
1545           int i;
1546           for (i = 0; i < 4; ++i)
1547             if (in1_dst->sin6_addr.s6_addr32[i]
1548                 != in1_src->sin6_addr.s6_addr32[i]
1549                 || (in2_dst->sin6_addr.s6_addr32[i]
1550                     != in2_src->sin6_addr.s6_addr32[i]))
1551               break;
1552
1553           if (i < 4)
1554             {
1555               bit1 = fls (ntohl (in1_dst->sin6_addr.s6_addr32[i]
1556                                  ^ in1_src->sin6_addr.s6_addr32[i]));
1557               bit2 = fls (ntohl (in2_dst->sin6_addr.s6_addr32[i]
1558                                  ^ in2_src->sin6_addr.s6_addr32[i]));
1559             }
1560         }
1561
1562       if (bit1 > bit2)
1563         return -1;
1564       if (bit1 < bit2)
1565         return 1;
1566     }
1567
1568
1569   /* Rule 10: Otherwise, leave the order unchanged.  To ensure this
1570      compare with the value indicating the order in which the entries
1571      have been received from the services.  NB: no two entries can have
1572      the same order so the test will never return zero.  */
1573   return idx1 < idx2 ? -1 : 1;
1574 }
1575
1576
1577 static int
1578 in6aicmp (const void *p1, const void *p2)
1579 {
1580   struct in6addrinfo *a1 = (struct in6addrinfo *) p1;
1581   struct in6addrinfo *a2 = (struct in6addrinfo *) p2;
1582
1583   return memcmp (a1->addr, a2->addr, sizeof (a1->addr));
1584 }
1585
1586
1587 /* Name of the config file for RFC 3484 sorting (for now).  */
1588 #define GAICONF_FNAME "/etc/gai.conf"
1589
1590
1591 /* Non-zero if we are supposed to reload the config file automatically
1592    whenever it changed.  */
1593 static int gaiconf_reload_flag;
1594
1595 /* Non-zero if gaiconf_reload_flag was ever set to true.  */
1596 static int gaiconf_reload_flag_ever_set;
1597
1598 /* Last modification time.  */
1599 static __time_t gaiconf_mtime;
1600
1601
1602 libc_freeres_fn(fini)
1603 {
1604   if (labels != default_labels)
1605     {
1606       const struct prefixentry *old = labels;
1607       labels = default_labels;
1608       free ((void *) old);
1609     }
1610
1611   if (precedence != default_precedence)
1612     {
1613       const struct prefixentry *old = precedence;
1614       precedence = default_precedence;
1615       free ((void *) old);
1616     }
1617
1618   if (scopes != default_scopes)
1619     {
1620       const struct scopeentry *old = scopes;
1621       scopes = default_scopes;
1622       free ((void *) old);
1623     }
1624 }
1625
1626
1627 struct prefixlist
1628 {
1629   struct prefixentry entry;
1630   struct prefixlist *next;
1631 };
1632
1633
1634 struct scopelist
1635 {
1636   struct scopeentry entry;
1637   struct scopelist *next;
1638 };
1639
1640
1641 static void
1642 free_prefixlist (struct prefixlist *list)
1643 {
1644   while (list != NULL)
1645     {
1646       struct prefixlist *oldp = list;
1647       list = list->next;
1648       free (oldp);
1649     }
1650 }
1651
1652
1653 static void
1654 free_scopelist (struct scopelist *list)
1655 {
1656   while (list != NULL)
1657     {
1658       struct scopelist *oldp = list;
1659       list = list->next;
1660       free (oldp);
1661     }
1662 }
1663
1664
1665 static int
1666 prefixcmp (const void *p1, const void *p2)
1667 {
1668   const struct prefixentry *e1 = (const struct prefixentry *) p1;
1669   const struct prefixentry *e2 = (const struct prefixentry *) p2;
1670
1671   if (e1->bits < e2->bits)
1672     return 1;
1673   if (e1->bits == e2->bits)
1674     return 0;
1675   return -1;
1676 }
1677
1678
1679 static int
1680 scopecmp (const void *p1, const void *p2)
1681 {
1682   const struct scopeentry *e1 = (const struct scopeentry *) p1;
1683   const struct scopeentry *e2 = (const struct scopeentry *) p2;
1684
1685   if (e1->netmask > e2->netmask)
1686     return -1;
1687   if (e1->netmask == e2->netmask)
1688     return 0;
1689   return 1;
1690 }
1691
1692
1693 static void
1694 gaiconf_init (void)
1695 {
1696   struct prefixlist *labellist = NULL;
1697   size_t nlabellist = 0;
1698   bool labellist_nullbits = false;
1699   struct prefixlist *precedencelist = NULL;
1700   size_t nprecedencelist = 0;
1701   bool precedencelist_nullbits = false;
1702   struct scopelist *scopelist =  NULL;
1703   size_t nscopelist = 0;
1704   bool scopelist_nullbits = false;
1705
1706   FILE *fp = fopen (GAICONF_FNAME, "rc");
1707   if (fp != NULL)
1708     {
1709       struct stat64 st;
1710       if (__fxstat64 (_STAT_VER, fileno (fp), &st) != 0)
1711         {
1712           fclose (fp);
1713           goto no_file;
1714         }
1715
1716       char *line = NULL;
1717       size_t linelen = 0;
1718
1719       __fsetlocking (fp, FSETLOCKING_BYCALLER);
1720
1721       while (!feof_unlocked (fp))
1722         {
1723           ssize_t n = __getline (&line, &linelen, fp);
1724           if (n <= 0)
1725             break;
1726
1727           /* Handle comments.  No escaping possible so this is easy.  */
1728           char *cp = strchr (line, '#');
1729           if (cp != NULL)
1730             *cp = '\0';
1731
1732           cp = line;
1733           while (isspace (*cp))
1734             ++cp;
1735
1736           char *cmd = cp;
1737           while (*cp != '\0' && !isspace (*cp))
1738             ++cp;
1739           size_t cmdlen = cp - cmd;
1740
1741           if (*cp != '\0')
1742             *cp++ = '\0';
1743           while (isspace (*cp))
1744             ++cp;
1745
1746           char *val1 = cp;
1747           while (*cp != '\0' && !isspace (*cp))
1748             ++cp;
1749           size_t val1len = cp - cmd;
1750
1751           /* We always need at least two values.  */
1752           if (val1len == 0)
1753             continue;
1754
1755           if (*cp != '\0')
1756             *cp++ = '\0';
1757           while (isspace (*cp))
1758             ++cp;
1759
1760           char *val2 = cp;
1761           while (*cp != '\0' && !isspace (*cp))
1762             ++cp;
1763
1764           /*  Ignore the rest of the line.  */
1765           *cp = '\0';
1766
1767           struct prefixlist **listp;
1768           size_t *lenp;
1769           bool *nullbitsp;
1770           switch (cmdlen)
1771             {
1772             case 5:
1773               if (strcmp (cmd, "label") == 0)
1774                 {
1775                   struct in6_addr prefix;
1776                   unsigned long int bits;
1777                   unsigned long int val;
1778                   char *endp;
1779
1780                   listp = &labellist;
1781                   lenp = &nlabellist;
1782                   nullbitsp = &labellist_nullbits;
1783
1784                 new_elem:
1785                   bits = 128;
1786                   __set_errno (0);
1787                   cp = strchr (val1, '/');
1788                   if (cp != NULL)
1789                     *cp++ = '\0';
1790                   if (inet_pton (AF_INET6, val1, &prefix)
1791                       && (cp == NULL
1792                           || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
1793                           || errno != ERANGE)
1794                       && *endp == '\0'
1795                       && bits <= 128
1796                       && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
1797                           || errno != ERANGE)
1798                       && *endp == '\0'
1799                       && val <= INT_MAX)
1800                     {
1801                       struct prefixlist *newp = malloc (sizeof (*newp));
1802                       if (newp == NULL)
1803                         {
1804                           free (line);
1805                           fclose (fp);
1806                           goto no_file;
1807                         }
1808
1809                       memcpy (&newp->entry.prefix, &prefix, sizeof (prefix));
1810                       newp->entry.bits = bits;
1811                       newp->entry.val = val;
1812                       newp->next = *listp;
1813                       *listp = newp;
1814                       ++*lenp;
1815                       *nullbitsp |= bits == 0;
1816                     }
1817                 }
1818               break;
1819
1820             case 6:
1821               if (strcmp (cmd, "reload") == 0)
1822                 {
1823                   gaiconf_reload_flag = strcmp (val1, "yes") == 0;
1824                   if (gaiconf_reload_flag)
1825                     gaiconf_reload_flag_ever_set = 1;
1826                 }
1827               break;
1828
1829             case 7:
1830               if (strcmp (cmd, "scopev4") == 0)
1831                 {
1832                   struct in6_addr prefix;
1833                   unsigned long int bits;
1834                   unsigned long int val;
1835                   char *endp;
1836
1837                   bits = 32;
1838                   __set_errno (0);
1839                   cp = strchr (val1, '/');
1840                   if (cp != NULL)
1841                     *cp++ = '\0';
1842                   if (inet_pton (AF_INET6, val1, &prefix))
1843                     {
1844                       bits = 128;
1845                       if (IN6_IS_ADDR_V4MAPPED (&prefix)
1846                           && (cp == NULL
1847                               || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
1848                               || errno != ERANGE)
1849                           && *endp == '\0'
1850                           && bits >= 96
1851                           && bits <= 128
1852                           && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
1853                               || errno != ERANGE)
1854                           && *endp == '\0'
1855                           && val <= INT_MAX)
1856                         {
1857                           struct scopelist *newp;
1858                         new_scope:
1859                           newp = malloc (sizeof (*newp));
1860                           if (newp == NULL)
1861                             {
1862                               free (line);
1863                               fclose (fp);
1864                               goto no_file;
1865                             }
1866
1867                           newp->entry.netmask = htonl (bits != 96
1868                                                        ? (0xffffffff
1869                                                           << (128 - bits))
1870                                                        : 0);
1871                           newp->entry.addr32 = (prefix.s6_addr32[3]
1872                                                 & newp->entry.netmask);
1873                           newp->entry.scope = val;
1874                           newp->next = scopelist;
1875                           scopelist = newp;
1876                           ++nscopelist;
1877                           scopelist_nullbits |= bits == 96;
1878                         }
1879                     }
1880                   else if (inet_pton (AF_INET, val1, &prefix.s6_addr32[3])
1881                            && (cp == NULL
1882                                || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
1883                                || errno != ERANGE)
1884                            && *endp == '\0'
1885                            && bits <= 32
1886                            && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
1887                                || errno != ERANGE)
1888                            && *endp == '\0'
1889                            && val <= INT_MAX)
1890                     {
1891                       bits += 96;
1892                       goto new_scope;
1893                     }
1894                 }
1895               break;
1896
1897             case 10:
1898               if (strcmp (cmd, "precedence") == 0)
1899                 {
1900                   listp = &precedencelist;
1901                   lenp = &nprecedencelist;
1902                   nullbitsp = &precedencelist_nullbits;
1903                   goto new_elem;
1904                 }
1905               break;
1906             }
1907         }
1908
1909       free (line);
1910
1911       fclose (fp);
1912
1913       /* Create the array for the labels.  */
1914       struct prefixentry *new_labels;
1915       if (nlabellist > 0)
1916         {
1917           if (!labellist_nullbits)
1918             ++nlabellist;
1919           new_labels = malloc (nlabellist * sizeof (*new_labels));
1920           if (new_labels == NULL)
1921             goto no_file;
1922
1923           int i = nlabellist;
1924           if (!labellist_nullbits)
1925             {
1926               --i;
1927               memset (&new_labels[i].prefix, '\0', sizeof (struct in6_addr));
1928               new_labels[i].bits = 0;
1929               new_labels[i].val = 1;
1930             }
1931
1932           struct prefixlist *l = labellist;
1933           while (i-- > 0)
1934             {
1935               new_labels[i] = l->entry;
1936               l = l->next;
1937             }
1938           free_prefixlist (labellist);
1939
1940           /* Sort the entries so that the most specific ones are at
1941              the beginning.  */
1942           qsort (new_labels, nlabellist, sizeof (*new_labels), prefixcmp);
1943         }
1944       else
1945         new_labels = (struct prefixentry *) default_labels;
1946
1947       struct prefixentry *new_precedence;
1948       if (nprecedencelist > 0)
1949         {
1950           if (!precedencelist_nullbits)
1951             ++nprecedencelist;
1952           new_precedence = malloc (nprecedencelist * sizeof (*new_precedence));
1953           if (new_precedence == NULL)
1954             {
1955               if (new_labels != default_labels)
1956                 free (new_labels);
1957               goto no_file;
1958             }
1959
1960           int i = nprecedencelist;
1961           if (!precedencelist_nullbits)
1962             {
1963               --i;
1964               memset (&new_precedence[i].prefix, '\0',
1965                       sizeof (struct in6_addr));
1966               new_precedence[i].bits = 0;
1967               new_precedence[i].val = 40;
1968             }
1969
1970           struct prefixlist *l = precedencelist;
1971           while (i-- > 0)
1972             {
1973               new_precedence[i] = l->entry;
1974               l = l->next;
1975             }
1976           free_prefixlist (precedencelist);
1977
1978           /* Sort the entries so that the most specific ones are at
1979              the beginning.  */
1980           qsort (new_precedence, nprecedencelist, sizeof (*new_precedence),
1981                  prefixcmp);
1982         }
1983       else
1984         new_precedence = (struct prefixentry *) default_precedence;
1985
1986       struct scopeentry *new_scopes;
1987       if (nscopelist > 0)
1988         {
1989           if (!scopelist_nullbits)
1990             ++nscopelist;
1991           new_scopes = malloc (nscopelist * sizeof (*new_scopes));
1992           if (new_scopes == NULL)
1993             {
1994               if (new_labels != default_labels)
1995                 free (new_labels);
1996               if (new_precedence != default_precedence)
1997                 free (new_precedence);
1998               goto no_file;
1999             }
2000
2001           int i = nscopelist;
2002           if (!scopelist_nullbits)
2003             {
2004               --i;
2005               new_scopes[i].addr32 = 0;
2006               new_scopes[i].netmask = 0;
2007               new_scopes[i].scope = 14;
2008             }
2009
2010           struct scopelist *l = scopelist;
2011           while (i-- > 0)
2012             {
2013               new_scopes[i] = l->entry;
2014               l = l->next;
2015             }
2016           free_scopelist (scopelist);
2017
2018           /* Sort the entries so that the most specific ones are at
2019              the beginning.  */
2020           qsort (new_scopes, nscopelist, sizeof (*new_scopes),
2021                  scopecmp);
2022         }
2023       else
2024         new_scopes = (struct scopeentry *) default_scopes;
2025
2026       /* Now we are ready to replace the values.  */
2027       const struct prefixentry *old = labels;
2028       labels = new_labels;
2029       if (old != default_labels)
2030         free ((void *) old);
2031
2032       old = precedence;
2033       precedence = new_precedence;
2034       if (old != default_precedence)
2035         free ((void *) old);
2036
2037       const struct scopeentry *oldscope = scopes;
2038       scopes = new_scopes;
2039       if (oldscope != default_scopes)
2040         free ((void *) oldscope);
2041
2042       gaiconf_mtime = st.st_mtime;
2043     }
2044   else
2045     {
2046     no_file:
2047       free_prefixlist (labellist);
2048       free_prefixlist (precedencelist);
2049       free_scopelist (scopelist);
2050
2051       /* If we previously read the file but it is gone now, free the
2052          old data and use the builtin one.  Leave the reload flag
2053          alone.  */
2054       fini ();
2055     }
2056 }
2057
2058
2059 static void
2060 gaiconf_reload (void)
2061 {
2062   struct stat64 st;
2063   if (__xstat64 (_STAT_VER, GAICONF_FNAME, &st) != 0
2064       || memcmp (&st.st_mtime, &gaiconf_mtime, sizeof (gaiconf_mtime)) != 0)
2065     gaiconf_init ();
2066 }
2067
2068
2069 int
2070 getaddrinfo (const char *name, const char *service,
2071              const struct addrinfo *hints, struct addrinfo **pai)
2072 {
2073   int i = 0, last_i = 0;
2074   int nresults = 0;
2075   struct addrinfo *p = NULL;
2076   struct gaih_service gaih_service, *pservice;
2077   struct addrinfo local_hints;
2078
2079   if (name != NULL && name[0] == '*' && name[1] == 0)
2080     name = NULL;
2081
2082   if (service != NULL && service[0] == '*' && service[1] == 0)
2083     service = NULL;
2084
2085   if (name == NULL && service == NULL)
2086     return EAI_NONAME;
2087
2088   if (hints == NULL)
2089     hints = &default_hints;
2090
2091   if (hints->ai_flags
2092       & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|AI_ADDRCONFIG|AI_V4MAPPED
2093 #ifdef HAVE_LIBIDN
2094           |AI_IDN|AI_CANONIDN|AI_IDN_ALLOW_UNASSIGNED
2095           |AI_IDN_USE_STD3_ASCII_RULES
2096 #endif
2097           |AI_NUMERICSERV|AI_ALL))
2098     return EAI_BADFLAGS;
2099
2100   if ((hints->ai_flags & AI_CANONNAME) && name == NULL)
2101     return EAI_BADFLAGS;
2102
2103   struct in6addrinfo *in6ai = NULL;
2104   size_t in6ailen = 0;
2105   bool seen_ipv4 = false;
2106   bool seen_ipv6 = false;
2107   /* We might need information about what interfaces are available.
2108      Also determine whether we have IPv4 or IPv6 interfaces or both.  We
2109      cannot cache the results since new interfaces could be added at
2110      any time.  */
2111   __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen);
2112
2113   if (hints->ai_flags & AI_ADDRCONFIG)
2114     {
2115       /* Now make a decision on what we return, if anything.  */
2116       if (hints->ai_family == PF_UNSPEC && (seen_ipv4 || seen_ipv6))
2117         {
2118           /* If we haven't seen both IPv4 and IPv6 interfaces we can
2119              narrow down the search.  */
2120           if ((! seen_ipv4 || ! seen_ipv6) && (seen_ipv4 || seen_ipv6))
2121             {
2122               local_hints = *hints;
2123               local_hints.ai_family = seen_ipv4 ? PF_INET : PF_INET6;
2124               hints = &local_hints;
2125             }
2126         }
2127       else if ((hints->ai_family == PF_INET && ! seen_ipv4)
2128                || (hints->ai_family == PF_INET6 && ! seen_ipv6))
2129         {
2130           /* We cannot possibly return a valid answer.  */
2131           free (in6ai);
2132           return EAI_NONAME;
2133         }
2134     }
2135
2136   if (service && service[0])
2137     {
2138       char *c;
2139       gaih_service.name = service;
2140       gaih_service.num = strtoul (gaih_service.name, &c, 10);
2141       if (*c != '\0')
2142         {
2143           if (hints->ai_flags & AI_NUMERICSERV)
2144             {
2145               free (in6ai);
2146               return EAI_NONAME;
2147             }
2148
2149           gaih_service.num = -1;
2150         }
2151
2152       pservice = &gaih_service;
2153     }
2154   else
2155     pservice = NULL;
2156
2157   struct addrinfo **end = &p;
2158
2159   unsigned int naddrs = 0;
2160   if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET
2161       || hints->ai_family == AF_INET6)
2162     {
2163       last_i = gaih_inet (name, pservice, hints, end, &naddrs);
2164       if (last_i != 0)
2165         {
2166           freeaddrinfo (p);
2167           free (in6ai);
2168
2169           return -(last_i & GAIH_EAI);
2170         }
2171       while (*end)
2172         {
2173           end = &((*end)->ai_next);
2174           ++nresults;
2175         }
2176     }
2177   else
2178     {
2179       free (in6ai);
2180       return EAI_FAMILY;
2181     }
2182
2183   if (naddrs > 1)
2184     {
2185       /* Read the config file.  */
2186       __libc_once_define (static, once);
2187       __typeof (once) old_once = once;
2188       __libc_once (once, gaiconf_init);
2189       /* Sort results according to RFC 3484.  */
2190       struct sort_result results[nresults];
2191       size_t order[nresults];
2192       struct addrinfo *q;
2193       struct addrinfo *last = NULL;
2194       char *canonname = NULL;
2195
2196       /* If we have information about deprecated and temporary addresses
2197          sort the array now.  */
2198       if (in6ai != NULL)
2199         qsort (in6ai, in6ailen, sizeof (*in6ai), in6aicmp);
2200
2201       int fd = -1;
2202       int af = AF_UNSPEC;
2203
2204       for (i = 0, q = p; q != NULL; ++i, last = q, q = q->ai_next)
2205         {
2206           results[i].dest_addr = q;
2207           results[i].native = -1;
2208           order[i] = i;
2209
2210           /* If we just looked up the address for a different
2211              protocol, reuse the result.  */
2212           if (last != NULL && last->ai_addrlen == q->ai_addrlen
2213               && memcmp (last->ai_addr, q->ai_addr, q->ai_addrlen) == 0)
2214             {
2215               memcpy (&results[i].source_addr, &results[i - 1].source_addr,
2216                       results[i - 1].source_addr_len);
2217               results[i].source_addr_len = results[i - 1].source_addr_len;
2218               results[i].got_source_addr = results[i - 1].got_source_addr;
2219               results[i].source_addr_flags = results[i - 1].source_addr_flags;
2220               results[i].prefixlen = results[i - 1].prefixlen;
2221               results[i].index = results[i - 1].index;
2222             }
2223           else
2224             {
2225               results[i].got_source_addr = false;
2226               results[i].source_addr_flags = 0;
2227               results[i].prefixlen = 0;
2228               results[i].index = 0xffffffffu;
2229
2230               /* We overwrite the type with SOCK_DGRAM since we do not
2231                  want connect() to connect to the other side.  If we
2232                  cannot determine the source address remember this
2233                  fact.  */
2234               if (fd == -1 || (af == AF_INET && q->ai_family == AF_INET6))
2235                 {
2236                   if (fd != -1)
2237                   close_retry:
2238                     close_not_cancel_no_status (fd);
2239                   af = q->ai_family;
2240                   fd = __socket (af, SOCK_DGRAM, IPPROTO_IP);
2241                 }
2242               else
2243                 {
2244                   /* Reset the connection.  */
2245                   struct sockaddr sa = { .sa_family = AF_UNSPEC };
2246                   __connect (fd, &sa, sizeof (sa));
2247                 }
2248
2249               socklen_t sl = sizeof (results[i].source_addr);
2250               if (fd != -1
2251                   && __connect (fd, q->ai_addr, q->ai_addrlen) == 0
2252                   && __getsockname (fd,
2253                                     (struct sockaddr *) &results[i].source_addr,
2254                                     &sl) == 0)
2255                 {
2256                   results[i].source_addr_len = sl;
2257                   results[i].got_source_addr = true;
2258
2259                   if (in6ai != NULL)
2260                     {
2261                       /* See whether the source address is on the list of
2262                          deprecated or temporary addresses.  */
2263                       struct in6addrinfo tmp;
2264
2265                       if (q->ai_family == AF_INET && af == AF_INET)
2266                         {
2267                           struct sockaddr_in *sinp
2268                             = (struct sockaddr_in *) &results[i].source_addr;
2269                           tmp.addr[0] = 0;
2270                           tmp.addr[1] = 0;
2271                           tmp.addr[2] = htonl (0xffff);
2272                           tmp.addr[3] = sinp->sin_addr.s_addr;
2273                         }
2274                       else
2275                         {
2276                           struct sockaddr_in6 *sin6p
2277                             = (struct sockaddr_in6 *) &results[i].source_addr;
2278                           memcpy (tmp.addr, &sin6p->sin6_addr, IN6ADDRSZ);
2279                         }
2280
2281                       struct in6addrinfo *found
2282                         = bsearch (&tmp, in6ai, in6ailen, sizeof (*in6ai),
2283                                    in6aicmp);
2284                       if (found != NULL)
2285                         {
2286                           results[i].source_addr_flags = found->flags;
2287                           results[i].prefixlen = found->prefixlen;
2288                           results[i].index = found->index;
2289                         }
2290                     }
2291
2292                   if (q->ai_family == AF_INET && af == AF_INET6)
2293                     {
2294                       /* We have to convert the address.  The socket is
2295                          IPv6 and the request is for IPv4.  */
2296                       struct sockaddr_in6 *sin6
2297                         = (struct sockaddr_in6 *) &results[i].source_addr;
2298                       struct sockaddr_in *sin
2299                         = (struct sockaddr_in *) &results[i].source_addr;
2300                       assert (IN6_IS_ADDR_V4MAPPED (sin6->sin6_addr.s6_addr32));
2301                       sin->sin_family = AF_INET;
2302                       /* We do not have to initialize sin_port since this
2303                          fields has the same position and size in the IPv6
2304                          structure.  */
2305                       assert (offsetof (struct sockaddr_in, sin_port)
2306                               == offsetof (struct sockaddr_in6, sin6_port));
2307                       assert (sizeof (sin->sin_port)
2308                               == sizeof (sin6->sin6_port));
2309                       memcpy (&sin->sin_addr,
2310                               &sin6->sin6_addr.s6_addr32[3], INADDRSZ);
2311                       results[i].source_addr_len = sizeof (struct sockaddr_in);
2312                     }
2313                 }
2314               else if (errno == EAFNOSUPPORT && af == AF_INET6
2315                        && q->ai_family == AF_INET)
2316                 /* This could mean IPv6 sockets are IPv6-only.  */
2317                 goto close_retry;
2318               else
2319                 /* Just make sure that if we have to process the same
2320                    address again we do not copy any memory.  */
2321                 results[i].source_addr_len = 0;
2322             }
2323
2324           /* Remember the canonical name.  */
2325           if (q->ai_canonname != NULL)
2326             {
2327               assert (canonname == NULL);
2328               canonname = q->ai_canonname;
2329               q->ai_canonname = NULL;
2330             }
2331         }
2332
2333       if (fd != -1)
2334         close_not_cancel_no_status (fd);
2335
2336       /* We got all the source addresses we can get, now sort using
2337          the information.  */
2338       struct sort_result_combo src
2339         = { .results = results, .nresults = nresults };
2340       if (__builtin_expect (gaiconf_reload_flag_ever_set, 0))
2341         {
2342           __libc_lock_define_initialized (static, lock);
2343
2344           __libc_lock_lock (lock);
2345           if (old_once && gaiconf_reload_flag)
2346             gaiconf_reload ();
2347           qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
2348           __libc_lock_unlock (lock);
2349         }
2350       else
2351         qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
2352
2353       /* Queue the results up as they come out of sorting.  */
2354       q = p = results[order[0]].dest_addr;
2355       for (i = 1; i < nresults; ++i)
2356         q = q->ai_next = results[order[i]].dest_addr;
2357       q->ai_next = NULL;
2358
2359       /* Fill in the canonical name into the new first entry.  */
2360       p->ai_canonname = canonname;
2361     }
2362
2363   free (in6ai);
2364
2365   if (p)
2366     {
2367       *pai = p;
2368       return 0;
2369     }
2370
2371   return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;
2372 }
2373 libc_hidden_def (getaddrinfo)
2374
2375 static_link_warning (getaddrinfo)
2376
2377 void
2378 freeaddrinfo (struct addrinfo *ai)
2379 {
2380   struct addrinfo *p;
2381
2382   while (ai != NULL)
2383     {
2384       p = ai;
2385       ai = ai->ai_next;
2386       free (p->ai_canonname);
2387       free (p);
2388     }
2389 }
2390 libc_hidden_def (freeaddrinfo)