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