Implement AI_CANONIDN.
[kopensolaris-gnu/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 <errno.h>
40 #include <ifaddrs.h>
41 #include <netdb.h>
42 #include <resolv.h>
43 #include <stdbool.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <unistd.h>
48 #include <arpa/inet.h>
49 #include <sys/socket.h>
50 #include <netinet/in.h>
51 #include <sys/types.h>
52 #include <sys/un.h>
53 #include <sys/utsname.h>
54 #include <net/if.h>
55 #include <nsswitch.h>
56 #include <not-cancel.h>
57
58 #ifdef HAVE_LIBIDN
59 extern int __idna_to_ascii_lz (const char *input, char **output, int flags);
60 extern int __idna_to_unicode_lzlz (const char *input, char **output,
61                                    int flags);
62 # include <libidn/idna.h>
63 #endif
64
65 #define GAIH_OKIFUNSPEC 0x0100
66 #define GAIH_EAI        ~(GAIH_OKIFUNSPEC)
67
68 #ifndef UNIX_PATH_MAX
69 #define UNIX_PATH_MAX  108
70 #endif
71
72 struct gaih_service
73   {
74     const char *name;
75     int num;
76   };
77
78 struct gaih_servtuple
79   {
80     struct gaih_servtuple *next;
81     int socktype;
82     int protocol;
83     int port;
84   };
85
86 static const struct gaih_servtuple nullserv;
87
88 struct gaih_addrtuple
89   {
90     struct gaih_addrtuple *next;
91     int family;
92     char addr[16];
93     uint32_t scopeid;
94   };
95
96 struct gaih_typeproto
97   {
98     int socktype;
99     int protocol;
100     char name[4];
101     int protoflag;
102   };
103
104 /* Values for `protoflag'.  */
105 #define GAI_PROTO_NOSERVICE     1
106 #define GAI_PROTO_PROTOANY      2
107
108 static const struct gaih_typeproto gaih_inet_typeproto[] =
109 {
110   { 0, 0, "", 0 },
111   { SOCK_STREAM, IPPROTO_TCP, "tcp", 0 },
112   { SOCK_DGRAM, IPPROTO_UDP, "udp", 0 },
113   { SOCK_RAW, 0, "raw", GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE },
114   { 0, 0, "", 0 }
115 };
116
117 struct gaih
118   {
119     int family;
120     int (*gaih)(const char *name, const struct gaih_service *service,
121                 const struct addrinfo *req, struct addrinfo **pai);
122   };
123
124 static const struct addrinfo default_hints =
125   {
126     .ai_flags = AI_DEFAULT,
127     .ai_family = PF_UNSPEC,
128     .ai_socktype = 0,
129     .ai_protocol = 0,
130     .ai_addrlen = 0,
131     .ai_addr = NULL,
132     .ai_canonname = NULL,
133     .ai_next = NULL
134   };
135
136
137 #if 0
138 /* Using Unix sockets this way is a security risk.  */
139 static int
140 gaih_local (const char *name, const struct gaih_service *service,
141             const struct addrinfo *req, struct addrinfo **pai)
142 {
143   struct utsname utsname;
144
145   if ((name != NULL) && (req->ai_flags & AI_NUMERICHOST))
146     return GAIH_OKIFUNSPEC | -EAI_NONAME;
147
148   if ((name != NULL) || (req->ai_flags & AI_CANONNAME))
149     if (uname (&utsname) < 0)
150       return -EAI_SYSTEM;
151
152   if (name != NULL)
153     {
154       if (strcmp(name, "localhost") &&
155           strcmp(name, "local") &&
156           strcmp(name, "unix") &&
157           strcmp(name, utsname.nodename))
158         return GAIH_OKIFUNSPEC | -EAI_NONAME;
159     }
160
161   if (req->ai_protocol || req->ai_socktype)
162     {
163       const struct gaih_typeproto *tp = gaih_inet_typeproto + 1;
164
165       while (tp->name[0]
166              && ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0
167                  || (req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
168                  || (req->ai_protocol != 0
169                      && !(tp->protoflag & GAI_PROTO_PROTOANY)
170                      && req->ai_protocol != tp->protocol)))
171         ++tp;
172
173       if (! tp->name[0])
174         {
175           if (req->ai_socktype)
176             return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE);
177           else
178             return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
179         }
180     }
181
182   *pai = malloc (sizeof (struct addrinfo) + sizeof (struct sockaddr_un)
183                  + ((req->ai_flags & AI_CANONNAME)
184                     ? (strlen(utsname.nodename) + 1): 0));
185   if (*pai == NULL)
186     return -EAI_MEMORY;
187
188   (*pai)->ai_next = NULL;
189   (*pai)->ai_flags = req->ai_flags;
190   (*pai)->ai_family = AF_LOCAL;
191   (*pai)->ai_socktype = req->ai_socktype ? req->ai_socktype : SOCK_STREAM;
192   (*pai)->ai_protocol = req->ai_protocol;
193   (*pai)->ai_addrlen = sizeof (struct sockaddr_un);
194   (*pai)->ai_addr = (void *) (*pai) + sizeof (struct addrinfo);
195
196 #if SALEN
197   ((struct sockaddr_un *) (*pai)->ai_addr)->sun_len =
198     sizeof (struct sockaddr_un);
199 #endif /* SALEN */
200
201   ((struct sockaddr_un *)(*pai)->ai_addr)->sun_family = AF_LOCAL;
202   memset(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, 0, UNIX_PATH_MAX);
203
204   if (service)
205     {
206       struct sockaddr_un *sunp = (struct sockaddr_un *) (*pai)->ai_addr;
207
208       if (strchr (service->name, '/') != NULL)
209         {
210           if (strlen (service->name) >= sizeof (sunp->sun_path))
211             return GAIH_OKIFUNSPEC | -EAI_SERVICE;
212
213           strcpy (sunp->sun_path, service->name);
214         }
215       else
216         {
217           if (strlen (P_tmpdir "/") + 1 + strlen (service->name) >=
218               sizeof (sunp->sun_path))
219             return GAIH_OKIFUNSPEC | -EAI_SERVICE;
220
221           __stpcpy (__stpcpy (sunp->sun_path, P_tmpdir "/"), service->name);
222         }
223     }
224   else
225     {
226       /* This is a dangerous use of the interface since there is a time
227          window between the test for the file and the actual creation
228          (done by the caller) in which a file with the same name could
229          be created.  */
230       char *buf = ((struct sockaddr_un *) (*pai)->ai_addr)->sun_path;
231
232       if (__builtin_expect (__path_search (buf, L_tmpnam, NULL, NULL, 0),
233                             0) != 0
234           || __builtin_expect (__gen_tempname (buf, __GT_NOCREATE), 0) != 0)
235         return -EAI_SYSTEM;
236     }
237
238   if (req->ai_flags & AI_CANONNAME)
239     (*pai)->ai_canonname = strcpy ((char *) *pai + sizeof (struct addrinfo)
240                                    + sizeof (struct sockaddr_un),
241                                    utsname.nodename);
242   else
243     (*pai)->ai_canonname = NULL;
244   return 0;
245 }
246 #endif  /* 0 */
247
248 static int
249 gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
250                const struct addrinfo *req, struct gaih_servtuple *st)
251 {
252   struct servent *s;
253   size_t tmpbuflen = 1024;
254   struct servent ts;
255   char *tmpbuf;
256   int r;
257
258   do
259     {
260       tmpbuf = __alloca (tmpbuflen);
261
262       r = __getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen,
263                              &s);
264       if (r != 0 || s == NULL)
265         {
266           if (r == ERANGE)
267             tmpbuflen *= 2;
268           else
269             return GAIH_OKIFUNSPEC | -EAI_SERVICE;
270         }
271     }
272   while (r);
273
274   st->next = NULL;
275   st->socktype = tp->socktype;
276   st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
277                   ? req->ai_protocol : tp->protocol);
278   st->port = s->s_port;
279
280   return 0;
281 }
282
283 #define gethosts(_family, _type) \
284  {                                                                            \
285   int i, herrno;                                                              \
286   size_t tmpbuflen;                                                           \
287   struct hostent th;                                                          \
288   char *tmpbuf = NULL;                                                        \
289   tmpbuflen = 512;                                                            \
290   no_data = 0;                                                                \
291   do {                                                                        \
292     tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);                \
293     rc = __gethostbyname2_r (name, _family, &th, tmpbuf,                      \
294          tmpbuflen, &h, &herrno);                                             \
295   } while (rc == ERANGE && herrno == NETDB_INTERNAL);                         \
296   if (rc != 0)                                                                \
297     {                                                                         \
298       if (herrno == NETDB_INTERNAL)                                           \
299         {                                                                     \
300           __set_h_errno (herrno);                                             \
301           return -EAI_SYSTEM;                                                 \
302         }                                                                     \
303       if (herrno == TRY_AGAIN)                                                \
304         no_data = EAI_AGAIN;                                                  \
305       else                                                                    \
306         no_data = herrno == NO_DATA;                                          \
307     }                                                                         \
308   else if (h != NULL)                                                         \
309     {                                                                         \
310       for (i = 0; h->h_addr_list[i]; i++)                                     \
311         {                                                                     \
312           if (*pat == NULL) {                                                 \
313             *pat = __alloca (sizeof (struct gaih_addrtuple));                 \
314             (*pat)->scopeid = 0;                                              \
315           }                                                                   \
316           (*pat)->next = NULL;                                                \
317           (*pat)->family = _family;                                           \
318           memcpy ((*pat)->addr, h->h_addr_list[i],                            \
319                  sizeof(_type));                                              \
320           pat = &((*pat)->next);                                              \
321         }                                                                     \
322       if (_family == AF_INET6)                                                \
323         got_ipv6 = true;                                                      \
324     }                                                                         \
325   else if (_family == AF_INET6 && (req->ai_flags & AI_V4MAPPED))              \
326     {                                                                         \
327       /* We have to add V4 mapped addresses.  Maybe we discard them           \
328          later again but we get them anyhow for now.  */                      \
329       while ((rc = __gethostbyname2_r (name, AF_INET6, &th, tmpbuf,           \
330                                        tmpbuflen, &h, &herrno)) == ERANGE     \
331              && herrno == NETDB_INTERNAL)                                     \
332         tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);            \
333                                                                               \
334       if (rc != 0)                                                            \
335         {                                                                     \
336           if (herrno == NETDB_INTERNAL)                                       \
337             {                                                                 \
338               __set_h_errno (herrno);                                         \
339               return -EAI_SYSTEM;                                             \
340             }                                                                 \
341           if (herrno == TRY_AGAIN)                                            \
342             no_data = EAI_AGAIN;                                              \
343           else                                                                \
344             no_data = herrno == NO_DATA;                                      \
345         }                                                                     \
346       else if (h != NULL)                                                     \
347         {                                                                     \
348           for (i = 0; h->h_addr_list[i]; ++i)                                 \
349             {                                                                 \
350               if (*pat == NULL)                                               \
351                 {                                                             \
352                   *pat = __alloca (sizeof (struct gaih_addrtuple));           \
353                   (*pat)->scopeid = 0;                                        \
354                 }                                                             \
355               uint32_t *addr = (uint32_t *) (*pat)->addr;                     \
356               (*pat)->next = NULL;                                            \
357               (*pat)->family = _family;                                       \
358               addr[3] = *(uint32_t *) h->h_addr_list[i];                      \
359               addr[2] = htonl (0xffff);                                       \
360               addr[1] = 0;                                                    \
361               addr[0] = 0;                                                    \
362               pat = &((*pat)->next);                                          \
363             }                                                                 \
364         }                                                                     \
365     }                                                                         \
366  }
367
368
369 #define gethosts2(_family, _type) \
370  {                                                                            \
371   int i, herrno;                                                              \
372   size_t tmpbuflen;                                                           \
373   struct hostent th;                                                          \
374   char *tmpbuf = NULL;                                                        \
375   tmpbuflen = 512;                                                            \
376   no_data = 0;                                                                \
377   do {                                                                        \
378     tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);                \
379     rc = 0;                                                                   \
380     status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf,                   \
381            tmpbuflen, &rc, &herrno));                                         \
382   } while (rc == ERANGE && herrno == NETDB_INTERNAL);                         \
383   if (status == NSS_STATUS_SUCCESS && rc == 0)                                \
384     h = &th;                                                                  \
385   else                                                                        \
386     h = NULL;                                                                 \
387   if (rc != 0)                                                                \
388     {                                                                         \
389       if (herrno == NETDB_INTERNAL)                                           \
390         {                                                                     \
391           __set_h_errno (herrno);                                             \
392           return -EAI_SYSTEM;                                                 \
393         }                                                                     \
394       if (herrno == TRY_AGAIN)                                                \
395         no_data = EAI_AGAIN;                                                  \
396       else                                                                    \
397         no_data = herrno == NO_DATA;                                          \
398     }                                                                         \
399   else if (h != NULL)                                                         \
400     {                                                                         \
401       for (i = 0; h->h_addr_list[i]; i++)                                     \
402         {                                                                     \
403           if (*pat == NULL) {                                                 \
404             *pat = __alloca (sizeof (struct gaih_addrtuple));                 \
405             (*pat)->scopeid = 0;                                              \
406           }                                                                   \
407           (*pat)->next = NULL;                                                \
408           (*pat)->family = _family;                                           \
409           memcpy ((*pat)->addr, h->h_addr_list[i],                            \
410                  sizeof(_type));                                              \
411           pat = &((*pat)->next);                                              \
412         }                                                                     \
413     }                                                                         \
414  }
415
416 typedef enum nss_status (*nss_gethostbyname2_r)
417   (const char *name, int af, struct hostent *host,
418    char *buffer, size_t buflen, int *errnop,
419    int *h_errnop);
420 extern service_user *__nss_hosts_database attribute_hidden;
421
422 static int
423 gaih_inet (const char *name, const struct gaih_service *service,
424            const struct addrinfo *req, struct addrinfo **pai)
425 {
426   const struct gaih_typeproto *tp = gaih_inet_typeproto;
427   struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv;
428   struct gaih_addrtuple *at = NULL;
429   int rc;
430   bool got_ipv6 = false;
431
432   if (req->ai_protocol || req->ai_socktype)
433     {
434       ++tp;
435
436       while (tp->name[0]
437              && ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
438                  || (req->ai_protocol != 0
439                      && !(tp->protoflag & GAI_PROTO_PROTOANY)
440                      && req->ai_protocol != tp->protocol)))
441         ++tp;
442
443       if (! tp->name[0])
444         {
445           if (req->ai_socktype)
446             return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE);
447           else
448             return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
449         }
450     }
451
452   if (service != NULL)
453     {
454       if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
455         return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
456
457       if (service->num < 0)
458         {
459           if (tp->name[0])
460             {
461               st = (struct gaih_servtuple *)
462                 __alloca (sizeof (struct gaih_servtuple));
463
464               if ((rc = gaih_inet_serv (service->name, tp, req, st)))
465                 return rc;
466             }
467           else
468             {
469               struct gaih_servtuple **pst = &st;
470               for (tp++; tp->name[0]; tp++)
471                 {
472                   struct gaih_servtuple *newp;
473
474                   if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
475                     continue;
476
477                   if (req->ai_socktype != 0
478                       && req->ai_socktype != tp->socktype)
479                     continue;
480                   if (req->ai_protocol != 0
481                       && !(tp->protoflag & GAI_PROTO_PROTOANY)
482                       && req->ai_protocol != tp->protocol)
483                     continue;
484
485                   newp = (struct gaih_servtuple *)
486                     __alloca (sizeof (struct gaih_servtuple));
487
488                   if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
489                     {
490                       if (rc & GAIH_OKIFUNSPEC)
491                         continue;
492                       return rc;
493                     }
494
495                   *pst = newp;
496                   pst = &(newp->next);
497                 }
498               if (st == (struct gaih_servtuple *) &nullserv)
499                 return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
500             }
501         }
502       else
503         {
504           st = __alloca (sizeof (struct gaih_servtuple));
505           st->next = NULL;
506           st->socktype = tp->socktype;
507           st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
508                           ? req->ai_protocol : tp->protocol);
509           st->port = htons (service->num);
510         }
511     }
512   else if (req->ai_socktype || req->ai_protocol)
513     {
514       st = __alloca (sizeof (struct gaih_servtuple));
515       st->next = NULL;
516       st->socktype = tp->socktype;
517       st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
518                       ? req->ai_protocol : tp->protocol);
519       st->port = 0;
520     }
521   else
522     {
523       /* Neither socket type nor protocol is set.  Return all socket types
524          we know about.  */
525       struct gaih_servtuple **lastp = &st;
526       for (++tp; tp->name[0]; ++tp)
527         {
528           struct gaih_servtuple *newp;
529
530           newp = __alloca (sizeof (struct gaih_servtuple));
531           newp->next = NULL;
532           newp->socktype = tp->socktype;
533           newp->protocol = tp->protocol;
534           newp->port = 0;
535
536           *lastp = newp;
537           lastp = &newp->next;
538         }
539     }
540
541   if (name != NULL)
542     {
543       at = __alloca (sizeof (struct gaih_addrtuple));
544
545       at->family = AF_UNSPEC;
546       at->scopeid = 0;
547       at->next = NULL;
548
549 #ifdef HAVE_LIBIDN
550       if (req->ai_flags & AI_IDN)
551         {
552           char *p = NULL;
553           rc = __idna_to_ascii_lz (name, &p, 0);
554           if (rc != IDNA_SUCCESS)
555             {
556               if (rc == IDNA_MALLOC_ERROR)
557                 return -EAI_MEMORY;
558               if (rc == IDNA_DLOPEN_ERROR)
559                 return -EAI_SYSTEM;
560               return -EAI_IDN_ENCODE;
561             }
562           /* In case the output string is the same as the input string
563              no new string has been allocated.  */
564           if (p != name)
565             {
566               name = strdupa (p);
567               free (p);
568             }
569         }
570 #endif
571
572       if (inet_pton (AF_INET, name, at->addr) > 0)
573         {
574           if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
575             at->family = AF_INET;
576           else if (req->ai_flags & AI_V4MAPPED)
577             {
578               ((uint32_t *) at->addr)[3] = *(uint32_t *) at->addr;
579               ((uint32_t *) at->addr)[2] = htonl (0xffff);
580               ((uint32_t *) at->addr)[1] = 0;
581               ((uint32_t *) at->addr)[0] = 0;
582             }
583           else
584             return -EAI_ADDRFAMILY;
585         }
586
587       if (at->family == AF_UNSPEC)
588         {
589           char *namebuf = strdupa (name);
590           char *scope_delim;
591
592           scope_delim = strchr (namebuf, SCOPE_DELIMITER);
593           if (scope_delim != NULL)
594             *scope_delim = '\0';
595
596           if (inet_pton (AF_INET6, namebuf, at->addr) > 0)
597             {
598               if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
599                 at->family = AF_INET6;
600               else if (IN6_IS_ADDR_V4MAPPED (at->addr))
601                 *(uint32_t *) at->addr = ((uint32_t *) at->addr)[3];
602               else
603                 return -EAI_ADDRFAMILY;
604
605               if (scope_delim != NULL)
606                 {
607                   int try_numericscope = 0;
608                   if (IN6_IS_ADDR_LINKLOCAL (at->addr)
609                       || IN6_IS_ADDR_MC_LINKLOCAL (at->addr))
610                     {
611                       at->scopeid = if_nametoindex (scope_delim + 1);
612                       if (at->scopeid == 0)
613                         try_numericscope = 1;
614                     }
615                   else
616                     try_numericscope = 1;
617
618                   if (try_numericscope != 0)
619                     {
620                       char *end;
621                       assert (sizeof (uint32_t) <= sizeof (unsigned long));
622                       at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
623                                                         10);
624                       if (*end != '\0')
625                         return GAIH_OKIFUNSPEC | -EAI_NONAME;
626                     }
627                 }
628             }
629         }
630
631       if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0)
632         {
633           struct hostent *h;
634           struct gaih_addrtuple **pat = &at;
635           int no_data = 0;
636           int no_inet6_data = 0;
637           /* If we are looking for both IPv4 and IPv6 address we don't
638              want the lookup functions to automatically promote IPv4
639              addresses to IPv6 addresses.  Currently this is decided
640              by setting the RES_USE_INET6 bit in _res.options.  */
641           if (req->ai_family == AF_UNSPEC)
642             {
643               service_user *nip = NULL;
644               enum nss_status inet6_status, status = NSS_STATUS_UNAVAIL;
645               int no_more;
646               nss_gethostbyname2_r fct;
647               int old_res_options;
648
649               if (__nss_hosts_database != NULL)
650                 {
651                   no_more = 0;
652                   nip = __nss_hosts_database;
653                 }
654               else
655                 no_more = __nss_database_lookup ("hosts", NULL,
656                                                  "dns [!UNAVAIL=return] files", &nip);
657
658               if ((_res.options & RES_INIT) == 0 && __res_ninit(&_res) == -1)
659                 no_more = 1;
660               old_res_options = _res.options;
661               _res.options &= ~RES_USE_INET6;
662
663               while (!no_more)
664                 {
665                   fct = __nss_lookup_function (nip, "gethostbyname2_r");
666
667                   if (fct != NULL)
668                     {
669                       gethosts2 (AF_INET6, struct in6_addr);
670                       no_inet6_data = no_data;
671                       inet6_status = status;
672                       gethosts2 (AF_INET, struct in_addr);
673
674                       /* If we found one address for AF_INET or AF_INET6,
675                          don't continue the search.  */
676                       if (inet6_status == NSS_STATUS_SUCCESS ||
677                           status == NSS_STATUS_SUCCESS)
678                         break;
679
680                       /* We can have different states for AF_INET
681                          and AF_INET6. Try to find a usefull one for
682                          both.  */
683                       if (inet6_status == NSS_STATUS_TRYAGAIN)
684                         status = NSS_STATUS_TRYAGAIN;
685                       else if (status == NSS_STATUS_UNAVAIL &&
686                                inet6_status != NSS_STATUS_UNAVAIL)
687                         status = inet6_status;
688                     }
689
690                   if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
691                     break;
692
693                   if (nip->next == NULL)
694                     no_more = -1;
695                   else
696                     nip = nip->next;
697                 }
698
699               _res.options = old_res_options;
700             }
701           else if (req->ai_family == AF_INET6)
702             {
703               gethosts (AF_INET6, struct in6_addr);
704               no_inet6_data = no_data;
705             }
706           else if (req->ai_family == AF_INET)
707             {
708               gethosts (AF_INET, struct in_addr);
709               no_inet6_data = no_data;
710             }
711
712           if (no_data != 0 && no_inet6_data != 0)
713             {
714               /* If both requests timed out report this.  */
715               if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
716                 return -EAI_AGAIN;
717
718               /* We made requests but they turned out no data.  The name
719                  is known, though.  */
720               return (GAIH_OKIFUNSPEC | -EAI_NODATA);
721             }
722         }
723
724       if (at->family == AF_UNSPEC)
725         return (GAIH_OKIFUNSPEC | -EAI_NONAME);
726     }
727   else
728     {
729       struct gaih_addrtuple *atr;
730       atr = at = __alloca (sizeof (struct gaih_addrtuple));
731       memset (at, '\0', sizeof (struct gaih_addrtuple));
732
733       if (req->ai_family == 0)
734         {
735           at->next = __alloca (sizeof (struct gaih_addrtuple));
736           memset (at->next, '\0', sizeof (struct gaih_addrtuple));
737         }
738
739       if (req->ai_family == 0 || req->ai_family == AF_INET6)
740         {
741           at->family = AF_INET6;
742           if ((req->ai_flags & AI_PASSIVE) == 0)
743             memcpy (at->addr, &in6addr_loopback, sizeof (struct in6_addr));
744           atr = at->next;
745         }
746
747       if (req->ai_family == 0 || req->ai_family == AF_INET)
748         {
749           atr->family = AF_INET;
750           if ((req->ai_flags & AI_PASSIVE) == 0)
751             *(uint32_t *) atr->addr = htonl (INADDR_LOOPBACK);
752         }
753     }
754
755   if (pai == NULL)
756     return 0;
757
758   {
759     const char *c = NULL;
760     struct gaih_servtuple *st2;
761     struct gaih_addrtuple *at2 = at;
762     size_t socklen, namelen;
763     sa_family_t family;
764
765     /*
766       buffer is the size of an unformatted IPv6 address in printable format.
767      */
768     while (at2 != NULL)
769       {
770         if (req->ai_flags & AI_CANONNAME)
771           {
772             struct hostent *h = NULL;
773
774             int herrno;
775             struct hostent th;
776             size_t tmpbuflen = 512;
777             char *tmpbuf = NULL;
778
779             do
780               {
781                 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, tmpbuflen * 2);
782                 rc = __gethostbyaddr_r (at2->addr,
783                                         ((at2->family == AF_INET6)
784                                          ? sizeof(struct in6_addr)
785                                          : sizeof(struct in_addr)),
786                                         at2->family, &th, tmpbuf, tmpbuflen,
787                                         &h, &herrno);
788
789               }
790             while (rc == ERANGE && herrno == NETDB_INTERNAL);
791
792             if (rc != 0 && herrno == NETDB_INTERNAL)
793               {
794                 __set_h_errno (herrno);
795                 return -EAI_SYSTEM;
796               }
797
798             if (h != NULL)
799               c = h->h_name;
800             else
801               {
802                 /* We have to try to get the canonical in some other
803                    way.  If we are looking for either AF_INET or
804                    AF_INET6 try the other line.  */
805                 if (req->ai_family == AF_UNSPEC)
806                   {
807                     struct addrinfo *p = NULL;
808                     struct addrinfo **end = &p;
809                     struct addrinfo localreq = *req;
810                     struct addrinfo *runp;
811
812                     localreq.ai_family = AF_INET + AF_INET6 - at2->family;
813                     (void) gaih_inet (name, service, &localreq, end);
814
815                     runp = p;
816                     while (runp != NULL)
817                       {
818                         if (p->ai_canonname != name)
819                           {
820                             c = strdupa (p->ai_canonname);
821                             break;
822                           }
823                         runp = runp->ai_next;
824                       }
825
826                     freeaddrinfo (p);
827                   }
828
829                 /* If this code is used the missing canonical name is
830                    substituted with the name passed in by the user.  */
831                 if (c == NULL)
832                   c = name;
833               }
834
835             if (c == NULL)
836               return GAIH_OKIFUNSPEC | -EAI_NONAME;
837
838 #ifdef HAVE_LIBIDN
839             if (req->ai_flags & AI_CANONIDN)
840               {
841                 char *out;
842                 int rc = __idna_to_unicode_lzlz (c, &out, 0);
843                 if (rc != IDNA_SUCCESS)
844                   {
845                     if (rc == IDNA_MALLOC_ERROR)
846                       return -EAI_MEMORY;
847                     if (rc == IDNA_DLOPEN_ERROR)
848                       return -EAI_SYSTEM;
849                     return -EAI_IDN_ENCODE;
850                   }
851                 /* In case the output string is the same as the input
852                    string no new string has been allocated.  */
853                 if (out != c)
854                   {
855                     c = strdupa (out);
856                     free (out);
857                   }
858               }
859 #endif
860
861             namelen = strlen (c) + 1;
862           }
863         else
864           namelen = 0;
865
866         if (at2->family == AF_INET6)
867           {
868             family = AF_INET6;
869             socklen = sizeof (struct sockaddr_in6);
870
871             /* If we looked up IPv4 mapped address discard them here if
872                the caller isn't interested in all address and we have
873                found at least one IPv6 address.  */
874             if (! got_ipv6
875                 && (req->ai_flags & (AI_V4MAPPED|AI_ALL)) == AI_V4MAPPED
876                 && IN6_IS_ADDR_V4MAPPED (at2->addr))
877               goto ignore;
878           }
879         else
880           {
881             family = AF_INET;
882             socklen = sizeof (struct sockaddr_in);
883           }
884
885         for (st2 = st; st2 != NULL; st2 = st2->next)
886           {
887             *pai = malloc (sizeof (struct addrinfo) + socklen + namelen);
888             if (*pai == NULL)
889               return -EAI_MEMORY;
890
891             (*pai)->ai_flags = req->ai_flags;
892             (*pai)->ai_family = family;
893             (*pai)->ai_socktype = st2->socktype;
894             (*pai)->ai_protocol = st2->protocol;
895             (*pai)->ai_addrlen = socklen;
896             (*pai)->ai_addr = (void *) (*pai) + sizeof (struct addrinfo);
897 #if SALEN
898             (*pai)->ai_addr->sa_len = socklen;
899 #endif /* SALEN */
900             (*pai)->ai_addr->sa_family = family;
901
902             if (family == AF_INET6)
903               {
904                 struct sockaddr_in6 *sin6p =
905                   (struct sockaddr_in6 *) (*pai)->ai_addr;
906
907                 sin6p->sin6_flowinfo = 0;
908                 memcpy (&sin6p->sin6_addr,
909                         at2->addr, sizeof (struct in6_addr));
910                 sin6p->sin6_port = st2->port;
911                 sin6p->sin6_scope_id = at2->scopeid;
912               }
913             else
914               {
915                 struct sockaddr_in *sinp =
916                   (struct sockaddr_in *) (*pai)->ai_addr;
917                 memcpy (&sinp->sin_addr,
918                         at2->addr, sizeof (struct in_addr));
919                 sinp->sin_port = st2->port;
920                 memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
921               }
922
923             if (c)
924               {
925                 (*pai)->ai_canonname = ((void *) (*pai) +
926                                         sizeof (struct addrinfo) + socklen);
927                 strcpy ((*pai)->ai_canonname, c);
928               }
929             else
930               (*pai)->ai_canonname = NULL;
931
932             (*pai)->ai_next = NULL;
933             pai = &((*pai)->ai_next);
934           }
935
936       ignore:
937         at2 = at2->next;
938       }
939   }
940   return 0;
941 }
942
943 static struct gaih gaih[] =
944   {
945     { PF_INET6, gaih_inet },
946     { PF_INET, gaih_inet },
947 #if 0
948     { PF_LOCAL, gaih_local },
949 #endif
950     { PF_UNSPEC, NULL }
951   };
952
953 struct sort_result
954 {
955   struct addrinfo *dest_addr;
956   struct sockaddr_storage source_addr;
957   bool got_source_addr;
958 };
959
960
961 static int
962 get_scope (const struct sockaddr_storage *ss)
963 {
964   int scope;
965   if (ss->ss_family == PF_INET6)
966     {
967       const struct sockaddr_in6 *in6 = (const struct sockaddr_in6 *) ss;
968
969       if (! IN6_IS_ADDR_MULTICAST (&in6->sin6_addr))
970         {
971           if (IN6_IS_ADDR_LINKLOCAL (&in6->sin6_addr))
972             scope = 2;
973           else if (IN6_IS_ADDR_SITELOCAL (&in6->sin6_addr))
974             scope = 5;
975           else
976             /* XXX Is this the correct default behavior?  */
977             scope = 14;
978         }
979       else
980         scope = in6->sin6_addr.s6_addr[1] & 0xf;
981     }
982   else if (ss->ss_family == PF_INET)
983     {
984       const struct sockaddr_in *in = (const struct sockaddr_in *) ss;
985       const uint8_t *addr = (const uint8_t *) &in->sin_addr;
986
987       /* RFC 3484 specifies how to map IPv6 addresses to scopes.
988          169.254/16 and 127/8 are link-local.  */
989       if ((addr[0] == 169 && addr[1] == 254) || addr[0] == 127)
990         scope = 2;
991       else if (addr[0] == 10 || (addr[0] == 172 && addr[1] == 16)
992                || (addr[0] == 192 && addr[1] == 168))
993         scope = 5;
994       else
995         scope = 14;
996     }
997   else
998     /* XXX What is a good default?  */
999     scope = 15;
1000
1001   return scope;
1002 }
1003
1004
1005 /* XXX The system administrator should be able to install other
1006    tables.  We need to make this configurable.  The problem is that
1007    the kernel is also involved since it needs the same table.  */
1008 static const struct prefixlist
1009 {
1010   struct in6_addr prefix;
1011   unsigned int bits;
1012   int val;
1013 } default_labels[] =
1014   {
1015     /* See RFC 3484 for the details.  */
1016     { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1017                                   0x0000, 0x0000, 0x0000, 0x0001 } } },
1018       128, 0 },
1019     { { .in6_u = { .u6_addr16 = { 0x2002, 0x0000, 0x0000, 0x0000,
1020                                   0x0000, 0x0000, 0x0000, 0x0000 } } },
1021       16, 2 },
1022     { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1023                                   0x0000, 0x0000, 0x0000, 0x0000 } } },
1024       96, 3 },
1025     { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1026                                   0x0000, 0xffff, 0x0000, 0x0000 } } },
1027       96, 4 },
1028     { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1029                                   0x0000, 0x0000, 0x0000, 0x0000 } } },
1030       0, 1 }
1031   };
1032
1033
1034 static const struct prefixlist default_precedence[] =
1035   {
1036     /* See RFC 3484 for the details.  */
1037     { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1038                                   0x0000, 0x0000, 0x0000, 0x0001 } } },
1039       128, 50 },
1040     { { .in6_u = { .u6_addr16 = { 0x2002, 0x0000, 0x0000, 0x0000,
1041                                   0x0000, 0x0000, 0x0000, 0x0000 } } },
1042       16, 30 },
1043     { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1044                                   0x0000, 0x0000, 0x0000, 0x0000 } } },
1045       96, 20 },
1046     { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1047                                   0x0000, 0xffff, 0x0000, 0x0000 } } },
1048       96, 10 },
1049     { { .in6_u = { .u6_addr16 = { 0x0000, 0x0000, 0x0000, 0x0000,
1050                                   0x0000, 0x0000, 0x0000, 0x0000 } } },
1051       0, 40 }
1052   };
1053
1054
1055 static int
1056 match_prefix (const struct sockaddr_storage *ss, const struct prefixlist *list,
1057               int default_val)
1058 {
1059   int idx;
1060   struct sockaddr_in6 in6_mem;
1061   const struct sockaddr_in6 *in6;
1062
1063   if (ss->ss_family == PF_INET6)
1064     in6 = (const struct sockaddr_in6 *) ss;
1065   else if (ss->ss_family == PF_INET)
1066     {
1067       const struct sockaddr_in *in = (const struct sockaddr_in *) ss;
1068
1069       /* Convert to IPv6 address.  */
1070       in6_mem.sin6_family = PF_INET6;
1071       in6_mem.sin6_port = in->sin_port;
1072       in6_mem.sin6_flowinfo = 0;
1073       if (in->sin_addr.s_addr == htonl (0x7f000001))
1074         in6_mem.sin6_addr = (struct in6_addr) IN6ADDR_LOOPBACK_INIT;
1075       else
1076         {
1077           /* Construct a V4-to-6 mapped address.  */
1078           memset (&in6_mem.sin6_addr, '\0', sizeof (in6_mem.sin6_addr));
1079           in6_mem.sin6_addr.s6_addr16[5] = 0xffff;
1080           in6_mem.sin6_addr.s6_addr32[3] = in->sin_addr.s_addr;
1081           in6_mem.sin6_scope_id = 0;
1082         }
1083
1084       in6 = &in6_mem;
1085     }
1086   else
1087     return default_val;
1088
1089   for (idx = 0; ; ++idx)
1090     {
1091       unsigned int bits = list[idx].bits;
1092       uint8_t *mask = list[idx].prefix.s6_addr;
1093       uint8_t *val = in6->sin6_addr.s6_addr;
1094
1095       while (bits > 8)
1096         {
1097           if (*mask != *val)
1098             break;
1099
1100           ++mask;
1101           ++val;
1102           bits -= 8;
1103         }
1104
1105       if (bits < 8)
1106         {
1107           if ((*mask & (0xff00 >> bits)) == (*val & (0xff00 >> bits)))
1108             /* Match!  */
1109             break;
1110         }
1111     }
1112
1113   return list[idx].val;
1114 }
1115
1116
1117 static int
1118 get_label (const struct sockaddr_storage *ss)
1119 {
1120   /* XXX What is a good default value?  */
1121   return match_prefix (ss, default_labels, INT_MAX);
1122 }
1123
1124
1125 static int
1126 get_precedence (const struct sockaddr_storage *ss)
1127 {
1128   /* XXX What is a good default value?  */
1129   return match_prefix (ss, default_precedence, 0);
1130 }
1131
1132
1133 static int
1134 rfc3484_sort (const void *p1, const void *p2)
1135 {
1136   const struct sort_result *a1 = (const struct sort_result *) p1;
1137   const struct sort_result *a2 = (const struct sort_result *) p2;
1138
1139   /* Rule 1: Avoid unusable destinations.
1140      We have the got_source_addr flag set if the destination is reachable.  */
1141   if (a1->got_source_addr && ! a2->got_source_addr)
1142     return -1;
1143   if (! a1->got_source_addr && a2->got_source_addr)
1144     return 1;
1145
1146
1147   /* Rule 2: Prefer matching scope.  Only interesting if both
1148      destination addresses are IPv6.  */
1149   int a1_dst_scope
1150     = get_scope ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
1151
1152   int a2_dst_scope
1153     = get_scope ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
1154
1155   if (a1->got_source_addr)
1156     {
1157       int a1_src_scope = get_scope (&a1->source_addr);
1158       int a2_src_scope = get_scope (&a2->source_addr);
1159
1160       if (a1_dst_scope == a1_src_scope && a2_dst_scope != a2_src_scope)
1161         return -1;
1162       if (a1_dst_scope != a1_src_scope && a2_dst_scope == a2_src_scope)
1163         return 1;
1164     }
1165
1166
1167   /* Rule 3: Avoid deprecated addresses.
1168      That's something only the kernel could decide.  */
1169
1170   /* Rule 4: Prefer home addresses.
1171      Another thing only the kernel can decide.  */
1172
1173   /* Rule 5: Prefer matching label.  */
1174   if (a1->got_source_addr)
1175     {
1176       int a1_dst_label
1177         = get_label ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
1178       int a1_src_label = get_label (&a1->source_addr);
1179
1180       int a2_dst_label
1181         = get_label ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
1182       int a2_src_label = get_label (&a2->source_addr);
1183
1184       if (a1_dst_label == a1_src_label && a2_dst_label != a2_src_label)
1185         return -1;
1186       if (a1_dst_label != a1_src_label && a2_dst_label == a2_src_label)
1187         return 1;
1188     }
1189
1190
1191   /* Rule 6: Prefer higher precedence.  */
1192   int a1_prec
1193     = get_precedence ((struct sockaddr_storage *) a1->dest_addr->ai_addr);
1194   int a2_prec
1195     = get_precedence ((struct sockaddr_storage *) a2->dest_addr->ai_addr);
1196
1197   if (a1_prec > a2_prec)
1198     return -1;
1199   if (a1_prec < a2_prec)
1200     return 1;
1201
1202
1203   /* Rule 7: Prefer native transport.
1204      XXX How to recognize tunnels?  */
1205
1206
1207   /* Rule 8: Prefer smaller scope.  */
1208   if (a1_dst_scope < a2_dst_scope)
1209     return -1;
1210   if (a1_dst_scope > a2_dst_scope)
1211     return 1;
1212
1213
1214   /* Rule 9: Use longest matching prefix.  */
1215   if (a1->got_source_addr
1216       && a1->dest_addr->ai_family == a2->dest_addr->ai_family)
1217     {
1218       int bit1 = 0;
1219       int bit2 = 0;
1220
1221       if (a1->dest_addr->ai_family == PF_INET)
1222         {
1223           assert (a1->source_addr.ss_family == PF_INET);
1224           assert (a2->source_addr.ss_family == PF_INET);
1225
1226           struct sockaddr_in *in1_dst;
1227           struct sockaddr_in *in1_src;
1228           struct sockaddr_in *in2_dst;
1229           struct sockaddr_in *in2_src;
1230
1231           in1_dst = (struct sockaddr_in *) a1->dest_addr->ai_addr;
1232           in1_src = (struct sockaddr_in *) &a1->source_addr;
1233           in2_dst = (struct sockaddr_in *) a2->dest_addr->ai_addr;
1234           in2_src = (struct sockaddr_in *) &a2->source_addr;
1235
1236           bit1 = ffs (in1_dst->sin_addr.s_addr ^ in1_src->sin_addr.s_addr);
1237           bit2 = ffs (in2_dst->sin_addr.s_addr ^ in2_src->sin_addr.s_addr);
1238         }
1239       else if (a1->dest_addr->ai_family == PF_INET6)
1240         {
1241           assert (a1->source_addr.ss_family == PF_INET6);
1242           assert (a2->source_addr.ss_family == PF_INET6);
1243
1244           struct sockaddr_in6 *in1_dst;
1245           struct sockaddr_in6 *in1_src;
1246           struct sockaddr_in6 *in2_dst;
1247           struct sockaddr_in6 *in2_src;
1248
1249           in1_dst = (struct sockaddr_in6 *) a1->dest_addr->ai_addr;
1250           in1_src = (struct sockaddr_in6 *) &a1->source_addr;
1251           in2_dst = (struct sockaddr_in6 *) a2->dest_addr->ai_addr;
1252           in2_src = (struct sockaddr_in6 *) &a2->source_addr;
1253
1254           int i;
1255           for (i = 0; i < 4; ++i)
1256             if (in1_dst->sin6_addr.s6_addr32[i]
1257                 != in1_src->sin6_addr.s6_addr32[i]
1258                 || (in2_dst->sin6_addr.s6_addr32[i]
1259                     != in2_src->sin6_addr.s6_addr32[i]))
1260               break;
1261
1262           if (i < 4)
1263             {
1264               bit1 = ffs (in1_dst->sin6_addr.s6_addr32[i]
1265                           ^ in1_src->sin6_addr.s6_addr32[i]);
1266               bit2 = ffs (in2_dst->sin6_addr.s6_addr32[i]
1267                           ^ in2_src->sin6_addr.s6_addr32[i]);
1268             }
1269         }
1270
1271       if (bit1 > bit2)
1272         return -1;
1273       if (bit1 < bit2)
1274         return 1;
1275     }
1276
1277
1278   /* Rule 10: Otherwise, leave the order unchanged.  */
1279   return 0;
1280 }
1281
1282
1283 int
1284 getaddrinfo (const char *name, const char *service,
1285              const struct addrinfo *hints, struct addrinfo **pai)
1286 {
1287   int i = 0, j = 0, last_i = 0;
1288   int nresults = 0;
1289   struct addrinfo *p = NULL, **end;
1290   struct gaih *g = gaih, *pg = NULL;
1291   struct gaih_service gaih_service, *pservice;
1292   struct addrinfo local_hints;
1293
1294   if (name != NULL && name[0] == '*' && name[1] == 0)
1295     name = NULL;
1296
1297   if (service != NULL && service[0] == '*' && service[1] == 0)
1298     service = NULL;
1299
1300   if (name == NULL && service == NULL)
1301     return EAI_NONAME;
1302
1303   if (hints == NULL)
1304     hints = &default_hints;
1305
1306   if (hints->ai_flags
1307       & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|AI_ADDRCONFIG|AI_V4MAPPED
1308 #ifdef HAVE_LIBIDN
1309           |AI_IDN|AI_CANONIDN
1310 #endif
1311           |AI_ALL))
1312     return EAI_BADFLAGS;
1313
1314   if ((hints->ai_flags & AI_CANONNAME) && name == NULL)
1315     return EAI_BADFLAGS;
1316
1317   if (hints->ai_flags & AI_ADDRCONFIG)
1318     {
1319       /* Determine whether we have IPv4 or IPv6 interfaces or both.
1320          We cannot cache the results since new interfaces could be
1321          added at any time.  */
1322       bool seen_ipv4;
1323       bool seen_ipv6;
1324       __check_pf (&seen_ipv4, &seen_ipv6);
1325
1326       /* Now make a decision on what we return, if anything.  */
1327       if (hints->ai_family == PF_UNSPEC)
1328         {
1329           /* If we haven't seen both IPv4 and IPv6 interfaces we can
1330              narrow down the search.  */
1331           if (! seen_ipv4 || ! seen_ipv6)
1332             {
1333               local_hints = *hints;
1334               local_hints.ai_family = seen_ipv4 ? PF_INET : PF_INET6;
1335               hints = &local_hints;
1336             }
1337         }
1338       else if ((hints->ai_family == PF_INET && ! seen_ipv4)
1339                || (hints->ai_family == PF_INET6 && ! seen_ipv6))
1340         /* We cannot possibly return a valid answer.  */
1341         return EAI_NONAME;
1342     }
1343
1344   if (service && service[0])
1345     {
1346       char *c;
1347       gaih_service.name = service;
1348       gaih_service.num = strtoul (gaih_service.name, &c, 10);
1349       if (*c)
1350         gaih_service.num = -1;
1351       else
1352         /* Can't specify a numerical socket unless a protocol family was
1353            given. */
1354         if (hints->ai_socktype == 0 && hints->ai_protocol == 0)
1355           return EAI_SERVICE;
1356       pservice = &gaih_service;
1357     }
1358   else
1359     pservice = NULL;
1360
1361   if (pai)
1362     end = &p;
1363   else
1364     end = NULL;
1365
1366   while (g->gaih)
1367     {
1368       if (hints->ai_family == g->family || hints->ai_family == AF_UNSPEC)
1369         {
1370           j++;
1371           if (pg == NULL || pg->gaih != g->gaih)
1372             {
1373               pg = g;
1374               i = g->gaih (name, pservice, hints, end);
1375               if (i != 0)
1376                 {
1377                   /* EAI_NODATA is a more specific result as it says that
1378                      we found a result but it is not usable.  */
1379                   if (last_i != (GAIH_OKIFUNSPEC | -EAI_NODATA))
1380                     last_i = i;
1381
1382                   if (hints->ai_family == AF_UNSPEC && (i & GAIH_OKIFUNSPEC))
1383                     {
1384                       ++g;
1385                       continue;
1386                     }
1387
1388                   freeaddrinfo (p);
1389
1390                   return -(i & GAIH_EAI);
1391                 }
1392               if (end)
1393                 while (*end)
1394                   {
1395                     end = &((*end)->ai_next);
1396                     ++nresults;
1397                   }
1398             }
1399         }
1400       ++g;
1401     }
1402
1403   if (j == 0)
1404     return EAI_FAMILY;
1405
1406   if (nresults > 1)
1407     {
1408       /* Sort results according to RFC 3484.  */
1409       struct sort_result results[nresults];
1410       struct addrinfo *q;
1411
1412       for (i = 0, q = p; q != NULL; ++i, q = q->ai_next)
1413         {
1414           results[i].dest_addr = q;
1415           results[i].got_source_addr = false;
1416
1417           /* We overwrite the type with SOCK_DGRAM since we do not
1418              want connect() to connect to the other side.  If we
1419              cannot determine the source address remember this
1420              fact.  */
1421           int fd = __socket (q->ai_family, SOCK_DGRAM, IPPROTO_IP);
1422           if (fd != -1)
1423             {
1424               socklen_t sl = sizeof (results[i].source_addr);
1425               if (__connect (fd, q->ai_addr, q->ai_addrlen) == 0
1426                   && __getsockname (fd,
1427                                     (struct sockaddr *) &results[i].source_addr,
1428                                     &sl) == 0)
1429                 results[i].got_source_addr = true;
1430
1431               close_not_cancel_no_status (fd);
1432             }
1433         }
1434
1435       /* We got all the source addresses we can get, now sort using
1436          the information.  */
1437       qsort (results, nresults, sizeof (results[0]), rfc3484_sort);
1438
1439       /* Queue the results up as they come out of sorting.  */
1440       q = p = results[0].dest_addr;
1441       for (i = 1; i < nresults; ++i)
1442         q = q->ai_next = results[i].dest_addr;
1443       q->ai_next = NULL;
1444     }
1445
1446   if (p)
1447     {
1448       *pai = p;
1449       return 0;
1450     }
1451
1452   if (pai == NULL && last_i == 0)
1453     return 0;
1454
1455   freeaddrinfo (p);
1456
1457   return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;
1458 }
1459 libc_hidden_def (getaddrinfo)
1460
1461 static_link_warning (getaddrinfo)
1462
1463 void
1464 freeaddrinfo (struct addrinfo *ai)
1465 {
1466   struct addrinfo *p;
1467
1468   while (ai != NULL)
1469     {
1470       p = ai;
1471       ai = ai->ai_next;
1472       free (p);
1473     }
1474 }
1475 libc_hidden_def (freeaddrinfo)