Back to index

glibc  2.9
getaddrinfo.c
Go to the documentation of this file.
00001 /* The Inner Net License, Version 2.00
00002 
00003   The author(s) grant permission for redistribution and use in source and
00004 binary forms, with or without modification, of the software and documentation
00005 provided that the following conditions are met:
00006 
00007 0. If you receive a version of the software that is specifically labelled
00008    as not being for redistribution (check the version message and/or README),
00009    you are not permitted to redistribute that version of the software in any
00010    way or form.
00011 1. All terms of the all other applicable copyrights and licenses must be
00012    followed.
00013 2. Redistributions of source code must retain the authors' copyright
00014    notice(s), this list of conditions, and the following disclaimer.
00015 3. Redistributions in binary form must reproduce the authors' copyright
00016    notice(s), this list of conditions, and the following disclaimer in the
00017    documentation and/or other materials provided with the distribution.
00018 4. [The copyright holder has authorized the removal of this clause.]
00019 5. Neither the name(s) of the author(s) nor the names of its contributors
00020    may be used to endorse or promote products derived from this software
00021    without specific prior written permission.
00022 
00023 THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS ``AS IS'' AND ANY
00024 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00025 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00026 DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
00027 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00028 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00030 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00031 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00032 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 
00034   If these license terms cause you a real problem, contact the author.  */
00035 
00036 /* This software is Copyright 1996 by Craig Metz, All Rights Reserved.  */
00037 
00038 #include <assert.h>
00039 #include <ctype.h>
00040 #include <errno.h>
00041 #include <ifaddrs.h>
00042 #include <netdb.h>
00043 #include <nss.h>
00044 #include <resolv.h>
00045 #include <stdbool.h>
00046 #include <stdio.h>
00047 #include <stdio_ext.h>
00048 #include <stdlib.h>
00049 #include <string.h>
00050 #include <arpa/inet.h>
00051 #include <net/if.h>
00052 #include <netinet/in.h>
00053 #include <sys/socket.h>
00054 #include <sys/stat.h>
00055 #include <sys/types.h>
00056 #include <sys/un.h>
00057 #include <sys/utsname.h>
00058 #include <unistd.h>
00059 #include <nsswitch.h>
00060 #include <bits/libc-lock.h>
00061 #include <not-cancel.h>
00062 #include <nscd/nscd-client.h>
00063 #include <nscd/nscd_proto.h>
00064 #include <resolv/res_hconf.h>
00065 
00066 #ifdef HAVE_LIBIDN
00067 extern int __idna_to_ascii_lz (const char *input, char **output, int flags);
00068 extern int __idna_to_unicode_lzlz (const char *input, char **output,
00069                                int flags);
00070 # include <libidn/idna.h>
00071 #endif
00072 
00073 #define GAIH_OKIFUNSPEC 0x0100
00074 #define GAIH_EAI        ~(GAIH_OKIFUNSPEC)
00075 
00076 #ifndef UNIX_PATH_MAX
00077 # define UNIX_PATH_MAX  108
00078 #endif
00079 
00080 struct gaih_service
00081   {
00082     const char *name;
00083     int num;
00084   };
00085 
00086 struct gaih_servtuple
00087   {
00088     struct gaih_servtuple *next;
00089     int socktype;
00090     int protocol;
00091     int port;
00092   };
00093 
00094 static const struct gaih_servtuple nullserv;
00095 
00096 
00097 struct gaih_typeproto
00098   {
00099     int socktype;
00100     int protocol;
00101     uint8_t protoflag;
00102     bool defaultflag;
00103     char name[8];
00104   };
00105 
00106 /* Values for `protoflag'.  */
00107 #define GAI_PROTO_NOSERVICE 1
00108 #define GAI_PROTO_PROTOANY  2
00109 
00110 static const struct gaih_typeproto gaih_inet_typeproto[] =
00111 {
00112   { 0, 0, 0, false, "" },
00113   { SOCK_STREAM, IPPROTO_TCP, 0, true, "tcp" },
00114   { SOCK_DGRAM, IPPROTO_UDP, 0, true, "udp" },
00115 #if defined SOCK_DCCP && defined IPPROTO_DCCP
00116   { SOCK_DCCP, IPPROTO_DCCP, 0, false, "dccp" },
00117 #endif
00118 #ifdef IPPROTO_UDPLITE
00119   { SOCK_DGRAM, IPPROTO_UDPLITE, 0, false, "udplite" },
00120 #endif
00121 #ifdef IPPROTO_SCTP
00122   { SOCK_STREAM, IPPROTO_SCTP, 0, false, "sctp" },
00123   { SOCK_SEQPACKET, IPPROTO_SCTP, 0, false, "sctp" },
00124 #endif
00125   { SOCK_RAW, 0, GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE, true, "raw" },
00126   { 0, 0, 0, false, "" }
00127 };
00128 
00129 struct gaih
00130   {
00131     int family;
00132     int (*gaih)(const char *name, const struct gaih_service *service,
00133               const struct addrinfo *req, struct addrinfo **pai,
00134               unsigned int *naddrs);
00135   };
00136 
00137 static const struct addrinfo default_hints =
00138   {
00139     .ai_flags = AI_DEFAULT,
00140     .ai_family = PF_UNSPEC,
00141     .ai_socktype = 0,
00142     .ai_protocol = 0,
00143     .ai_addrlen = 0,
00144     .ai_addr = NULL,
00145     .ai_canonname = NULL,
00146     .ai_next = NULL
00147   };
00148 
00149 
00150 static int
00151 gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
00152               const struct addrinfo *req, struct gaih_servtuple *st)
00153 {
00154   struct servent *s;
00155   size_t tmpbuflen = 1024;
00156   struct servent ts;
00157   char *tmpbuf;
00158   int r;
00159 
00160   do
00161     {
00162       tmpbuf = __alloca (tmpbuflen);
00163 
00164       r = __getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen,
00165                           &s);
00166       if (r != 0 || s == NULL)
00167        {
00168          if (r == ERANGE)
00169            tmpbuflen *= 2;
00170          else
00171            return GAIH_OKIFUNSPEC | -EAI_SERVICE;
00172        }
00173     }
00174   while (r);
00175 
00176   st->next = NULL;
00177   st->socktype = tp->socktype;
00178   st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
00179                 ? req->ai_protocol : tp->protocol);
00180   st->port = s->s_port;
00181 
00182   return 0;
00183 }
00184 
00185 #define gethosts(_family, _type) \
00186  {                                                                   \
00187   int i;                                                             \
00188   int herrno;                                                        \
00189   struct hostent th;                                                 \
00190   struct hostent *h;                                                 \
00191   char *localcanon = NULL;                                           \
00192   no_data = 0;                                                              \
00193   while (1) {                                                        \
00194     rc = 0;                                                          \
00195     status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen,             \
00196                             &rc, &herrno, NULL, &localcanon));       \
00197     if (rc != ERANGE || herrno != NETDB_INTERNAL)                           \
00198       break;                                                         \
00199     tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);              \
00200   }                                                                  \
00201   if (status == NSS_STATUS_SUCCESS && rc == 0)                              \
00202     h = &th;                                                         \
00203   else                                                               \
00204     h = NULL;                                                        \
00205   if (rc != 0)                                                              \
00206     {                                                                \
00207       if (herrno == NETDB_INTERNAL)                                         \
00208        {                                                             \
00209          __set_h_errno (herrno);                                     \
00210          _res.options = old_res_options;                             \
00211          return -EAI_SYSTEM;                                                \
00212        }                                                             \
00213       if (herrno == TRY_AGAIN)                                              \
00214        no_data = EAI_AGAIN;                                          \
00215       else                                                           \
00216        no_data = herrno == NO_DATA;                                         \
00217     }                                                                \
00218   else if (h != NULL)                                                       \
00219     {                                                                \
00220       for (i = 0; h->h_addr_list[i]; i++)                            \
00221        {                                                             \
00222          if (*pat == NULL)                                           \
00223            {                                                         \
00224              *pat = __alloca (sizeof (struct gaih_addrtuple));              \
00225              (*pat)->scopeid = 0;                                    \
00226            }                                                         \
00227          uint32_t *addr = (*pat)->addr;                              \
00228          (*pat)->next = NULL;                                               \
00229          (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL;                \
00230          if (_family == AF_INET && req->ai_family == AF_INET6)              \
00231            {                                                         \
00232              (*pat)->family = AF_INET6;                              \
00233              addr[3] = *(uint32_t *) h->h_addr_list[i];              \
00234              addr[2] = htonl (0xffff);                                      \
00235              addr[1] = 0;                                            \
00236              addr[0] = 0;                                            \
00237            }                                                         \
00238          else                                                        \
00239            {                                                         \
00240              (*pat)->family = _family;                                      \
00241              memcpy (addr, h->h_addr_list[i], sizeof(_type));               \
00242            }                                                         \
00243          pat = &((*pat)->next);                                      \
00244        }                                                             \
00245                                                                      \
00246       if (localcanon !=     NULL && canon == NULL)                                 \
00247        canon = strdupa (localcanon);                                        \
00248                                                                      \
00249       if (_family == AF_INET6 && i > 0)                                     \
00250        got_ipv6 = true;                                              \
00251     }                                                                \
00252  }
00253 
00254 
00255 typedef enum nss_status (*nss_gethostbyname4_r)
00256   (const char *name, struct gaih_addrtuple **pat,
00257    char *buffer, size_t buflen, int *errnop,
00258    int *h_errnop, int32_t *ttlp);
00259 typedef enum nss_status (*nss_gethostbyname3_r)
00260   (const char *name, int af, struct hostent *host,
00261    char *buffer, size_t buflen, int *errnop,
00262    int *h_errnop, int32_t *ttlp, char **canonp);
00263 typedef enum nss_status (*nss_getcanonname_r)
00264   (const char *name, char *buffer, size_t buflen, char **result,
00265    int *errnop, int *h_errnop);
00266 extern service_user *__nss_hosts_database attribute_hidden;
00267 
00268 
00269 static int
00270 gaih_inet (const char *name, const struct gaih_service *service,
00271           const struct addrinfo *req, struct addrinfo **pai,
00272           unsigned int *naddrs)
00273 {
00274   const struct gaih_typeproto *tp = gaih_inet_typeproto;
00275   struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv;
00276   struct gaih_addrtuple *at = NULL;
00277   int rc;
00278   bool got_ipv6 = false;
00279   const char *canon = NULL;
00280   const char *orig_name = name;
00281 
00282   if (req->ai_protocol || req->ai_socktype)
00283     {
00284       ++tp;
00285 
00286       while (tp->name[0]
00287             && ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
00288                || (req->ai_protocol != 0
00289                    && !(tp->protoflag & GAI_PROTO_PROTOANY)
00290                    && req->ai_protocol != tp->protocol)))
00291        ++tp;
00292 
00293       if (! tp->name[0])
00294        {
00295          if (req->ai_socktype)
00296            return GAIH_OKIFUNSPEC | -EAI_SOCKTYPE;
00297          else
00298            return GAIH_OKIFUNSPEC | -EAI_SERVICE;
00299        }
00300     }
00301 
00302   int port = 0;
00303   if (service != NULL)
00304     {
00305       if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
00306        return GAIH_OKIFUNSPEC | -EAI_SERVICE;
00307 
00308       if (service->num < 0)
00309        {
00310          if (tp->name[0])
00311            {
00312              st = (struct gaih_servtuple *)
00313               __alloca (sizeof (struct gaih_servtuple));
00314 
00315              if ((rc = gaih_inet_serv (service->name, tp, req, st)))
00316               return rc;
00317            }
00318          else
00319            {
00320              struct gaih_servtuple **pst = &st;
00321              for (tp++; tp->name[0]; tp++)
00322               {
00323                 struct gaih_servtuple *newp;
00324 
00325                 if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
00326                   continue;
00327 
00328                 if (req->ai_socktype != 0
00329                     && req->ai_socktype != tp->socktype)
00330                   continue;
00331                 if (req->ai_protocol != 0
00332                     && !(tp->protoflag & GAI_PROTO_PROTOANY)
00333                     && req->ai_protocol != tp->protocol)
00334                   continue;
00335 
00336                 newp = (struct gaih_servtuple *)
00337                   __alloca (sizeof (struct gaih_servtuple));
00338 
00339                 if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
00340                   {
00341                     if (rc & GAIH_OKIFUNSPEC)
00342                      continue;
00343                     return rc;
00344                   }
00345 
00346                 *pst = newp;
00347                 pst = &(newp->next);
00348               }
00349              if (st == (struct gaih_servtuple *) &nullserv)
00350               return GAIH_OKIFUNSPEC | -EAI_SERVICE;
00351            }
00352        }
00353       else
00354        {
00355          port = htons (service->num);
00356          goto got_port;
00357        }
00358     }
00359   else
00360     {
00361     got_port:
00362 
00363       if (req->ai_socktype || req->ai_protocol)
00364        {
00365          st = __alloca (sizeof (struct gaih_servtuple));
00366          st->next = NULL;
00367          st->socktype = tp->socktype;
00368          st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
00369                        ? req->ai_protocol : tp->protocol);
00370          st->port = port;
00371        }
00372       else
00373        {
00374          /* Neither socket type nor protocol is set.  Return all socket types
00375             we know about.  */
00376          struct gaih_servtuple **lastp = &st;
00377          for (++tp; tp->name[0]; ++tp)
00378            if (tp->defaultflag)
00379              {
00380               struct gaih_servtuple *newp;
00381 
00382               newp = __alloca (sizeof (struct gaih_servtuple));
00383               newp->next = NULL;
00384               newp->socktype = tp->socktype;
00385               newp->protocol = tp->protocol;
00386               newp->port = port;
00387 
00388               *lastp = newp;
00389               lastp = &newp->next;
00390              }
00391        }
00392     }
00393 
00394   if (name != NULL)
00395     {
00396       at = __alloca (sizeof (struct gaih_addrtuple));
00397 
00398       at->family = AF_UNSPEC;
00399       at->scopeid = 0;
00400       at->next = NULL;
00401 
00402 #ifdef HAVE_LIBIDN
00403       if (req->ai_flags & AI_IDN)
00404        {
00405          int idn_flags = 0;
00406          if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
00407            idn_flags |= IDNA_ALLOW_UNASSIGNED;
00408          if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
00409            idn_flags |= IDNA_USE_STD3_ASCII_RULES;
00410 
00411          char *p = NULL;
00412          rc = __idna_to_ascii_lz (name, &p, idn_flags);
00413          if (rc != IDNA_SUCCESS)
00414            {
00415              if (rc == IDNA_MALLOC_ERROR)
00416               return -EAI_MEMORY;
00417              if (rc == IDNA_DLOPEN_ERROR)
00418               return -EAI_SYSTEM;
00419              return -EAI_IDN_ENCODE;
00420            }
00421          /* In case the output string is the same as the input string
00422             no new string has been allocated.  */
00423          if (p != name)
00424            {
00425              name = strdupa (p);
00426              free (p);
00427            }
00428        }
00429 #endif
00430 
00431       if (__inet_aton (name, (struct in_addr *) at->addr) != 0)
00432        {
00433          if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
00434            at->family = AF_INET;
00435          else if (req->ai_family == AF_INET6 && (req->ai_flags & AI_V4MAPPED))
00436            {
00437              at->addr[3] = at->addr[0];
00438              at->addr[2] = htonl (0xffff);
00439              at->addr[1] = 0;
00440              at->addr[0] = 0;
00441              at->family = AF_INET6;
00442            }
00443          else
00444            return -EAI_ADDRFAMILY;
00445 
00446          if (req->ai_flags & AI_CANONNAME)
00447            canon = name;
00448        }
00449       else if (at->family == AF_UNSPEC)
00450        {
00451          char *namebuf = (char *) name;
00452          char *scope_delim = strchr (name, SCOPE_DELIMITER);
00453 
00454          if (__builtin_expect (scope_delim != NULL, 0))
00455            {
00456              namebuf = alloca (scope_delim - name + 1);
00457              *((char *) __mempcpy (namebuf, name, scope_delim - name)) = '\0';
00458            }
00459 
00460          if (inet_pton (AF_INET6, namebuf, at->addr) > 0)
00461            {
00462              if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
00463               at->family = AF_INET6;
00464              else if (req->ai_family == AF_INET
00465                      && IN6_IS_ADDR_V4MAPPED (at->addr))
00466               {
00467                 at->addr[0] = at->addr[3];
00468                 at->family = AF_INET;
00469               }
00470              else
00471               return -EAI_ADDRFAMILY;
00472 
00473              if (scope_delim != NULL)
00474               {
00475                 int try_numericscope = 0;
00476                 if (IN6_IS_ADDR_LINKLOCAL (at->addr)
00477                     || IN6_IS_ADDR_MC_LINKLOCAL (at->addr))
00478                   {
00479                     at->scopeid = if_nametoindex (scope_delim + 1);
00480                     if (at->scopeid == 0)
00481                      try_numericscope = 1;
00482                   }
00483                 else
00484                   try_numericscope = 1;
00485 
00486                 if (try_numericscope != 0)
00487                   {
00488                     char *end;
00489                     assert (sizeof (uint32_t) <= sizeof (unsigned long));
00490                     at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
00491                                                  10);
00492                     if (*end != '\0')
00493                      return GAIH_OKIFUNSPEC | -EAI_NONAME;
00494                   }
00495               }
00496 
00497              if (req->ai_flags & AI_CANONNAME)
00498               canon = name;
00499            }
00500        }
00501 
00502       if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0)
00503        {
00504          struct gaih_addrtuple **pat = &at;
00505          int no_data = 0;
00506          int no_inet6_data = 0;
00507          service_user *nip = NULL;
00508          enum nss_status inet6_status = NSS_STATUS_UNAVAIL;
00509          enum nss_status status = NSS_STATUS_UNAVAIL;
00510          int no_more;
00511          int old_res_options;
00512 
00513          /* If we do not have to look for IPv4 and IPv6 together, use
00514             the simple, old functions.  */
00515          if (req->ai_family == AF_INET
00516              || (req->ai_family == AF_INET6
00517                 && ((req->ai_flags & AI_V4MAPPED) == 0
00518                     || (req->ai_flags & AI_ALL) == 0)))
00519            {
00520              int family = req->ai_family;
00521              size_t tmpbuflen = 512;
00522              char *tmpbuf = alloca (tmpbuflen);
00523              int rc;
00524              struct hostent th;
00525              struct hostent *h;
00526              int herrno;
00527 
00528            simple_again:
00529              while (1)
00530               {
00531                 rc = __gethostbyname2_r (name, family, &th, tmpbuf,
00532                                       tmpbuflen, &h, &herrno);
00533                 if (rc != ERANGE || herrno != NETDB_INTERNAL)
00534                   break;
00535                 tmpbuf = extend_alloca (tmpbuf, tmpbuflen, 2 * tmpbuflen);
00536               }
00537 
00538              if (rc == 0)
00539               {
00540                 if (h == NULL)
00541                   {
00542                     if (req->ai_family == AF_INET6
00543                        && (req->ai_flags & AI_V4MAPPED)
00544                        && family == AF_INET6)
00545                      {
00546                        /* Try again, this time looking for IPv4
00547                           addresses.  */
00548                        family = AF_INET;
00549                        goto simple_again;
00550                      }
00551                   }
00552                 else
00553                   {
00554                     /* We found data, now convert it into the list.  */
00555                     for (int i = 0; h->h_addr_list[i]; ++i)
00556                      {
00557                        if (*pat == NULL)
00558                          {
00559                            *pat = __alloca (sizeof (struct gaih_addrtuple));
00560                            (*pat)->scopeid = 0;
00561                          }
00562                        (*pat)->next = NULL;
00563                        (*pat)->family = req->ai_family;
00564                        if (family == req->ai_family)
00565                          memcpy ((*pat)->addr, h->h_addr_list[i],
00566                                 h->h_length);
00567                        else
00568                          {
00569                            uint32_t *addr = (uint32_t *) (*pat)->addr;
00570                            addr[3] = *(uint32_t *) h->h_addr_list[i];
00571                            addr[2] = htonl (0xffff);
00572                            addr[1] = 0;
00573                            addr[0] = 0;
00574                          }
00575                        pat = &((*pat)->next);
00576                      }
00577                   }
00578               }
00579              else
00580               {
00581                 if (herrno == NETDB_INTERNAL)
00582                   {
00583                     __set_h_errno (herrno);
00584                     return -EAI_SYSTEM;
00585                   }
00586                 if (herrno == TRY_AGAIN)
00587                   {
00588                     return -EAI_AGAIN;
00589                   }
00590                 /* We made requests but they turned out no data.
00591                    The name is known, though.  */
00592                 return GAIH_OKIFUNSPEC | -EAI_NODATA;
00593               }
00594 
00595              goto process_list;
00596            }
00597 
00598 #ifdef USE_NSCD
00599          if (__nss_not_use_nscd_hosts > 0
00600              && ++__nss_not_use_nscd_hosts > NSS_NSCD_RETRY)
00601            __nss_not_use_nscd_hosts = 0;
00602 
00603          if (!__nss_not_use_nscd_hosts)
00604            {
00605              /* Try to use nscd.  */
00606              struct nscd_ai_result *air = NULL;
00607              int herrno;
00608              int err = __nscd_getai (name, &air, &herrno);
00609              if (air != NULL)
00610               {
00611                 /* Transform into gaih_addrtuple list.  */
00612                 bool added_canon = (req->ai_flags & AI_CANONNAME) == 0;
00613                 char *addrs = air->addrs;
00614 
00615                 for (int i = 0; i < air->naddrs; ++i)
00616                   {
00617                     socklen_t size = (air->family[i] == AF_INET
00618                                    ? INADDRSZ : IN6ADDRSZ);
00619                     if (*pat == NULL)
00620                      {
00621                        *pat = __alloca (sizeof (struct gaih_addrtuple));
00622                        (*pat)->scopeid = 0;
00623                      }
00624                     uint32_t *pataddr = (*pat)->addr;
00625                     (*pat)->next = NULL;
00626                     if (added_canon || air->canon == NULL)
00627                      (*pat)->name = NULL;
00628                     else
00629                      canon = (*pat)->name = strdupa (air->canon);
00630 
00631                     if (air->family[i] == AF_INET
00632                        && req->ai_family == AF_INET6
00633                        && (req->ai_flags & AI_V4MAPPED))
00634                      {
00635                        (*pat)->family = AF_INET6;
00636                        pataddr[3] = *(uint32_t *) addrs;
00637                        pataddr[2] = htonl (0xffff);
00638                        pataddr[1] = 0;
00639                        pataddr[0] = 0;
00640                        pat = &((*pat)->next);
00641                        added_canon = true;
00642                      }
00643                     else if (req->ai_family == AF_UNSPEC
00644                             || air->family[i] == req->ai_family)
00645                      {
00646                        (*pat)->family = air->family[i];
00647                        memcpy (pataddr, addrs, size);
00648                        pat = &((*pat)->next);
00649                        added_canon = true;
00650                        if (air->family[i] == AF_INET6)
00651                          got_ipv6 = true;
00652                      }
00653                     addrs += size;
00654                   }
00655 
00656                 free (air);
00657 
00658                 if (at->family == AF_UNSPEC)
00659                   return GAIH_OKIFUNSPEC | -EAI_NONAME;
00660 
00661                 goto process_list;
00662               }
00663              else if (err == 0)
00664               /* The database contains a negative entry.  */
00665               return 0;
00666              else if (__nss_not_use_nscd_hosts == 0)
00667               {
00668                 if (herrno == NETDB_INTERNAL && errno == ENOMEM)
00669                   return -EAI_MEMORY;
00670                 if (herrno == TRY_AGAIN)
00671                   return -EAI_AGAIN;
00672                 return -EAI_SYSTEM;
00673               }
00674            }
00675 #endif
00676 
00677          if (__nss_hosts_database != NULL)
00678            {
00679              no_more = 0;
00680              nip = __nss_hosts_database;
00681            }
00682          else
00683            no_more = __nss_database_lookup ("hosts", NULL,
00684                                         "dns [!UNAVAIL=return] files",
00685                                         &nip);
00686 
00687          /* Initialize configurations.  */
00688          if (__builtin_expect (!_res_hconf.initialized, 0))
00689            _res_hconf_init ();
00690          if (__res_maybe_init (&_res, 0) == -1)
00691            no_more = 1;
00692 
00693          /* If we are looking for both IPv4 and IPv6 address we don't
00694             want the lookup functions to automatically promote IPv4
00695             addresses to IPv6 addresses.  Currently this is decided
00696             by setting the RES_USE_INET6 bit in _res.options.  */
00697          old_res_options = _res.options;
00698          _res.options &= ~RES_USE_INET6;
00699 
00700          size_t tmpbuflen = 1024;
00701          char *tmpbuf = alloca (tmpbuflen);
00702 
00703          while (!no_more)
00704            {
00705              nss_gethostbyname4_r fct4
00706               = __nss_lookup_function (nip, "gethostbyname4_r");
00707              if (fct4 != NULL)
00708               {
00709                 int herrno;
00710 
00711                 while (1)
00712                   {
00713                     rc = 0;
00714                     status = DL_CALL_FCT (fct4, (name, pat, tmpbuf,
00715                                              tmpbuflen, &rc, &herrno,
00716                                              NULL));
00717                     if (status != NSS_STATUS_TRYAGAIN
00718                        || rc != ERANGE || herrno != NETDB_INTERNAL)
00719                      {
00720                        if (herrno == NETDB_INTERNAL)
00721                          {
00722                            __set_h_errno (herrno);
00723                            _res.options = old_res_options;
00724                            return -EAI_SYSTEM;
00725                          }
00726                        if (herrno == TRY_AGAIN)
00727                          no_data = EAI_AGAIN;
00728                        else
00729                          no_data = herrno == NO_DATA;
00730                        break;
00731                      }
00732                     tmpbuf = extend_alloca (tmpbuf,
00733                                          tmpbuflen, 2 * tmpbuflen);
00734                   }
00735 
00736                 if (status == NSS_STATUS_SUCCESS)
00737                   {
00738                     if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
00739                      canon = (*pat)->name;
00740 
00741                     while (*pat != NULL)
00742                      pat = &((*pat)->next);
00743                   }
00744               }
00745              else
00746               {
00747                 nss_gethostbyname3_r fct = NULL;
00748                 if (req->ai_flags & AI_CANONNAME)
00749                   /* No need to use this function if we do not look for
00750                      the canonical name.  The function does not exist in
00751                      all NSS modules and therefore the lookup would
00752                      often fail.  */
00753                   fct = __nss_lookup_function (nip, "gethostbyname3_r");
00754                 if (fct == NULL)
00755                   /* We are cheating here.  The gethostbyname2_r
00756                      function does not have the same interface as
00757                      gethostbyname3_r but the extra arguments the
00758                      latter takes are added at the end.  So the
00759                      gethostbyname2_r code will just ignore them.  */
00760                   fct = __nss_lookup_function (nip, "gethostbyname2_r");
00761 
00762                 if (fct != NULL)
00763                   {
00764                     if (req->ai_family == AF_INET6
00765                        || req->ai_family == AF_UNSPEC)
00766                      {
00767                        gethosts (AF_INET6, struct in6_addr);
00768                        no_inet6_data = no_data;
00769                        inet6_status = status;
00770                      }
00771                     if (req->ai_family == AF_INET
00772                        || req->ai_family == AF_UNSPEC
00773                        || (req->ai_family == AF_INET6
00774                            && (req->ai_flags & AI_V4MAPPED)
00775                            /* Avoid generating the mapped addresses if we
00776                              know we are not going to need them.  */
00777                            && ((req->ai_flags & AI_ALL) || !got_ipv6)))
00778                      {
00779                        gethosts (AF_INET, struct in_addr);
00780 
00781                        if (req->ai_family == AF_INET)
00782                          {
00783                            no_inet6_data = no_data;
00784                            inet6_status = status;
00785                          }
00786                      }
00787 
00788                     /* If we found one address for AF_INET or AF_INET6,
00789                       don't continue the search.  */
00790                     if (inet6_status == NSS_STATUS_SUCCESS
00791                        || status == NSS_STATUS_SUCCESS)
00792                      {
00793                        if ((req->ai_flags & AI_CANONNAME) != 0
00794                            && canon == NULL)
00795                          {
00796                            /* If we need the canonical name, get it
00797                              from the same service as the result.  */
00798                            nss_getcanonname_r cfct;
00799                            int herrno;
00800 
00801                            cfct = __nss_lookup_function (nip,
00802                                                      "getcanonname_r");
00803                            if (cfct != NULL)
00804                             {
00805                               const size_t max_fqdn_len = 256;
00806                               char *buf = alloca (max_fqdn_len);
00807                               char *s;
00808 
00809                               if (DL_CALL_FCT (cfct, (at->name ?: name,
00810                                                    buf, max_fqdn_len,
00811                                                    &s, &rc, &herrno))
00812                                   == NSS_STATUS_SUCCESS)
00813                                 canon = s;
00814                               else
00815                                 /* Set to name now to avoid using
00816                                    gethostbyaddr.  */
00817                                 canon = name;
00818                             }
00819                          }
00820 
00821                        break;
00822                      }
00823 
00824                     /* We can have different states for AF_INET and
00825                       AF_INET6.  Try to find a useful one for both.  */
00826                     if (inet6_status == NSS_STATUS_TRYAGAIN)
00827                      status = NSS_STATUS_TRYAGAIN;
00828                     else if (status == NSS_STATUS_UNAVAIL
00829                             && inet6_status != NSS_STATUS_UNAVAIL)
00830                      status = inet6_status;
00831                   }
00832               }
00833 
00834              if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
00835               break;
00836 
00837              if (nip->next == NULL)
00838               no_more = -1;
00839              else
00840               nip = nip->next;
00841            }
00842 
00843          _res.options = old_res_options;
00844 
00845          if (no_data != 0 && no_inet6_data != 0)
00846            {
00847              /* If both requests timed out report this.  */
00848              if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
00849               return -EAI_AGAIN;
00850 
00851              /* We made requests but they turned out no data.  The name
00852                is known, though.  */
00853              return GAIH_OKIFUNSPEC | -EAI_NODATA;
00854            }
00855        }
00856 
00857     process_list:
00858       if (at->family == AF_UNSPEC)
00859        return GAIH_OKIFUNSPEC | -EAI_NONAME;
00860     }
00861   else
00862     {
00863       struct gaih_addrtuple *atr;
00864       atr = at = __alloca (sizeof (struct gaih_addrtuple));
00865       memset (at, '\0', sizeof (struct gaih_addrtuple));
00866 
00867       if (req->ai_family == AF_UNSPEC)
00868        {
00869          at->next = __alloca (sizeof (struct gaih_addrtuple));
00870          memset (at->next, '\0', sizeof (struct gaih_addrtuple));
00871        }
00872 
00873       if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
00874        {
00875          at->family = AF_INET6;
00876          if ((req->ai_flags & AI_PASSIVE) == 0)
00877            memcpy (at->addr, &in6addr_loopback, sizeof (struct in6_addr));
00878          atr = at->next;
00879        }
00880 
00881       if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
00882        {
00883          atr->family = AF_INET;
00884          if ((req->ai_flags & AI_PASSIVE) == 0)
00885            atr->addr[0] = htonl (INADDR_LOOPBACK);
00886        }
00887     }
00888 
00889   {
00890     struct gaih_servtuple *st2;
00891     struct gaih_addrtuple *at2 = at;
00892     size_t socklen;
00893     sa_family_t family;
00894 
00895     /*
00896       buffer is the size of an unformatted IPv6 address in printable format.
00897      */
00898     while (at2 != NULL)
00899       {
00900        /* Only the first entry gets the canonical name.  */
00901        if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
00902          {
00903            if (canon == NULL)
00904              {
00905               struct hostent *h = NULL;
00906               int herrno;
00907               struct hostent th;
00908               size_t tmpbuflen = 512;
00909               char *tmpbuf = NULL;
00910 
00911               do
00912                 {
00913                   tmpbuf = extend_alloca (tmpbuf, tmpbuflen, tmpbuflen * 2);
00914                   rc = __gethostbyaddr_r (at2->addr,
00915                                        ((at2->family == AF_INET6)
00916                                         ? sizeof (struct in6_addr)
00917                                         : sizeof (struct in_addr)),
00918                                        at2->family, &th, tmpbuf,
00919                                        tmpbuflen, &h, &herrno);
00920                 }
00921               while (rc == ERANGE && herrno == NETDB_INTERNAL);
00922 
00923               if (rc != 0 && herrno == NETDB_INTERNAL)
00924                 {
00925                   __set_h_errno (herrno);
00926                   return -EAI_SYSTEM;
00927                 }
00928 
00929               if (h != NULL)
00930                 canon = h->h_name;
00931               else
00932                 {
00933                   assert (orig_name != NULL);
00934                   /* If the canonical name cannot be determined, use
00935                      the passed in string.  */
00936                   canon = orig_name;
00937                 }
00938              }
00939 
00940 #ifdef HAVE_LIBIDN
00941            if (req->ai_flags & AI_CANONIDN)
00942              {
00943               int idn_flags = 0;
00944               if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
00945                 idn_flags |= IDNA_ALLOW_UNASSIGNED;
00946               if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
00947                 idn_flags |= IDNA_USE_STD3_ASCII_RULES;
00948 
00949               char *out;
00950               int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
00951               if (rc != IDNA_SUCCESS)
00952                 {
00953                   if (rc == IDNA_MALLOC_ERROR)
00954                     return -EAI_MEMORY;
00955                   if (rc == IDNA_DLOPEN_ERROR)
00956                     return -EAI_SYSTEM;
00957                   return -EAI_IDN_ENCODE;
00958                 }
00959               /* In case the output string is the same as the input
00960                  string no new string has been allocated and we
00961                  make a copy.  */
00962               if (out == canon)
00963                 goto make_copy;
00964              }
00965            else
00966 #endif
00967              {
00968 #ifdef HAVE_LIBIDN
00969              make_copy:
00970 #endif
00971               canon = strdup (canon);
00972               if (canon == NULL)
00973                 return -EAI_MEMORY;
00974              }
00975          }
00976 
00977        family = at2->family;
00978        if (family == AF_INET6)
00979          {
00980            socklen = sizeof (struct sockaddr_in6);
00981 
00982            /* If we looked up IPv4 mapped address discard them here if
00983               the caller isn't interested in all address and we have
00984               found at least one IPv6 address.  */
00985            if (got_ipv6
00986               && (req->ai_flags & (AI_V4MAPPED|AI_ALL)) == AI_V4MAPPED
00987               && IN6_IS_ADDR_V4MAPPED (at2->addr))
00988              goto ignore;
00989          }
00990        else
00991          socklen = sizeof (struct sockaddr_in);
00992 
00993        for (st2 = st; st2 != NULL; st2 = st2->next)
00994          {
00995            struct addrinfo *ai;
00996            ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
00997            if (ai == NULL)
00998              {
00999               free ((char *) canon);
01000               return -EAI_MEMORY;
01001              }
01002 
01003            ai->ai_flags = req->ai_flags;
01004            ai->ai_family = family;
01005            ai->ai_socktype = st2->socktype;
01006            ai->ai_protocol = st2->protocol;
01007            ai->ai_addrlen = socklen;
01008            ai->ai_addr = (void *) (ai + 1);
01009 
01010            /* We only add the canonical name once.  */
01011            ai->ai_canonname = (char *) canon;
01012            canon = NULL;
01013 
01014 #ifdef _HAVE_SA_LEN
01015            ai->ai_addr->sa_len = socklen;
01016 #endif /* _HAVE_SA_LEN */
01017            ai->ai_addr->sa_family = family;
01018 
01019            /* In case of an allocation error the list must be NULL
01020               terminated.  */
01021            ai->ai_next = NULL;
01022 
01023            if (family == AF_INET6)
01024              {
01025               struct sockaddr_in6 *sin6p =
01026                 (struct sockaddr_in6 *) ai->ai_addr;
01027 
01028               sin6p->sin6_port = st2->port;
01029               sin6p->sin6_flowinfo = 0;
01030               memcpy (&sin6p->sin6_addr,
01031                      at2->addr, sizeof (struct in6_addr));
01032               sin6p->sin6_scope_id = at2->scopeid;
01033              }
01034            else
01035              {
01036               struct sockaddr_in *sinp =
01037                 (struct sockaddr_in *) ai->ai_addr;
01038               sinp->sin_port = st2->port;
01039               memcpy (&sinp->sin_addr,
01040                      at2->addr, sizeof (struct in_addr));
01041               memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
01042              }
01043 
01044            pai = &(ai->ai_next);
01045          }
01046 
01047        ++*naddrs;
01048 
01049       ignore:
01050        at2 = at2->next;
01051       }
01052   }
01053   return 0;
01054 }
01055 
01056 
01057 struct sort_result
01058 {
01059   struct addrinfo *dest_addr;
01060   /* Using sockaddr_storage is for now overkill.  We only support IPv4
01061      and IPv6 so far.  If this changes at some point we can adjust the
01062      type here.  */
01063   struct sockaddr_in6 source_addr;
01064   uint8_t source_addr_len;
01065   bool got_source_addr;
01066   uint8_t source_addr_flags;
01067   uint8_t prefixlen;
01068   uint32_t index;
01069   int32_t native;
01070 };
01071 
01072 struct sort_result_combo
01073 {
01074   struct sort_result *results;
01075   int nresults;
01076 };
01077 
01078 
01079 #if __BYTE_ORDER == __BIG_ENDIAN
01080 # define htonl_c(n) n
01081 #else
01082 # define htonl_c(n) __bswap_constant_32 (n)
01083 #endif
01084 
01085 static const struct scopeentry
01086 {
01087   union
01088   {
01089     char addr[4];
01090     uint32_t addr32;
01091   };
01092   uint32_t netmask;
01093   int32_t scope;
01094 } default_scopes[] =
01095   {
01096     /* Link-local addresses: scope 2.  */
01097     { { { 169, 254, 0, 0 } }, htonl_c (0xffff0000), 2 },
01098     { { { 127, 0, 0, 0 } }, htonl_c (0xff000000), 2 },
01099     /* Site-local addresses: scope 5.  */
01100     { { { 10, 0, 0, 0 } }, htonl_c (0xff000000), 5 },
01101     { { { 172, 16, 0, 0 } }, htonl_c (0xfff00000), 5 },
01102     { { { 192, 168, 0, 0 } }, htonl_c (0xffff0000), 5 },
01103     /* Default: scope 14.  */
01104     { { { 0, 0, 0, 0 } }, htonl_c (0x00000000), 14 }
01105   };
01106 
01107 /* The label table.  */
01108 static const struct scopeentry *scopes;
01109 
01110 
01111 static int
01112 get_scope (const struct sockaddr_in6 *in6)
01113 {
01114   int scope;
01115   if (in6->sin6_family == PF_INET6)
01116     {
01117       if (! IN6_IS_ADDR_MULTICAST (&in6->sin6_addr))
01118        {
01119          if (IN6_IS_ADDR_LINKLOCAL (&in6->sin6_addr)
01120              /* RFC 4291 2.5.3 says that the loopback address is to be
01121                treated like a link-local address.  */
01122              || IN6_IS_ADDR_LOOPBACK (&in6->sin6_addr))
01123            scope = 2;
01124          else if (IN6_IS_ADDR_SITELOCAL (&in6->sin6_addr))
01125            scope = 5;
01126          else
01127            /* XXX Is this the correct default behavior?  */
01128            scope = 14;
01129        }
01130       else
01131        scope = in6->sin6_addr.s6_addr[1] & 0xf;
01132     }
01133   else if (in6->sin6_family == PF_INET)
01134     {
01135       const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
01136 
01137       size_t cnt = 0;
01138       while (1)
01139        {
01140          if ((in->sin_addr.s_addr & scopes[cnt].netmask)
01141              == scopes[cnt].addr32)
01142            return scopes[cnt].scope;
01143 
01144          ++cnt;
01145        }
01146       /* NOTREACHED */
01147     }
01148   else
01149     /* XXX What is a good default?  */
01150     scope = 15;
01151 
01152   return scope;
01153 }
01154 
01155 
01156 struct prefixentry
01157 {
01158   struct in6_addr prefix;
01159   unsigned int bits;
01160   int val;
01161 };
01162 
01163 
01164 /* The label table.  */
01165 static const struct prefixentry *labels;
01166 
01167 /* Default labels.  */
01168 static const struct prefixentry default_labels[] =
01169   {
01170     /* See RFC 3484 for the details.  */
01171     { { .__in6_u
01172        = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
01173                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
01174       }, 128, 0 },
01175     { { .__in6_u
01176        = { .__u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
01177                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
01178       }, 16, 2 },
01179     { { .__in6_u
01180        = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
01181                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
01182       }, 96, 3 },
01183     { { .__in6_u
01184        = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
01185                          0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
01186       }, 96, 4 },
01187     /* The next two entries differ from RFC 3484.  We need to treat
01188        IPv6 site-local addresses special because they are never NATed,
01189        unlike site-locale IPv4 addresses.  If this would not happen, on
01190        machines which have only IPv4 and IPv6 site-local addresses, the
01191        sorting would prefer the IPv6 site-local addresses, causing
01192        unnecessary delays when trying to connect to a global IPv6 address
01193        through a site-local IPv6 address.  */
01194     { { .__in6_u
01195        = { .__u6_addr8 = { 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
01196                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
01197       }, 10, 5 },
01198     { { .__in6_u
01199        = { .__u6_addr8 = { 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
01200                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
01201       }, 7, 6 },
01202     /* Additional rule for Teredo tunnels.  */
01203     { { .__in6_u
01204        = { .__u6_addr8 = { 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
01205                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
01206       }, 32, 7 },
01207     { { .__in6_u
01208        = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
01209                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
01210       }, 0, 1 }
01211   };
01212 
01213 
01214 /* The precedence table.  */
01215 static const struct prefixentry *precedence;
01216 
01217 /* The default precedences.  */
01218 static const struct prefixentry default_precedence[] =
01219   {
01220     /* See RFC 3484 for the details.  */
01221     { { .__in6_u
01222        = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
01223                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } }
01224       }, 128, 50 },
01225     { { .__in6_u
01226        = { .__u6_addr8 = { 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
01227                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
01228       }, 16, 30 },
01229     { { .__in6_u
01230        = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
01231                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
01232       }, 96, 20 },
01233     { { .__in6_u
01234        = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
01235                          0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 } }
01236       }, 96, 10 },
01237     { { .__in6_u
01238        = { .__u6_addr8 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
01239                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
01240       }, 0, 40 }
01241   };
01242 
01243 
01244 static int
01245 match_prefix (const struct sockaddr_in6 *in6,
01246              const struct prefixentry *list, int default_val)
01247 {
01248   int idx;
01249   struct sockaddr_in6 in6_mem;
01250 
01251   if (in6->sin6_family == PF_INET)
01252     {
01253       const struct sockaddr_in *in = (const struct sockaddr_in *) in6;
01254 
01255       /* Construct a V4-to-6 mapped address.  */
01256       in6_mem.sin6_family = PF_INET6;
01257       in6_mem.sin6_port = in->sin_port;
01258       in6_mem.sin6_flowinfo = 0;
01259       memset (&in6_mem.sin6_addr, '\0', sizeof (in6_mem.sin6_addr));
01260       in6_mem.sin6_addr.s6_addr16[5] = 0xffff;
01261       in6_mem.sin6_addr.s6_addr32[3] = in->sin_addr.s_addr;
01262       in6_mem.sin6_scope_id = 0;
01263 
01264       in6 = &in6_mem;
01265     }
01266   else if (in6->sin6_family != PF_INET6)
01267     return default_val;
01268 
01269   for (idx = 0; ; ++idx)
01270     {
01271       unsigned int bits = list[idx].bits;
01272       const uint8_t *mask = list[idx].prefix.s6_addr;
01273       const uint8_t *val = in6->sin6_addr.s6_addr;
01274 
01275       while (bits >= 8)
01276        {
01277          if (*mask != *val)
01278            break;
01279 
01280          ++mask;
01281          ++val;
01282          bits -= 8;
01283        }
01284 
01285       if (bits < 8)
01286        {
01287          if ((*mask & (0xff00 >> bits)) == (*val & (0xff00 >> bits)))
01288            /* Match!  */
01289            break;
01290        }
01291     }
01292 
01293   return list[idx].val;
01294 }
01295 
01296 
01297 static int
01298 get_label (const struct sockaddr_in6 *in6)
01299 {
01300   /* XXX What is a good default value?  */
01301   return match_prefix (in6, labels, INT_MAX);
01302 }
01303 
01304 
01305 static int
01306 get_precedence (const struct sockaddr_in6 *in6)
01307 {
01308   /* XXX What is a good default value?  */
01309   return match_prefix (in6, precedence, 0);
01310 }
01311 
01312 
01313 /* Find last bit set in a word.  */
01314 static int
01315 fls (uint32_t a)
01316 {
01317   uint32_t mask;
01318   int n;
01319   for (n = 0, mask = 1 << 31; n < 32; mask >>= 1, ++n)
01320     if ((a & mask) != 0)
01321       break;
01322   return n;
01323 }
01324 
01325 
01326 static int
01327 rfc3484_sort (const void *p1, const void *p2, void *arg)
01328 {
01329   const size_t idx1 = *(const size_t *) p1;
01330   const size_t idx2 = *(const size_t *) p2;
01331   struct sort_result_combo *src = (struct sort_result_combo *) arg;
01332   struct sort_result *a1 = &src->results[idx1];
01333   struct sort_result *a2 = &src->results[idx2];
01334 
01335   /* Rule 1: Avoid unusable destinations.
01336      We have the got_source_addr flag set if the destination is reachable.  */
01337   if (a1->got_source_addr && ! a2->got_source_addr)
01338     return -1;
01339   if (! a1->got_source_addr && a2->got_source_addr)
01340     return 1;
01341 
01342 
01343   /* Rule 2: Prefer matching scope.  Only interesting if both
01344      destination addresses are IPv6.  */
01345   int a1_dst_scope
01346     = get_scope ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
01347 
01348   int a2_dst_scope
01349     = get_scope ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
01350 
01351   if (a1->got_source_addr)
01352     {
01353       int a1_src_scope = get_scope (&a1->source_addr);
01354       int a2_src_scope = get_scope (&a2->source_addr);
01355 
01356       if (a1_dst_scope == a1_src_scope && a2_dst_scope != a2_src_scope)
01357        return -1;
01358       if (a1_dst_scope != a1_src_scope && a2_dst_scope == a2_src_scope)
01359        return 1;
01360     }
01361 
01362 
01363   /* Rule 3: Avoid deprecated addresses.  */
01364   if (a1->got_source_addr)
01365     {
01366       if (!(a1->source_addr_flags & in6ai_deprecated)
01367          && (a2->source_addr_flags & in6ai_deprecated))
01368        return -1;
01369       if ((a1->source_addr_flags & in6ai_deprecated)
01370          && !(a2->source_addr_flags & in6ai_deprecated))
01371        return 1;
01372     }
01373 
01374   /* Rule 4: Prefer home addresses.  */
01375   if (a1->got_source_addr)
01376     {
01377       if (!(a1->source_addr_flags & in6ai_homeaddress)
01378          && (a2->source_addr_flags & in6ai_homeaddress))
01379        return 1;
01380       if ((a1->source_addr_flags & in6ai_homeaddress)
01381          && !(a2->source_addr_flags & in6ai_homeaddress))
01382        return -1;
01383     }
01384 
01385   /* Rule 5: Prefer matching label.  */
01386   if (a1->got_source_addr)
01387     {
01388       int a1_dst_label
01389        = get_label ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
01390       int a1_src_label = get_label (&a1->source_addr);
01391 
01392       int a2_dst_label
01393        = get_label ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
01394       int a2_src_label = get_label (&a2->source_addr);
01395 
01396       if (a1_dst_label == a1_src_label && a2_dst_label != a2_src_label)
01397        return -1;
01398       if (a1_dst_label != a1_src_label && a2_dst_label == a2_src_label)
01399        return 1;
01400     }
01401 
01402 
01403   /* Rule 6: Prefer higher precedence.  */
01404   int a1_prec
01405     = get_precedence ((struct sockaddr_in6 *) a1->dest_addr->ai_addr);
01406   int a2_prec
01407     = get_precedence ((struct sockaddr_in6 *) a2->dest_addr->ai_addr);
01408 
01409   if (a1_prec > a2_prec)
01410     return -1;
01411   if (a1_prec < a2_prec)
01412     return 1;
01413 
01414 
01415   /* Rule 7: Prefer native transport.  */
01416   if (a1->got_source_addr)
01417     {
01418       /* The same interface index means the same interface which means
01419         there is no difference in transport.  This should catch many
01420         (most?) cases.  */
01421       if (a1->index != a2->index)
01422        {
01423          int a1_native = a1->native;
01424          int a2_native = a2->native;
01425 
01426          if (a1_native == -1 || a2_native == -1)
01427            {
01428              uint32_t a1_index;
01429              if (a1_native == -1)
01430               {
01431                 /* If we do not have the information use 'native' as
01432                    the default.  */
01433                 a1_native = 0;
01434                 a1_index = a1->index;
01435               }
01436              else
01437               a1_index = 0xffffffffu;
01438 
01439              uint32_t a2_index;
01440              if (a2_native == -1)
01441               {
01442                 /* If we do not have the information use 'native' as
01443                    the default.  */
01444                 a2_native = 0;
01445                 a2_index = a2->index;
01446               }
01447              else
01448               a2_index = 0xffffffffu;
01449 
01450              __check_native (a1_index, &a1_native, a2_index, &a2_native);
01451 
01452              /* Fill in the results in all the records.  */
01453              for (int i = 0; i < src->nresults; ++i)
01454               if (src->results[i].index == a1_index)
01455                 {
01456                   assert (src->results[i].native == -1
01457                          || src->results[i].native == a1_native);
01458                   src->results[i].native = a1_native;
01459                 }
01460               else if (src->results[i].index == a2_index)
01461                 {
01462                   assert (src->results[i].native == -1
01463                          || src->results[i].native == a2_native);
01464                   src->results[i].native = a2_native;
01465                 }
01466            }
01467 
01468          if (a1_native && !a2_native)
01469            return -1;
01470          if (!a1_native && a2_native)
01471            return 1;
01472        }
01473     }
01474 
01475 
01476   /* Rule 8: Prefer smaller scope.  */
01477   if (a1_dst_scope < a2_dst_scope)
01478     return -1;
01479   if (a1_dst_scope > a2_dst_scope)
01480     return 1;
01481 
01482 
01483   /* Rule 9: Use longest matching prefix.  */
01484   if (a1->got_source_addr
01485       && a1->dest_addr->ai_family == a2->dest_addr->ai_family)
01486     {
01487       int bit1 = 0;
01488       int bit2 = 0;
01489 
01490       if (a1->dest_addr->ai_family == PF_INET)
01491        {
01492          assert (a1->source_addr.sin6_family == PF_INET);
01493          assert (a2->source_addr.sin6_family == PF_INET);
01494 
01495          /* Outside of subnets, as defined by the network masks,
01496             common address prefixes for IPv4 addresses make no sense.
01497             So, define a non-zero value only if source and
01498             destination address are on the same subnet.  */
01499          struct sockaddr_in *in1_dst
01500            = (struct sockaddr_in *) a1->dest_addr->ai_addr;
01501          in_addr_t in1_dst_addr = ntohl (in1_dst->sin_addr.s_addr);
01502          struct sockaddr_in *in1_src
01503            = (struct sockaddr_in *) &a1->source_addr;
01504          in_addr_t in1_src_addr = ntohl (in1_src->sin_addr.s_addr);
01505          in_addr_t netmask1 = 0xffffffffu << (32 - a1->prefixlen);
01506 
01507          if ((in1_src_addr & netmask1) == (in1_dst_addr & netmask1))
01508            bit1 = fls (in1_dst_addr ^ in1_src_addr);
01509 
01510          struct sockaddr_in *in2_dst
01511            = (struct sockaddr_in *) a2->dest_addr->ai_addr;
01512          in_addr_t in2_dst_addr = ntohl (in2_dst->sin_addr.s_addr);
01513          struct sockaddr_in *in2_src
01514            = (struct sockaddr_in *) &a2->source_addr;
01515          in_addr_t in2_src_addr = ntohl (in2_src->sin_addr.s_addr);
01516          in_addr_t netmask2 = 0xffffffffu << (32 - a2->prefixlen);
01517 
01518          if ((in2_src_addr & netmask2) == (in2_dst_addr & netmask2))
01519            bit2 = fls (in2_dst_addr ^ in2_src_addr);
01520        }
01521       else if (a1->dest_addr->ai_family == PF_INET6)
01522        {
01523          assert (a1->source_addr.sin6_family == PF_INET6);
01524          assert (a2->source_addr.sin6_family == PF_INET6);
01525 
01526          struct sockaddr_in6 *in1_dst;
01527          struct sockaddr_in6 *in1_src;
01528          struct sockaddr_in6 *in2_dst;
01529          struct sockaddr_in6 *in2_src;
01530 
01531          in1_dst = (struct sockaddr_in6 *) a1->dest_addr->ai_addr;
01532          in1_src = (struct sockaddr_in6 *) &a1->source_addr;
01533          in2_dst = (struct sockaddr_in6 *) a2->dest_addr->ai_addr;
01534          in2_src = (struct sockaddr_in6 *) &a2->source_addr;
01535 
01536          int i;
01537          for (i = 0; i < 4; ++i)
01538            if (in1_dst->sin6_addr.s6_addr32[i]
01539               != in1_src->sin6_addr.s6_addr32[i]
01540               || (in2_dst->sin6_addr.s6_addr32[i]
01541                   != in2_src->sin6_addr.s6_addr32[i]))
01542              break;
01543 
01544          if (i < 4)
01545            {
01546              bit1 = fls (ntohl (in1_dst->sin6_addr.s6_addr32[i]
01547                              ^ in1_src->sin6_addr.s6_addr32[i]));
01548              bit2 = fls (ntohl (in2_dst->sin6_addr.s6_addr32[i]
01549                              ^ in2_src->sin6_addr.s6_addr32[i]));
01550            }
01551        }
01552 
01553       if (bit1 > bit2)
01554        return -1;
01555       if (bit1 < bit2)
01556        return 1;
01557     }
01558 
01559 
01560   /* Rule 10: Otherwise, leave the order unchanged.  To ensure this
01561      compare with the value indicating the order in which the entries
01562      have been received from the services.  NB: no two entries can have
01563      the same order so the test will never return zero.  */
01564   return idx1 < idx2 ? -1 : 1;
01565 }
01566 
01567 
01568 static int
01569 in6aicmp (const void *p1, const void *p2)
01570 {
01571   struct in6addrinfo *a1 = (struct in6addrinfo *) p1;
01572   struct in6addrinfo *a2 = (struct in6addrinfo *) p2;
01573 
01574   return memcmp (a1->addr, a2->addr, sizeof (a1->addr));
01575 }
01576 
01577 
01578 /* Name of the config file for RFC 3484 sorting (for now).  */
01579 #define GAICONF_FNAME "/etc/gai.conf"
01580 
01581 
01582 /* Non-zero if we are supposed to reload the config file automatically
01583    whenever it changed.  */
01584 static int gaiconf_reload_flag;
01585 
01586 /* Non-zero if gaiconf_reload_flag was ever set to true.  */
01587 static int gaiconf_reload_flag_ever_set;
01588 
01589 /* Last modification time.  */
01590 static struct timespec gaiconf_mtime;
01591 
01592 
01593 libc_freeres_fn(fini)
01594 {
01595   if (labels != default_labels)
01596     {
01597       const struct prefixentry *old = labels;
01598       labels = default_labels;
01599       free ((void *) old);
01600     }
01601 
01602   if (precedence != default_precedence)
01603     {
01604       const struct prefixentry *old = precedence;
01605       precedence = default_precedence;
01606       free ((void *) old);
01607     }
01608 
01609   if (scopes != default_scopes)
01610     {
01611       const struct scopeentry *old = scopes;
01612       scopes = default_scopes;
01613       free ((void *) old);
01614     }
01615 }
01616 
01617 
01618 struct prefixlist
01619 {
01620   struct prefixentry entry;
01621   struct prefixlist *next;
01622 };
01623 
01624 
01625 struct scopelist
01626 {
01627   struct scopeentry entry;
01628   struct scopelist *next;
01629 };
01630 
01631 
01632 static void
01633 free_prefixlist (struct prefixlist *list)
01634 {
01635   while (list != NULL)
01636     {
01637       struct prefixlist *oldp = list;
01638       list = list->next;
01639       free (oldp);
01640     }
01641 }
01642 
01643 
01644 static void
01645 free_scopelist (struct scopelist *list)
01646 {
01647   while (list != NULL)
01648     {
01649       struct scopelist *oldp = list;
01650       list = list->next;
01651       free (oldp);
01652     }
01653 }
01654 
01655 
01656 static int
01657 prefixcmp (const void *p1, const void *p2)
01658 {
01659   const struct prefixentry *e1 = (const struct prefixentry *) p1;
01660   const struct prefixentry *e2 = (const struct prefixentry *) p2;
01661 
01662   if (e1->bits < e2->bits)
01663     return 1;
01664   if (e1->bits == e2->bits)
01665     return 0;
01666   return -1;
01667 }
01668 
01669 
01670 static int
01671 scopecmp (const void *p1, const void *p2)
01672 {
01673   const struct scopeentry *e1 = (const struct scopeentry *) p1;
01674   const struct scopeentry *e2 = (const struct scopeentry *) p2;
01675 
01676   if (e1->netmask > e2->netmask)
01677     return -1;
01678   if (e1->netmask == e2->netmask)
01679     return 0;
01680   return 1;
01681 }
01682 
01683 
01684 static void
01685 gaiconf_init (void)
01686 {
01687   struct prefixlist *labellist = NULL;
01688   size_t nlabellist = 0;
01689   bool labellist_nullbits = false;
01690   struct prefixlist *precedencelist = NULL;
01691   size_t nprecedencelist = 0;
01692   bool precedencelist_nullbits = false;
01693   struct scopelist *scopelist =  NULL;
01694   size_t nscopelist = 0;
01695   bool scopelist_nullbits = false;
01696 
01697   FILE *fp = fopen (GAICONF_FNAME, "rc");
01698   if (fp != NULL)
01699     {
01700       struct stat64 st;
01701       if (__fxstat64 (_STAT_VER, fileno (fp), &st) != 0)
01702        {
01703          fclose (fp);
01704          goto no_file;
01705        }
01706 
01707       char *line = NULL;
01708       size_t linelen = 0;
01709 
01710       __fsetlocking (fp, FSETLOCKING_BYCALLER);
01711 
01712       while (!feof_unlocked (fp))
01713        {
01714          ssize_t n = __getline (&line, &linelen, fp);
01715          if (n <= 0)
01716            break;
01717 
01718          /* Handle comments.  No escaping possible so this is easy.  */
01719          char *cp = strchr (line, '#');
01720          if (cp != NULL)
01721            *cp = '\0';
01722 
01723          cp = line;
01724          while (isspace (*cp))
01725            ++cp;
01726 
01727          char *cmd = cp;
01728          while (*cp != '\0' && !isspace (*cp))
01729            ++cp;
01730          size_t cmdlen = cp - cmd;
01731 
01732          if (*cp != '\0')
01733            *cp++ = '\0';
01734          while (isspace (*cp))
01735            ++cp;
01736 
01737          char *val1 = cp;
01738          while (*cp != '\0' && !isspace (*cp))
01739            ++cp;
01740          size_t val1len = cp - cmd;
01741 
01742          /* We always need at least two values.  */
01743          if (val1len == 0)
01744            continue;
01745 
01746          if (*cp != '\0')
01747            *cp++ = '\0';
01748          while (isspace (*cp))
01749            ++cp;
01750 
01751          char *val2 = cp;
01752          while (*cp != '\0' && !isspace (*cp))
01753            ++cp;
01754 
01755          /*  Ignore the rest of the line.  */
01756          *cp = '\0';
01757 
01758          struct prefixlist **listp;
01759          size_t *lenp;
01760          bool *nullbitsp;
01761          switch (cmdlen)
01762            {
01763            case 5:
01764              if (strcmp (cmd, "label") == 0)
01765               {
01766                 struct in6_addr prefix;
01767                 unsigned long int bits;
01768                 unsigned long int val;
01769                 char *endp;
01770 
01771                 listp = &labellist;
01772                 lenp = &nlabellist;
01773                 nullbitsp = &labellist_nullbits;
01774 
01775               new_elem:
01776                 bits = 128;
01777                 __set_errno (0);
01778                 cp = strchr (val1, '/');
01779                 if (cp != NULL)
01780                   *cp++ = '\0';
01781                 if (inet_pton (AF_INET6, val1, &prefix)
01782                     && (cp == NULL
01783                        || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
01784                        || errno != ERANGE)
01785                     && *endp == '\0'
01786                     && bits <= 128
01787                     && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
01788                        || errno != ERANGE)
01789                     && *endp == '\0'
01790                     && val <= INT_MAX)
01791                   {
01792                     struct prefixlist *newp = malloc (sizeof (*newp));
01793                     if (newp == NULL)
01794                      {
01795                        free (line);
01796                        fclose (fp);
01797                        goto no_file;
01798                      }
01799 
01800                     memcpy (&newp->entry.prefix, &prefix, sizeof (prefix));
01801                     newp->entry.bits = bits;
01802                     newp->entry.val = val;
01803                     newp->next = *listp;
01804                     *listp = newp;
01805                     ++*lenp;
01806                     *nullbitsp |= bits == 0;
01807                   }
01808               }
01809              break;
01810 
01811            case 6:
01812              if (strcmp (cmd, "reload") == 0)
01813               {
01814                 gaiconf_reload_flag = strcmp (val1, "yes") == 0;
01815                 if (gaiconf_reload_flag)
01816                   gaiconf_reload_flag_ever_set = 1;
01817               }
01818              break;
01819 
01820            case 7:
01821              if (strcmp (cmd, "scopev4") == 0)
01822               {
01823                 struct in6_addr prefix;
01824                 unsigned long int bits;
01825                 unsigned long int val;
01826                 char *endp;
01827 
01828                 bits = 32;
01829                 __set_errno (0);
01830                 cp = strchr (val1, '/');
01831                 if (cp != NULL)
01832                   *cp++ = '\0';
01833                 if (inet_pton (AF_INET6, val1, &prefix))
01834                   {
01835                     bits = 128;
01836                     if (IN6_IS_ADDR_V4MAPPED (&prefix)
01837                        && (cp == NULL
01838                            || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
01839                            || errno != ERANGE)
01840                        && *endp == '\0'
01841                        && bits >= 96
01842                        && bits <= 128
01843                        && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
01844                            || errno != ERANGE)
01845                        && *endp == '\0'
01846                        && val <= INT_MAX)
01847                      {
01848                        struct scopelist *newp;
01849                      new_scope:
01850                        newp = malloc (sizeof (*newp));
01851                        if (newp == NULL)
01852                          {
01853                            free (line);
01854                            fclose (fp);
01855                            goto no_file;
01856                          }
01857 
01858                        newp->entry.netmask = htonl (bits != 96
01859                                                  ? (0xffffffff
01860                                                    << (128 - bits))
01861                                                  : 0);
01862                        newp->entry.addr32 = (prefix.s6_addr32[3]
01863                                           & newp->entry.netmask);
01864                        newp->entry.scope = val;
01865                        newp->next = scopelist;
01866                        scopelist = newp;
01867                        ++nscopelist;
01868                        scopelist_nullbits |= bits == 96;
01869                      }
01870                   }
01871                 else if (inet_pton (AF_INET, val1, &prefix.s6_addr32[3])
01872                         && (cp == NULL
01873                             || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
01874                             || errno != ERANGE)
01875                         && *endp == '\0'
01876                         && bits <= 32
01877                         && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
01878                             || errno != ERANGE)
01879                         && *endp == '\0'
01880                         && val <= INT_MAX)
01881                   {
01882                     bits += 96;
01883                     goto new_scope;
01884                   }
01885               }
01886              break;
01887 
01888            case 10:
01889              if (strcmp (cmd, "precedence") == 0)
01890               {
01891                 listp = &precedencelist;
01892                 lenp = &nprecedencelist;
01893                 nullbitsp = &precedencelist_nullbits;
01894                 goto new_elem;
01895               }
01896              break;
01897            }
01898        }
01899 
01900       free (line);
01901 
01902       fclose (fp);
01903 
01904       /* Create the array for the labels.  */
01905       struct prefixentry *new_labels;
01906       if (nlabellist > 0)
01907        {
01908          if (!labellist_nullbits)
01909            ++nlabellist;
01910          new_labels = malloc (nlabellist * sizeof (*new_labels));
01911          if (new_labels == NULL)
01912            goto no_file;
01913 
01914          int i = nlabellist;
01915          if (!labellist_nullbits)
01916            {
01917              --i;
01918              memset (&new_labels[i].prefix, '\0', sizeof (struct in6_addr));
01919              new_labels[i].bits = 0;
01920              new_labels[i].val = 1;
01921            }
01922 
01923          struct prefixlist *l = labellist;
01924          while (i-- > 0)
01925            {
01926              new_labels[i] = l->entry;
01927              l = l->next;
01928            }
01929          free_prefixlist (labellist);
01930 
01931          /* Sort the entries so that the most specific ones are at
01932             the beginning.  */
01933          qsort (new_labels, nlabellist, sizeof (*new_labels), prefixcmp);
01934        }
01935       else
01936        new_labels = (struct prefixentry *) default_labels;
01937 
01938       struct prefixentry *new_precedence;
01939       if (nprecedencelist > 0)
01940        {
01941          if (!precedencelist_nullbits)
01942            ++nprecedencelist;
01943          new_precedence = malloc (nprecedencelist * sizeof (*new_precedence));
01944          if (new_precedence == NULL)
01945            {
01946              if (new_labels != default_labels)
01947               free (new_labels);
01948              goto no_file;
01949            }
01950 
01951          int i = nprecedencelist;
01952          if (!precedencelist_nullbits)
01953            {
01954              --i;
01955              memset (&new_precedence[i].prefix, '\0',
01956                     sizeof (struct in6_addr));
01957              new_precedence[i].bits = 0;
01958              new_precedence[i].val = 40;
01959            }
01960 
01961          struct prefixlist *l = precedencelist;
01962          while (i-- > 0)
01963            {
01964              new_precedence[i] = l->entry;
01965              l = l->next;
01966            }
01967          free_prefixlist (precedencelist);
01968 
01969          /* Sort the entries so that the most specific ones are at
01970             the beginning.  */
01971          qsort (new_precedence, nprecedencelist, sizeof (*new_precedence),
01972                prefixcmp);
01973        }
01974       else
01975        new_precedence = (struct prefixentry *) default_precedence;
01976 
01977       struct scopeentry *new_scopes;
01978       if (nscopelist > 0)
01979        {
01980          if (!scopelist_nullbits)
01981            ++nscopelist;
01982          new_scopes = malloc (nscopelist * sizeof (*new_scopes));
01983          if (new_scopes == NULL)
01984            {
01985              if (new_labels != default_labels)
01986               free (new_labels);
01987              if (new_precedence != default_precedence)
01988               free (new_precedence);
01989              goto no_file;
01990            }
01991 
01992          int i = nscopelist;
01993          if (!scopelist_nullbits)
01994            {
01995              --i;
01996              new_scopes[i].addr32 = 0;
01997              new_scopes[i].netmask = 0;
01998              new_scopes[i].scope = 14;
01999            }
02000 
02001          struct scopelist *l = scopelist;
02002          while (i-- > 0)
02003            {
02004              new_scopes[i] = l->entry;
02005              l = l->next;
02006            }
02007          free_scopelist (scopelist);
02008 
02009          /* Sort the entries so that the most specific ones are at
02010             the beginning.  */
02011          qsort (new_scopes, nscopelist, sizeof (*new_scopes),
02012                scopecmp);
02013        }
02014       else
02015        new_scopes = (struct scopeentry *) default_scopes;
02016 
02017       /* Now we are ready to replace the values.  */
02018       const struct prefixentry *old = labels;
02019       labels = new_labels;
02020       if (old != default_labels)
02021        free ((void *) old);
02022 
02023       old = precedence;
02024       precedence = new_precedence;
02025       if (old != default_precedence)
02026        free ((void *) old);
02027 
02028       const struct scopeentry *oldscope = scopes;
02029       scopes = new_scopes;
02030       if (oldscope != default_scopes)
02031        free ((void *) oldscope);
02032 
02033       gaiconf_mtime = st.st_mtim;
02034     }
02035   else
02036     {
02037     no_file:
02038       free_prefixlist (labellist);
02039       free_prefixlist (precedencelist);
02040       free_scopelist (scopelist);
02041 
02042       /* If we previously read the file but it is gone now, free the
02043         old data and use the builtin one.  Leave the reload flag
02044         alone.  */
02045       fini ();
02046     }
02047 }
02048 
02049 
02050 static void
02051 gaiconf_reload (void)
02052 {
02053   struct stat64 st;
02054   if (__xstat64 (_STAT_VER, GAICONF_FNAME, &st) != 0
02055       || memcmp (&st.st_mtim, &gaiconf_mtime, sizeof (gaiconf_mtime)) != 0)
02056     gaiconf_init ();
02057 }
02058 
02059 
02060 int
02061 getaddrinfo (const char *name, const char *service,
02062             const struct addrinfo *hints, struct addrinfo **pai)
02063 {
02064   int i = 0, last_i = 0;
02065   int nresults = 0;
02066   struct addrinfo *p = NULL;
02067   struct gaih_service gaih_service, *pservice;
02068   struct addrinfo local_hints;
02069 
02070   if (name != NULL && name[0] == '*' && name[1] == 0)
02071     name = NULL;
02072 
02073   if (service != NULL && service[0] == '*' && service[1] == 0)
02074     service = NULL;
02075 
02076   if (name == NULL && service == NULL)
02077     return EAI_NONAME;
02078 
02079   if (hints == NULL)
02080     hints = &default_hints;
02081 
02082   if (hints->ai_flags
02083       & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|AI_ADDRCONFIG|AI_V4MAPPED
02084 #ifdef HAVE_LIBIDN
02085          |AI_IDN|AI_CANONIDN|AI_IDN_ALLOW_UNASSIGNED
02086          |AI_IDN_USE_STD3_ASCII_RULES
02087 #endif
02088          |AI_NUMERICSERV|AI_ALL))
02089     return EAI_BADFLAGS;
02090 
02091   if ((hints->ai_flags & AI_CANONNAME) && name == NULL)
02092     return EAI_BADFLAGS;
02093 
02094   struct in6addrinfo *in6ai = NULL;
02095   size_t in6ailen = 0;
02096   bool seen_ipv4 = false;
02097   bool seen_ipv6 = false;
02098   /* We might need information about what interfaces are available.
02099      Also determine whether we have IPv4 or IPv6 interfaces or both.  We
02100      cannot cache the results since new interfaces could be added at
02101      any time.  */
02102   __check_pf (&seen_ipv4, &seen_ipv6, &in6ai, &in6ailen);
02103 
02104   if (hints->ai_flags & AI_ADDRCONFIG)
02105     {
02106       /* Now make a decision on what we return, if anything.  */
02107       if (hints->ai_family == PF_UNSPEC && (seen_ipv4 || seen_ipv6))
02108        {
02109          /* If we haven't seen both IPv4 and IPv6 interfaces we can
02110             narrow down the search.  */
02111          if (! seen_ipv4 || ! seen_ipv6)
02112            {
02113              local_hints = *hints;
02114              local_hints.ai_family = seen_ipv4 ? PF_INET : PF_INET6;
02115              hints = &local_hints;
02116            }
02117        }
02118       else if ((hints->ai_family == PF_INET && ! seen_ipv4)
02119               || (hints->ai_family == PF_INET6 && ! seen_ipv6))
02120        {
02121          /* We cannot possibly return a valid answer.  */
02122          free (in6ai);
02123          return EAI_NONAME;
02124        }
02125     }
02126 
02127   if (service && service[0])
02128     {
02129       char *c;
02130       gaih_service.name = service;
02131       gaih_service.num = strtoul (gaih_service.name, &c, 10);
02132       if (*c != '\0')
02133        {
02134          if (hints->ai_flags & AI_NUMERICSERV)
02135            {
02136              free (in6ai);
02137              return EAI_NONAME;
02138            }
02139 
02140          gaih_service.num = -1;
02141        }
02142 
02143       pservice = &gaih_service;
02144     }
02145   else
02146     pservice = NULL;
02147 
02148   struct addrinfo **end = &p;
02149 
02150   unsigned int naddrs = 0;
02151   if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET
02152       || hints->ai_family == AF_INET6)
02153     {
02154       last_i = gaih_inet (name, pservice, hints, end, &naddrs);
02155       if (last_i != 0)
02156        {
02157          freeaddrinfo (p);
02158          free (in6ai);
02159 
02160          return -(last_i & GAIH_EAI);
02161        }
02162       while (*end)
02163        {
02164          end = &((*end)->ai_next);
02165          ++nresults;
02166        }
02167     }
02168   else
02169     {
02170       free (in6ai);
02171       return EAI_FAMILY;
02172     }
02173 
02174   if (naddrs > 1)
02175     {
02176       /* Read the config file.  */
02177       __libc_once_define (static, once);
02178       __typeof (once) old_once = once;
02179       __libc_once (once, gaiconf_init);
02180       /* Sort results according to RFC 3484.  */
02181       struct sort_result results[nresults];
02182       size_t order[nresults];
02183       struct addrinfo *q;
02184       struct addrinfo *last = NULL;
02185       char *canonname = NULL;
02186 
02187       /* If we have information about deprecated and temporary addresses
02188         sort the array now.  */
02189       if (in6ai != NULL)
02190        qsort (in6ai, in6ailen, sizeof (*in6ai), in6aicmp);
02191 
02192       int fd = -1;
02193       int af = AF_UNSPEC;
02194 
02195       for (i = 0, q = p; q != NULL; ++i, last = q, q = q->ai_next)
02196        {
02197          results[i].dest_addr = q;
02198          results[i].native = -1;
02199          order[i] = i;
02200 
02201          /* If we just looked up the address for a different
02202             protocol, reuse the result.  */
02203          if (last != NULL && last->ai_addrlen == q->ai_addrlen
02204              && memcmp (last->ai_addr, q->ai_addr, q->ai_addrlen) == 0)
02205            {
02206              memcpy (&results[i].source_addr, &results[i - 1].source_addr,
02207                     results[i - 1].source_addr_len);
02208              results[i].source_addr_len = results[i - 1].source_addr_len;
02209              results[i].got_source_addr = results[i - 1].got_source_addr;
02210              results[i].source_addr_flags = results[i - 1].source_addr_flags;
02211              results[i].prefixlen = results[i - 1].prefixlen;
02212              results[i].index = results[i - 1].index;
02213            }
02214          else
02215            {
02216              results[i].got_source_addr = false;
02217              results[i].source_addr_flags = 0;
02218              results[i].prefixlen = 0;
02219              results[i].index = 0xffffffffu;
02220 
02221              /* We overwrite the type with SOCK_DGRAM since we do not
02222                want connect() to connect to the other side.  If we
02223                cannot determine the source address remember this
02224                fact.  */
02225              if (fd == -1 || (af == AF_INET && q->ai_family == AF_INET6))
02226               {
02227                 if (fd != -1)
02228                 close_retry:
02229                   close_not_cancel_no_status (fd);
02230                 af = q->ai_family;
02231                 fd = __socket (af, SOCK_DGRAM, IPPROTO_IP);
02232               }
02233              else
02234               {
02235                 /* Reset the connection.  */
02236                 struct sockaddr sa = { .sa_family = AF_UNSPEC };
02237                 __connect (fd, &sa, sizeof (sa));
02238               }
02239 
02240              socklen_t sl = sizeof (results[i].source_addr);
02241              if (fd != -1
02242                 && __connect (fd, q->ai_addr, q->ai_addrlen) == 0
02243                 && __getsockname (fd,
02244                                 (struct sockaddr *) &results[i].source_addr,
02245                                 &sl) == 0)
02246               {
02247                 results[i].source_addr_len = sl;
02248                 results[i].got_source_addr = true;
02249 
02250                 if (in6ai != NULL)
02251                   {
02252                     /* See whether the source address is on the list of
02253                       deprecated or temporary addresses.  */
02254                     struct in6addrinfo tmp;
02255 
02256                     if (q->ai_family == AF_INET && af == AF_INET)
02257                      {
02258                        struct sockaddr_in *sinp
02259                          = (struct sockaddr_in *) &results[i].source_addr;
02260                        tmp.addr[0] = 0;
02261                        tmp.addr[1] = 0;
02262                        tmp.addr[2] = htonl (0xffff);
02263                        tmp.addr[3] = sinp->sin_addr.s_addr;
02264                      }
02265                     else
02266                      {
02267                        struct sockaddr_in6 *sin6p
02268                          = (struct sockaddr_in6 *) &results[i].source_addr;
02269                        memcpy (tmp.addr, &sin6p->sin6_addr, IN6ADDRSZ);
02270                      }
02271 
02272                     struct in6addrinfo *found
02273                      = bsearch (&tmp, in6ai, in6ailen, sizeof (*in6ai),
02274                                in6aicmp);
02275                     if (found != NULL)
02276                      {
02277                        results[i].source_addr_flags = found->flags;
02278                        results[i].prefixlen = found->prefixlen;
02279                        results[i].index = found->index;
02280                      }
02281                   }
02282 
02283                 if (q->ai_family == AF_INET && af == AF_INET6)
02284                   {
02285                     /* We have to convert the address.  The socket is
02286                       IPv6 and the request is for IPv4.  */
02287                     struct sockaddr_in6 *sin6
02288                      = (struct sockaddr_in6 *) &results[i].source_addr;
02289                     struct sockaddr_in *sin
02290                      = (struct sockaddr_in *) &results[i].source_addr;
02291                     assert (IN6_IS_ADDR_V4MAPPED (sin6->sin6_addr.s6_addr32));
02292                     sin->sin_family = AF_INET;
02293                     /* We do not have to initialize sin_port since this
02294                       fields has the same position and size in the IPv6
02295                       structure.  */
02296                     assert (offsetof (struct sockaddr_in, sin_port)
02297                            == offsetof (struct sockaddr_in6, sin6_port));
02298                     assert (sizeof (sin->sin_port)
02299                            == sizeof (sin6->sin6_port));
02300                     memcpy (&sin->sin_addr,
02301                            &sin6->sin6_addr.s6_addr32[3], INADDRSZ);
02302                     results[i].source_addr_len = sizeof (struct sockaddr_in);
02303                   }
02304               }
02305              else if (errno == EAFNOSUPPORT && af == AF_INET6
02306                      && q->ai_family == AF_INET)
02307               /* This could mean IPv6 sockets are IPv6-only.  */
02308               goto close_retry;
02309              else
02310               /* Just make sure that if we have to process the same
02311                  address again we do not copy any memory.  */
02312               results[i].source_addr_len = 0;
02313            }
02314 
02315          /* Remember the canonical name.  */
02316          if (q->ai_canonname != NULL)
02317            {
02318              assert (canonname == NULL);
02319              canonname = q->ai_canonname;
02320              q->ai_canonname = NULL;
02321            }
02322        }
02323 
02324       if (fd != -1)
02325        close_not_cancel_no_status (fd);
02326 
02327       /* We got all the source addresses we can get, now sort using
02328         the information.  */
02329       struct sort_result_combo src
02330        = { .results = results, .nresults = nresults };
02331       if (__builtin_expect (gaiconf_reload_flag_ever_set, 0))
02332        {
02333          __libc_lock_define_initialized (static, lock);
02334 
02335          __libc_lock_lock (lock);
02336          if (old_once && gaiconf_reload_flag)
02337            gaiconf_reload ();
02338          qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
02339          __libc_lock_unlock (lock);
02340        }
02341       else
02342        qsort_r (order, nresults, sizeof (order[0]), rfc3484_sort, &src);
02343 
02344       /* Queue the results up as they come out of sorting.  */
02345       q = p = results[order[0]].dest_addr;
02346       for (i = 1; i < nresults; ++i)
02347        q = q->ai_next = results[order[i]].dest_addr;
02348       q->ai_next = NULL;
02349 
02350       /* Fill in the canonical name into the new first entry.  */
02351       p->ai_canonname = canonname;
02352     }
02353 
02354   free (in6ai);
02355 
02356   if (p)
02357     {
02358       *pai = p;
02359       return 0;
02360     }
02361 
02362   return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;
02363 }
02364 libc_hidden_def (getaddrinfo)
02365 
02366 static_link_warning (getaddrinfo)
02367 
02368 void
02369 freeaddrinfo (struct addrinfo *ai)
02370 {
02371   struct addrinfo *p;
02372 
02373   while (ai != NULL)
02374     {
02375       p = ai;
02376       ai = ai->ai_next;
02377       free (p->ai_canonname);
02378       free (p);
02379     }
02380 }
02381 libc_hidden_def (freeaddrinfo)