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