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