(root)/
Python-3.11.7/
Modules/
getaddrinfo.c
       1  /*
       2   * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
       3   * All rights reserved.
       4   *
       5   * Redistribution and use in source and binary forms, with or without
       6   * modification, are permitted provided that the following conditions
       7   * are met:
       8   * 1. Redistributions of source code must retain the above copyright
       9   *    notice, this list of conditions and the following disclaimer.
      10   * 2. Redistributions in binary form must reproduce the above copyright
      11   *    notice, this list of conditions and the following disclaimer in the
      12   *    documentation and/or other materials provided with the distribution.
      13   * 3. Neither the name of the project nor the names of its contributors
      14   *    may be used to endorse or promote products derived from this software
      15   *    without specific prior written permission.
      16   *
      17   * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
      18   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      19   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      20   * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
      21   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      22   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      23   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      24   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      25   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      26   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      27   * SUCH DAMAGE.
      28   */
      29  
      30  /*
      31   * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
      32   *
      33   * Issues to be discussed:
      34   * - Thread safe-ness must be checked.
      35   * - Return values.  There are nonstandard return values defined and used
      36   *   in the source code.  This is because RFC2133 is silent about which error
      37   *   code must be returned for which situation.
      38   * - PF_UNSPEC case would be handled in getipnodebyname() with the AI_ALL flag.
      39   */
      40  
      41  #if 0
      42  #include <sys/types.h>
      43  #include <sys/param.h>
      44  #include <sys/sysctl.h>
      45  #include <sys/socket.h>
      46  #include <netinet/in.h>
      47  #include <arpa/inet.h>
      48  #include <arpa/nameser.h>
      49  #include <netdb.h>
      50  #include <resolv.h>
      51  #include <string.h>
      52  #include <stdlib.h>
      53  #include <stddef.h>
      54  #include <ctype.h>
      55  #include <unistd.h>
      56  
      57  #include "addrinfo.h"
      58  #endif
      59  
      60  #if defined(__KAME__) && defined(ENABLE_IPV6)
      61  # define FAITH
      62  #endif
      63  
      64  #ifdef HAVE_NETDB_H
      65  #define HAVE_GETADDRINFO 1
      66  
      67  #define SUCCESS 0
      68  #define GAI_ANY 0
      69  #define YES 1
      70  #define NO  0
      71  
      72  #ifdef FAITH
      73  static int translate = NO;
      74  static struct in6_addr faith_prefix = IN6ADDR_GAI_ANY_INIT;
      75  #endif
      76  
      77  static const char in_addrany[] = { 0, 0, 0, 0 };
      78  static const char in6_addrany[] = {
      79      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
      80  };
      81  static const char in_loopback[] = { 127, 0, 0, 1 };
      82  static const char in6_loopback[] = {
      83      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
      84  };
      85  
      86  struct sockinet {
      87      u_char      si_len;
      88      u_char      si_family;
      89      u_short     si_port;
      90  };
      91  
      92  static struct gai_afd {
      93      int a_af;
      94      int a_addrlen;
      95      int a_socklen;
      96      int a_off;
      97      const char *a_addrany;
      98      const char *a_loopback;
      99  } gai_afdl [] = {
     100  #ifdef ENABLE_IPV6
     101  #define N_INET6 0
     102      {PF_INET6, sizeof(struct in6_addr),
     103       sizeof(struct sockaddr_in6),
     104       offsetof(struct sockaddr_in6, sin6_addr),
     105       in6_addrany, in6_loopback},
     106  #define N_INET  1
     107  #else
     108  #define N_INET  0
     109  #endif
     110      {PF_INET, sizeof(struct in_addr),
     111       sizeof(struct sockaddr_in),
     112       offsetof(struct sockaddr_in, sin_addr),
     113       in_addrany, in_loopback},
     114      {0, 0, 0, 0, NULL, NULL},
     115  };
     116  
     117  #ifdef ENABLE_IPV6
     118  #define PTON_MAX        16
     119  #else
     120  #define PTON_MAX        4
     121  #endif
     122  
     123  #ifndef IN_MULTICAST
     124  #define IN_MULTICAST(i)     (((i) & 0xf0000000U) == 0xe0000000U)
     125  #endif
     126  
     127  #ifndef IN_EXPERIMENTAL
     128  #define IN_EXPERIMENTAL(i)  (((i) & 0xe0000000U) == 0xe0000000U)
     129  #endif
     130  
     131  #ifndef IN_LOOPBACKNET
     132  #define IN_LOOPBACKNET      127
     133  #endif
     134  
     135  static int get_name(const char *, struct gai_afd *,
     136                            struct addrinfo **, char *, struct addrinfo *,
     137                            int);
     138  static int get_addr(const char *, int, struct addrinfo **,
     139                          struct addrinfo *, int);
     140  static int str_isnumber(const char *);
     141  
     142  static const char * const ai_errlist[] = {
     143      "success.",
     144      "address family for hostname not supported.",       /* EAI_ADDRFAMILY */
     145      "temporary failure in name resolution.",            /* EAI_AGAIN      */
     146      "invalid value for ai_flags.",                      /* EAI_BADFLAGS   */
     147      "non-recoverable failure in name resolution.",      /* EAI_FAIL       */
     148      "ai_family not supported.",                         /* EAI_FAMILY     */
     149      "memory allocation failure.",                       /* EAI_MEMORY     */
     150      "no address associated with hostname.",             /* EAI_NODATA     */
     151      "hostname nor servname provided, or not known.",/* EAI_NONAME     */
     152      "servname not supported for ai_socktype.",          /* EAI_SERVICE    */
     153      "ai_socktype not supported.",                       /* EAI_SOCKTYPE   */
     154      "system error returned in errno.",                  /* EAI_SYSTEM     */
     155      "invalid value for hints.",                         /* EAI_BADHINTS   */
     156      "resolved protocol is unknown.",                    /* EAI_PROTOCOL   */
     157      "unknown error.",                                   /* EAI_MAX        */
     158  };
     159  
     160  #define GET_CANONNAME(ai, str) \
     161  if (pai->ai_flags & AI_CANONNAME) {\
     162      if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\
     163          strcpy((ai)->ai_canonname, (str));\
     164      } else {\
     165          error = EAI_MEMORY;\
     166          goto free;\
     167      }\
     168  }
     169  
     170  #ifdef HAVE_SOCKADDR_SA_LEN
     171  #define GET_AI(ai, gai_afd, addr, port) {\
     172      char *p;\
     173      if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\
     174                                            ((gai_afd)->a_socklen)))\
     175          == NULL) goto free;\
     176      memcpy(ai, pai, sizeof(struct addrinfo));\
     177      (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\
     178      memset((ai)->ai_addr, 0, (gai_afd)->a_socklen);\
     179      (ai)->ai_addr->sa_len = (ai)->ai_addrlen = (gai_afd)->a_socklen;\
     180      (ai)->ai_addr->sa_family = (ai)->ai_family = (gai_afd)->a_af;\
     181      ((struct sockinet *)(ai)->ai_addr)->si_port = port;\
     182      p = (char *)((ai)->ai_addr);\
     183      memcpy(p + (gai_afd)->a_off, (addr), (gai_afd)->a_addrlen);\
     184  }
     185  #else
     186  #define GET_AI(ai, gai_afd, addr, port) {\
     187      char *p;\
     188      if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\
     189                                            ((gai_afd)->a_socklen)))\
     190          == NULL) goto free;\
     191      memcpy(ai, pai, sizeof(struct addrinfo));\
     192      (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\
     193      memset((ai)->ai_addr, 0, (gai_afd)->a_socklen);\
     194      (ai)->ai_addrlen = (gai_afd)->a_socklen;\
     195      (ai)->ai_addr->sa_family = (ai)->ai_family = (gai_afd)->a_af;\
     196      ((struct sockinet *)(ai)->ai_addr)->si_port = port;\
     197      p = (char *)((ai)->ai_addr);\
     198      memcpy(p + (gai_afd)->a_off, (addr), (gai_afd)->a_addrlen);\
     199  }
     200  #endif
     201  
     202  #define ERR(err) { error = (err); goto bad; }
     203  
     204  const char *
     205  gai_strerror(int ecode)
     206  {
     207      if (ecode < 0 || ecode > EAI_MAX)
     208          ecode = EAI_MAX;
     209      return ai_errlist[ecode];
     210  }
     211  
     212  void
     213  freeaddrinfo(struct addrinfo *ai)
     214  {
     215      struct addrinfo *next;
     216  
     217      do {
     218          next = ai->ai_next;
     219          if (ai->ai_canonname)
     220              free(ai->ai_canonname);
     221          /* no need to free(ai->ai_addr) */
     222          free(ai);
     223      } while ((ai = next) != NULL);
     224  }
     225  
     226  static int
     227  str_isnumber(const char *p)
     228  {
     229      unsigned char *q = (unsigned char *)p;
     230      while (*q) {
     231          if (! isdigit(*q))
     232              return NO;
     233          q++;
     234      }
     235      return YES;
     236  }
     237  
     238  int
     239  getaddrinfo(const char*hostname, const char*servname,
     240              const struct addrinfo *hints, struct addrinfo **res)
     241  {
     242      struct addrinfo sentinel;
     243      struct addrinfo *top = NULL;
     244      struct addrinfo *cur;
     245      int i, error = 0;
     246      char pton[PTON_MAX];
     247      struct addrinfo ai;
     248      struct addrinfo *pai;
     249      u_short port;
     250  
     251  #ifdef FAITH
     252      static int firsttime = 1;
     253  
     254      if (firsttime) {
     255          /* translator hack */
     256          {
     257              const char *q = getenv("GAI");
     258              if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1)
     259                  translate = YES;
     260          }
     261          firsttime = 0;
     262      }
     263  #endif
     264  
     265      /* initialize file static vars */
     266      sentinel.ai_next = NULL;
     267      cur = &sentinel;
     268      pai = &ai;
     269      pai->ai_flags = 0;
     270      pai->ai_family = PF_UNSPEC;
     271      pai->ai_socktype = GAI_ANY;
     272      pai->ai_protocol = GAI_ANY;
     273      pai->ai_addrlen = 0;
     274      pai->ai_canonname = NULL;
     275      pai->ai_addr = NULL;
     276      pai->ai_next = NULL;
     277      port = GAI_ANY;
     278  
     279      if (hostname == NULL && servname == NULL)
     280          return EAI_NONAME;
     281      if (hints) {
     282          /* error check for hints */
     283          if (hints->ai_addrlen || hints->ai_canonname ||
     284              hints->ai_addr || hints->ai_next)
     285              ERR(EAI_BADHINTS); /* xxx */
     286          if (hints->ai_flags & ~AI_MASK)
     287              ERR(EAI_BADFLAGS);
     288          switch (hints->ai_family) {
     289          case PF_UNSPEC:
     290          case PF_INET:
     291  #ifdef ENABLE_IPV6
     292          case PF_INET6:
     293  #endif
     294              break;
     295          default:
     296              ERR(EAI_FAMILY);
     297          }
     298          memcpy(pai, hints, sizeof(*pai));
     299          switch (pai->ai_socktype) {
     300          case GAI_ANY:
     301              switch (pai->ai_protocol) {
     302              case GAI_ANY:
     303                  break;
     304              case IPPROTO_UDP:
     305                  pai->ai_socktype = SOCK_DGRAM;
     306                  break;
     307              case IPPROTO_TCP:
     308                  pai->ai_socktype = SOCK_STREAM;
     309                  break;
     310              default:
     311                  pai->ai_socktype = SOCK_RAW;
     312                  break;
     313              }
     314              break;
     315          case SOCK_RAW:
     316              break;
     317          case SOCK_DGRAM:
     318              if (pai->ai_protocol != IPPROTO_UDP &&
     319                  pai->ai_protocol != GAI_ANY)
     320                  ERR(EAI_BADHINTS);                      /*xxx*/
     321              pai->ai_protocol = IPPROTO_UDP;
     322              break;
     323          case SOCK_STREAM:
     324              if (pai->ai_protocol != IPPROTO_TCP &&
     325                  pai->ai_protocol != GAI_ANY)
     326                  ERR(EAI_BADHINTS);                      /*xxx*/
     327              pai->ai_protocol = IPPROTO_TCP;
     328              break;
     329          default:
     330              ERR(EAI_SOCKTYPE);
     331              /* unreachable */
     332          }
     333      }
     334  
     335      /*
     336       * service port
     337       */
     338      if (servname) {
     339          if (str_isnumber(servname)) {
     340              if (pai->ai_socktype == GAI_ANY) {
     341                  /* caller accept *GAI_ANY* socktype */
     342                  pai->ai_socktype = SOCK_DGRAM;
     343                  pai->ai_protocol = IPPROTO_UDP;
     344              }
     345              port = htons((u_short)atoi(servname));
     346          } else {
     347              struct servent *sp;
     348              const char *proto;
     349  
     350              proto = NULL;
     351              switch (pai->ai_socktype) {
     352              case GAI_ANY:
     353                  proto = NULL;
     354                  break;
     355              case SOCK_DGRAM:
     356                  proto = "udp";
     357                  break;
     358              case SOCK_STREAM:
     359                  proto = "tcp";
     360                  break;
     361              default:
     362                  fprintf(stderr, "panic!\n");
     363                  break;
     364              }
     365              if ((sp = getservbyname(servname, proto)) == NULL)
     366                  ERR(EAI_SERVICE);
     367              port = sp->s_port;
     368              if (pai->ai_socktype == GAI_ANY) {
     369                  if (strcmp(sp->s_proto, "udp") == 0) {
     370                      pai->ai_socktype = SOCK_DGRAM;
     371                      pai->ai_protocol = IPPROTO_UDP;
     372                  } else if (strcmp(sp->s_proto, "tcp") == 0) {
     373                      pai->ai_socktype = SOCK_STREAM;
     374                      pai->ai_protocol = IPPROTO_TCP;
     375                  } else
     376                      ERR(EAI_PROTOCOL);                          /*xxx*/
     377              }
     378          }
     379      }
     380  
     381      /*
     382       * hostname == NULL.
     383       * passive socket -> anyaddr (0.0.0.0 or ::)
     384       * non-passive socket -> localhost (127.0.0.1 or ::1)
     385       */
     386      if (hostname == NULL) {
     387          struct gai_afd *gai_afd;
     388  
     389          for (gai_afd = &gai_afdl[0]; gai_afd->a_af; gai_afd++) {
     390              if (!(pai->ai_family == PF_UNSPEC
     391                 || pai->ai_family == gai_afd->a_af)) {
     392                  continue;
     393              }
     394  
     395              if (pai->ai_flags & AI_PASSIVE) {
     396                  GET_AI(cur->ai_next, gai_afd, gai_afd->a_addrany, port);
     397                  /* xxx meaningless?
     398                   * GET_CANONNAME(cur->ai_next, "anyaddr");
     399                   */
     400              } else {
     401                  GET_AI(cur->ai_next, gai_afd, gai_afd->a_loopback,
     402                      port);
     403                  /* xxx meaningless?
     404                   * GET_CANONNAME(cur->ai_next, "localhost");
     405                   */
     406              }
     407              cur = cur->ai_next;
     408          }
     409          top = sentinel.ai_next;
     410          if (top)
     411              goto good;
     412          else
     413              ERR(EAI_FAMILY);
     414      }
     415  
     416      /* hostname as numeric name */
     417      for (i = 0; gai_afdl[i].a_af; i++) {
     418          if (inet_pton(gai_afdl[i].a_af, hostname, pton)) {
     419              u_long v4a;
     420  #ifdef ENABLE_IPV6
     421              u_char pfx;
     422  #endif
     423  
     424              switch (gai_afdl[i].a_af) {
     425              case AF_INET:
     426                  v4a = ((struct in_addr *)pton)->s_addr;
     427                  v4a = ntohl(v4a);
     428                  if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
     429                      pai->ai_flags &= ~AI_CANONNAME;
     430                  v4a >>= IN_CLASSA_NSHIFT;
     431                  if (v4a == 0 || v4a == IN_LOOPBACKNET)
     432                      pai->ai_flags &= ~AI_CANONNAME;
     433                  break;
     434  #ifdef ENABLE_IPV6
     435              case AF_INET6:
     436                  pfx = ((struct in6_addr *)pton)->s6_addr[0];
     437                  if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
     438                      pai->ai_flags &= ~AI_CANONNAME;
     439                  break;
     440  #endif
     441              }
     442  
     443              if (pai->ai_family == gai_afdl[i].a_af ||
     444                  pai->ai_family == PF_UNSPEC) {
     445                  if (! (pai->ai_flags & AI_CANONNAME)) {
     446                      GET_AI(top, &gai_afdl[i], pton, port);
     447                      goto good;
     448                  }
     449                  /*
     450                   * if AI_CANONNAME and if reverse lookup
     451                   * fail, return ai anyway to pacify
     452                   * calling application.
     453                   *
     454                   * XXX getaddrinfo() is a name->address
     455                   * translation function, and it looks strange
     456                   * that we do addr->name translation here.
     457                   */
     458                  get_name(pton, &gai_afdl[i], &top, pton, pai, port);
     459                  goto good;
     460              } else
     461                  ERR(EAI_FAMILY);                        /*xxx*/
     462          }
     463      }
     464  
     465      if (pai->ai_flags & AI_NUMERICHOST)
     466          ERR(EAI_NONAME);
     467  
     468      /* hostname as alphabetical name */
     469      error = get_addr(hostname, pai->ai_family, &top, pai, port);
     470      if (error == 0) {
     471          if (top) {
     472   good:
     473              *res = top;
     474              return SUCCESS;
     475          } else
     476              error = EAI_FAIL;
     477      }
     478   free:
     479      if (top)
     480          freeaddrinfo(top);
     481   bad:
     482      *res = NULL;
     483      return error;
     484  }
     485  
     486  static int
     487  get_name(addr, gai_afd, res, numaddr, pai, port0)
     488      const char *addr;
     489      struct gai_afd *gai_afd;
     490      struct addrinfo **res;
     491      char *numaddr;
     492      struct addrinfo *pai;
     493      int port0;
     494  {
     495      u_short port = port0 & 0xffff;
     496      struct hostent *hp;
     497      struct addrinfo *cur;
     498      int error = 0;
     499  #ifdef ENABLE_IPV6
     500      int h_error;
     501  #endif
     502  
     503  #ifdef ENABLE_IPV6
     504      hp = getipnodebyaddr(addr, gai_afd->a_addrlen, gai_afd->a_af, &h_error);
     505  #else
     506      hp = gethostbyaddr(addr, gai_afd->a_addrlen, AF_INET);
     507  #endif
     508      if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
     509          GET_AI(cur, gai_afd, hp->h_addr_list[0], port);
     510          GET_CANONNAME(cur, hp->h_name);
     511      } else
     512          GET_AI(cur, gai_afd, numaddr, port);
     513  
     514  #ifdef ENABLE_IPV6
     515      if (hp)
     516          freehostent(hp);
     517  #endif
     518      *res = cur;
     519      return SUCCESS;
     520   free:
     521      if (cur)
     522          freeaddrinfo(cur);
     523  #ifdef ENABLE_IPV6
     524      if (hp)
     525          freehostent(hp);
     526  #endif
     527   /* bad: */
     528      *res = NULL;
     529      return error;
     530  }
     531  
     532  static int
     533  get_addr(hostname, af, res, pai, port0)
     534      const char *hostname;
     535      int af;
     536      struct addrinfo **res;
     537      struct addrinfo *pai;
     538      int port0;
     539  {
     540      u_short port = port0 & 0xffff;
     541      struct addrinfo sentinel;
     542      struct hostent *hp;
     543      struct addrinfo *top, *cur;
     544      struct gai_afd *gai_afd;
     545      int i, error = 0, h_error;
     546      char *ap;
     547  
     548      top = NULL;
     549      sentinel.ai_next = NULL;
     550      cur = &sentinel;
     551  #ifdef ENABLE_IPV6
     552      if (af == AF_UNSPEC) {
     553          hp = getipnodebyname(hostname, AF_INET6,
     554                          AI_ADDRCONFIG|AI_ALL|AI_V4MAPPED, &h_error);
     555      } else
     556          hp = getipnodebyname(hostname, af, AI_ADDRCONFIG, &h_error);
     557  #else
     558      hp = gethostbyname(hostname);
     559      h_error = h_errno;
     560  #endif
     561      if (hp == NULL) {
     562          switch (h_error) {
     563          case HOST_NOT_FOUND:
     564          case NO_DATA:
     565              error = EAI_NODATA;
     566              break;
     567          case TRY_AGAIN:
     568              error = EAI_AGAIN;
     569              break;
     570          case NO_RECOVERY:
     571          default:
     572              error = EAI_FAIL;
     573              break;
     574          }
     575          goto free;
     576      }
     577  
     578      if ((hp->h_name == NULL) || (hp->h_name[0] == 0) ||
     579          (hp->h_addr_list[0] == NULL)) {
     580          error = EAI_FAIL;
     581          goto free;
     582      }
     583  
     584      for (i = 0; (ap = hp->h_addr_list[i]) != NULL; i++) {
     585          switch (af) {
     586  #ifdef ENABLE_IPV6
     587          case AF_INET6:
     588              gai_afd = &gai_afdl[N_INET6];
     589              break;
     590  #endif
     591  #ifndef ENABLE_IPV6
     592          default:                /* AF_UNSPEC */
     593  #endif
     594          case AF_INET:
     595              gai_afd = &gai_afdl[N_INET];
     596              break;
     597  #ifdef ENABLE_IPV6
     598          default:                /* AF_UNSPEC */
     599              if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
     600                  ap += sizeof(struct in6_addr) -
     601                      sizeof(struct in_addr);
     602                  gai_afd = &gai_afdl[N_INET];
     603              } else
     604                  gai_afd = &gai_afdl[N_INET6];
     605              break;
     606  #endif
     607          }
     608  #ifdef FAITH
     609          if (translate && gai_afd->a_af == AF_INET) {
     610              struct in6_addr *in6;
     611  
     612              GET_AI(cur->ai_next, &gai_afdl[N_INET6], ap, port);
     613              in6 = &((struct sockaddr_in6 *)cur->ai_next->ai_addr)->sin6_addr;
     614              memcpy(&in6->s6_addr32[0], &faith_prefix,
     615                  sizeof(struct in6_addr) - sizeof(struct in_addr));
     616              memcpy(&in6->s6_addr32[3], ap, sizeof(struct in_addr));
     617          } else
     618  #endif /* FAITH */
     619          GET_AI(cur->ai_next, gai_afd, ap, port);
     620          if (cur == &sentinel) {
     621              top = cur->ai_next;
     622              GET_CANONNAME(top, hp->h_name);
     623          }
     624          cur = cur->ai_next;
     625      }
     626  #ifdef ENABLE_IPV6
     627      freehostent(hp);
     628  #endif
     629      *res = top;
     630      return SUCCESS;
     631   free:
     632      if (top)
     633          freeaddrinfo(top);
     634  #ifdef ENABLE_IPV6
     635      if (hp)
     636          freehostent(hp);
     637  #endif
     638  /* bad: */
     639      *res = NULL;
     640      return error;
     641  }
     642  
     643  #endif // HAVE_NETDB_H