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