Home | History | Annotate | Download | only in Modules
      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 #define SUCCESS 0
     65 #define GAI_ANY 0
     66 #define YES 1
     67 #define NO  0
     68 
     69 #ifdef FAITH
     70 static int translate = NO;
     71 static struct in6_addr faith_prefix = IN6ADDR_GAI_ANY_INIT;
     72 #endif
     73 
     74 static const char in_addrany[] = { 0, 0, 0, 0 };
     75 static const char in6_addrany[] = {
     76     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     77 };
     78 static const char in_loopback[] = { 127, 0, 0, 1 };
     79 static const char in6_loopback[] = {
     80     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
     81 };
     82 
     83 struct sockinet {
     84     u_char      si_len;
     85     u_char      si_family;
     86     u_short     si_port;
     87 };
     88 
     89 static struct gai_afd {
     90     int a_af;
     91     int a_addrlen;
     92     int a_socklen;
     93     int a_off;
     94     const char *a_addrany;
     95     const char *a_loopback;
     96 } gai_afdl [] = {
     97 #ifdef ENABLE_IPV6
     98 #define N_INET6 0
     99     {PF_INET6, sizeof(struct in6_addr),
    100      sizeof(struct sockaddr_in6),
    101      offsetof(struct sockaddr_in6, sin6_addr),
    102      in6_addrany, in6_loopback},
    103 #define N_INET  1
    104 #else
    105 #define N_INET  0
    106 #endif
    107     {PF_INET, sizeof(struct in_addr),
    108      sizeof(struct sockaddr_in),
    109      offsetof(struct sockaddr_in, sin_addr),
    110      in_addrany, in_loopback},
    111     {0, 0, 0, 0, NULL, NULL},
    112 };
    113 
    114 #ifdef ENABLE_IPV6
    115 #define PTON_MAX        16
    116 #else
    117 #define PTON_MAX        4
    118 #endif
    119 
    120 #ifndef IN_MULTICAST
    121 #define IN_MULTICAST(i)     (((i) & 0xf0000000U) == 0xe0000000U)
    122 #endif
    123 
    124 #ifndef IN_EXPERIMENTAL
    125 #define IN_EXPERIMENTAL(i)  (((i) & 0xe0000000U) == 0xe0000000U)
    126 #endif
    127 
    128 #ifndef IN_LOOPBACKNET
    129 #define IN_LOOPBACKNET      127
    130 #endif
    131 
    132 static int get_name(const char *, struct gai_afd *,
    133                           struct addrinfo **, char *, struct addrinfo *,
    134                           int);
    135 static int get_addr(const char *, int, struct addrinfo **,
    136                         struct addrinfo *, int);
    137 static int str_isnumber(const char *);
    138 
    139 static const char * const ai_errlist[] = {
    140     "success.",
    141     "address family for hostname not supported.",       /* EAI_ADDRFAMILY */
    142     "temporary failure in name resolution.",            /* EAI_AGAIN      */
    143     "invalid value for ai_flags.",                      /* EAI_BADFLAGS   */
    144     "non-recoverable failure in name resolution.",      /* EAI_FAIL       */
    145     "ai_family not supported.",                         /* EAI_FAMILY     */
    146     "memory allocation failure.",                       /* EAI_MEMORY     */
    147     "no address associated with hostname.",             /* EAI_NODATA     */
    148     "hostname nor servname provided, or not known.",/* EAI_NONAME     */
    149     "servname not supported for ai_socktype.",          /* EAI_SERVICE    */
    150     "ai_socktype not supported.",                       /* EAI_SOCKTYPE   */
    151     "system error returned in errno.",                  /* EAI_SYSTEM     */
    152     "invalid value for hints.",                         /* EAI_BADHINTS   */
    153     "resolved protocol is unknown.",                    /* EAI_PROTOCOL   */
    154     "unknown error.",                                   /* EAI_MAX        */
    155 };
    156 
    157 #define GET_CANONNAME(ai, str) \
    158 if (pai->ai_flags & AI_CANONNAME) {\
    159     if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\
    160         strcpy((ai)->ai_canonname, (str));\
    161     } else {\
    162         error = EAI_MEMORY;\
    163         goto free;\
    164     }\
    165 }
    166 
    167 #ifdef HAVE_SOCKADDR_SA_LEN
    168 #define GET_AI(ai, gai_afd, addr, port) {\
    169     char *p;\
    170     if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\
    171                                           ((gai_afd)->a_socklen)))\
    172         == NULL) goto free;\
    173     memcpy(ai, pai, sizeof(struct addrinfo));\
    174     (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\
    175     memset((ai)->ai_addr, 0, (gai_afd)->a_socklen);\
    176     (ai)->ai_addr->sa_len = (ai)->ai_addrlen = (gai_afd)->a_socklen;\
    177     (ai)->ai_addr->sa_family = (ai)->ai_family = (gai_afd)->a_af;\
    178     ((struct sockinet *)(ai)->ai_addr)->si_port = port;\
    179     p = (char *)((ai)->ai_addr);\
    180     memcpy(p + (gai_afd)->a_off, (addr), (gai_afd)->a_addrlen);\
    181 }
    182 #else
    183 #define GET_AI(ai, gai_afd, addr, port) {\
    184     char *p;\
    185     if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\
    186                                           ((gai_afd)->a_socklen)))\
    187         == NULL) goto free;\
    188     memcpy(ai, pai, sizeof(struct addrinfo));\
    189     (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\
    190     memset((ai)->ai_addr, 0, (gai_afd)->a_socklen);\
    191     (ai)->ai_addrlen = (gai_afd)->a_socklen;\
    192     (ai)->ai_addr->sa_family = (ai)->ai_family = (gai_afd)->a_af;\
    193     ((struct sockinet *)(ai)->ai_addr)->si_port = port;\
    194     p = (char *)((ai)->ai_addr);\
    195     memcpy(p + (gai_afd)->a_off, (addr), (gai_afd)->a_addrlen);\
    196 }
    197 #endif
    198 
    199 #define ERR(err) { error = (err); goto bad; }
    200 
    201 const char *
    202 gai_strerror(int ecode)
    203 {
    204     if (ecode < 0 || ecode > EAI_MAX)
    205         ecode = EAI_MAX;
    206     return ai_errlist[ecode];
    207 }
    208 
    209 void
    210 freeaddrinfo(struct addrinfo *ai)
    211 {
    212     struct addrinfo *next;
    213 
    214     do {
    215         next = ai->ai_next;
    216         if (ai->ai_canonname)
    217             free(ai->ai_canonname);
    218         /* no need to free(ai->ai_addr) */
    219         free(ai);
    220     } while ((ai = next) != NULL);
    221 }
    222 
    223 static int
    224 str_isnumber(const char *p)
    225 {
    226     unsigned char *q = (unsigned char *)p;
    227     while (*q) {
    228         if (! isdigit(*q))
    229             return NO;
    230         q++;
    231     }
    232     return YES;
    233 }
    234 
    235 int
    236 getaddrinfo(const char*hostname, const char*servname,
    237             const struct addrinfo *hints, struct addrinfo **res)
    238 {
    239     struct addrinfo sentinel;
    240     struct addrinfo *top = NULL;
    241     struct addrinfo *cur;
    242     int i, error = 0;
    243     char pton[PTON_MAX];
    244     struct addrinfo ai;
    245     struct addrinfo *pai;
    246     u_short port;
    247 
    248 #ifdef FAITH
    249     static int firsttime = 1;
    250 
    251     if (firsttime) {
    252         /* translator hack */
    253         {
    254             char *q = getenv("GAI");
    255             if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1)
    256                 translate = YES;
    257         }
    258         firsttime = 0;
    259     }
    260 #endif
    261 
    262     /* initialize file static vars */
    263     sentinel.ai_next = NULL;
    264     cur = &sentinel;
    265     pai = &ai;
    266     pai->ai_flags = 0;
    267     pai->ai_family = PF_UNSPEC;
    268     pai->ai_socktype = GAI_ANY;
    269     pai->ai_protocol = GAI_ANY;
    270     pai->ai_addrlen = 0;
    271     pai->ai_canonname = NULL;
    272     pai->ai_addr = NULL;
    273     pai->ai_next = NULL;
    274     port = GAI_ANY;
    275 
    276     if (hostname == NULL && servname == NULL)
    277         return EAI_NONAME;
    278     if (hints) {
    279         /* error check for hints */
    280         if (hints->ai_addrlen || hints->ai_canonname ||
    281             hints->ai_addr || hints->ai_next)
    282             ERR(EAI_BADHINTS); /* xxx */
    283         if (hints->ai_flags & ~AI_MASK)
    284             ERR(EAI_BADFLAGS);
    285         switch (hints->ai_family) {
    286         case PF_UNSPEC:
    287         case PF_INET:
    288 #ifdef ENABLE_IPV6
    289         case PF_INET6:
    290 #endif
    291             break;
    292         default:
    293             ERR(EAI_FAMILY);
    294         }
    295         memcpy(pai, hints, sizeof(*pai));
    296         switch (pai->ai_socktype) {
    297         case GAI_ANY:
    298             switch (pai->ai_protocol) {
    299             case GAI_ANY:
    300                 break;
    301             case IPPROTO_UDP:
    302                 pai->ai_socktype = SOCK_DGRAM;
    303                 break;
    304             case IPPROTO_TCP:
    305                 pai->ai_socktype = SOCK_STREAM;
    306                 break;
    307             default:
    308                 pai->ai_socktype = SOCK_RAW;
    309                 break;
    310             }
    311             break;
    312         case SOCK_RAW:
    313             break;
    314         case SOCK_DGRAM:
    315             if (pai->ai_protocol != IPPROTO_UDP &&
    316                 pai->ai_protocol != GAI_ANY)
    317                 ERR(EAI_BADHINTS);                      /*xxx*/
    318             pai->ai_protocol = IPPROTO_UDP;
    319             break;
    320         case SOCK_STREAM:
    321             if (pai->ai_protocol != IPPROTO_TCP &&
    322                 pai->ai_protocol != GAI_ANY)
    323                 ERR(EAI_BADHINTS);                      /*xxx*/
    324             pai->ai_protocol = IPPROTO_TCP;
    325             break;
    326         default:
    327             ERR(EAI_SOCKTYPE);
    328             /* unreachable */
    329         }
    330     }
    331 
    332     /*
    333      * service port
    334      */
    335     if (servname) {
    336         if (str_isnumber(servname)) {
    337             if (pai->ai_socktype == GAI_ANY) {
    338                 /* caller accept *GAI_ANY* socktype */
    339                 pai->ai_socktype = SOCK_DGRAM;
    340                 pai->ai_protocol = IPPROTO_UDP;
    341             }
    342             port = htons((u_short)atoi(servname));
    343         } else {
    344             struct servent *sp;
    345             char *proto;
    346 
    347             proto = NULL;
    348             switch (pai->ai_socktype) {
    349             case GAI_ANY:
    350                 proto = NULL;
    351                 break;
    352             case SOCK_DGRAM:
    353                 proto = "udp";
    354                 break;
    355             case SOCK_STREAM:
    356                 proto = "tcp";
    357                 break;
    358             default:
    359                 fprintf(stderr, "panic!\n");
    360                 break;
    361             }
    362             if ((sp = getservbyname(servname, proto)) == NULL)
    363                 ERR(EAI_SERVICE);
    364             port = sp->s_port;
    365             if (pai->ai_socktype == GAI_ANY) {
    366                 if (strcmp(sp->s_proto, "udp") == 0) {
    367                     pai->ai_socktype = SOCK_DGRAM;
    368                     pai->ai_protocol = IPPROTO_UDP;
    369                 } else if (strcmp(sp->s_proto, "tcp") == 0) {
    370                     pai->ai_socktype = SOCK_STREAM;
    371                     pai->ai_protocol = IPPROTO_TCP;
    372                 } else
    373                     ERR(EAI_PROTOCOL);                          /*xxx*/
    374             }
    375         }
    376     }
    377 
    378     /*
    379      * hostname == NULL.
    380      * passive socket -> anyaddr (0.0.0.0 or ::)
    381      * non-passive socket -> localhost (127.0.0.1 or ::1)
    382      */
    383     if (hostname == NULL) {
    384         struct gai_afd *gai_afd;
    385 
    386         for (gai_afd = &gai_afdl[0]; gai_afd->a_af; gai_afd++) {
    387             if (!(pai->ai_family == PF_UNSPEC
    388                || pai->ai_family == gai_afd->a_af)) {
    389                 continue;
    390             }
    391 
    392             if (pai->ai_flags & AI_PASSIVE) {
    393                 GET_AI(cur->ai_next, gai_afd, gai_afd->a_addrany, port);
    394                 /* xxx meaningless?
    395                  * GET_CANONNAME(cur->ai_next, "anyaddr");
    396                  */
    397             } else {
    398                 GET_AI(cur->ai_next, gai_afd, gai_afd->a_loopback,
    399                     port);
    400                 /* xxx meaningless?
    401                  * GET_CANONNAME(cur->ai_next, "localhost");
    402                  */
    403             }
    404             cur = cur->ai_next;
    405         }
    406         top = sentinel.ai_next;
    407         if (top)
    408             goto good;
    409         else
    410             ERR(EAI_FAMILY);
    411     }
    412 
    413     /* hostname as numeric name */
    414     for (i = 0; gai_afdl[i].a_af; i++) {
    415         if (inet_pton(gai_afdl[i].a_af, hostname, pton)) {
    416             u_long v4a;
    417 #ifdef ENABLE_IPV6
    418             u_char pfx;
    419 #endif
    420 
    421             switch (gai_afdl[i].a_af) {
    422             case AF_INET:
    423                 v4a = ((struct in_addr *)pton)->s_addr;
    424                 v4a = ntohl(v4a);
    425                 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
    426                     pai->ai_flags &= ~AI_CANONNAME;
    427                 v4a >>= IN_CLASSA_NSHIFT;
    428                 if (v4a == 0 || v4a == IN_LOOPBACKNET)
    429                     pai->ai_flags &= ~AI_CANONNAME;
    430                 break;
    431 #ifdef ENABLE_IPV6
    432             case AF_INET6:
    433                 pfx = ((struct in6_addr *)pton)->s6_addr[0];
    434                 if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
    435                     pai->ai_flags &= ~AI_CANONNAME;
    436                 break;
    437 #endif
    438             }
    439 
    440             if (pai->ai_family == gai_afdl[i].a_af ||
    441                 pai->ai_family == PF_UNSPEC) {
    442                 if (! (pai->ai_flags & AI_CANONNAME)) {
    443                     GET_AI(top, &gai_afdl[i], pton, port);
    444                     goto good;
    445                 }
    446                 /*
    447                  * if AI_CANONNAME and if reverse lookup
    448                  * fail, return ai anyway to pacify
    449                  * calling application.
    450                  *
    451                  * XXX getaddrinfo() is a name->address
    452                  * translation function, and it looks strange
    453                  * that we do addr->name translation here.
    454                  */
    455                 get_name(pton, &gai_afdl[i], &top, pton, pai, port);
    456                 goto good;
    457             } else
    458                 ERR(EAI_FAMILY);                        /*xxx*/
    459         }
    460     }
    461 
    462     if (pai->ai_flags & AI_NUMERICHOST)
    463         ERR(EAI_NONAME);
    464 
    465     /* hostname as alphabetical name */
    466     error = get_addr(hostname, pai->ai_family, &top, pai, port);
    467     if (error == 0) {
    468         if (top) {
    469  good:
    470             *res = top;
    471             return SUCCESS;
    472         } else
    473             error = EAI_FAIL;
    474     }
    475  free:
    476     if (top)
    477         freeaddrinfo(top);
    478  bad:
    479     *res = NULL;
    480     return error;
    481 }
    482 
    483 static int
    484 get_name(addr, gai_afd, res, numaddr, pai, port0)
    485     const char *addr;
    486     struct gai_afd *gai_afd;
    487     struct addrinfo **res;
    488     char *numaddr;
    489     struct addrinfo *pai;
    490     int port0;
    491 {
    492     u_short port = port0 & 0xffff;
    493     struct hostent *hp;
    494     struct addrinfo *cur;
    495     int error = 0;
    496 #ifdef ENABLE_IPV6
    497     int h_error;
    498 #endif
    499 
    500 #ifdef ENABLE_IPV6
    501     hp = getipnodebyaddr(addr, gai_afd->a_addrlen, gai_afd->a_af, &h_error);
    502 #else
    503     hp = gethostbyaddr(addr, gai_afd->a_addrlen, AF_INET);
    504 #endif
    505     if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
    506         GET_AI(cur, gai_afd, hp->h_addr_list[0], port);
    507         GET_CANONNAME(cur, hp->h_name);
    508     } else
    509         GET_AI(cur, gai_afd, numaddr, port);
    510 
    511 #ifdef ENABLE_IPV6
    512     if (hp)
    513         freehostent(hp);
    514 #endif
    515     *res = cur;
    516     return SUCCESS;
    517  free:
    518     if (cur)
    519         freeaddrinfo(cur);
    520 #ifdef ENABLE_IPV6
    521     if (hp)
    522         freehostent(hp);
    523 #endif
    524  /* bad: */
    525     *res = NULL;
    526     return error;
    527 }
    528 
    529 static int
    530 get_addr(hostname, af, res, pai, port0)
    531     const char *hostname;
    532     int af;
    533     struct addrinfo **res;
    534     struct addrinfo *pai;
    535     int port0;
    536 {
    537     u_short port = port0 & 0xffff;
    538     struct addrinfo sentinel;
    539     struct hostent *hp;
    540     struct addrinfo *top, *cur;
    541     struct gai_afd *gai_afd;
    542     int i, error = 0, h_error;
    543     char *ap;
    544 
    545     top = NULL;
    546     sentinel.ai_next = NULL;
    547     cur = &sentinel;
    548 #ifdef ENABLE_IPV6
    549     if (af == AF_UNSPEC) {
    550         hp = getipnodebyname(hostname, AF_INET6,
    551                         AI_ADDRCONFIG|AI_ALL|AI_V4MAPPED, &h_error);
    552     } else
    553         hp = getipnodebyname(hostname, af, AI_ADDRCONFIG, &h_error);
    554 #else
    555     hp = gethostbyname(hostname);
    556     h_error = h_errno;
    557 #endif
    558     if (hp == NULL) {
    559         switch (h_error) {
    560         case HOST_NOT_FOUND:
    561         case NO_DATA:
    562             error = EAI_NODATA;
    563             break;
    564         case TRY_AGAIN:
    565             error = EAI_AGAIN;
    566             break;
    567         case NO_RECOVERY:
    568         default:
    569             error = EAI_FAIL;
    570             break;
    571         }
    572         goto free;
    573     }
    574 
    575     if ((hp->h_name == NULL) || (hp->h_name[0] == 0) ||
    576         (hp->h_addr_list[0] == NULL)) {
    577         error = EAI_FAIL;
    578         goto free;
    579     }
    580 
    581     for (i = 0; (ap = hp->h_addr_list[i]) != NULL; i++) {
    582         switch (af) {
    583 #ifdef ENABLE_IPV6
    584         case AF_INET6:
    585             gai_afd = &gai_afdl[N_INET6];
    586             break;
    587 #endif
    588 #ifndef ENABLE_IPV6
    589         default:                /* AF_UNSPEC */
    590 #endif
    591         case AF_INET:
    592             gai_afd = &gai_afdl[N_INET];
    593             break;
    594 #ifdef ENABLE_IPV6
    595         default:                /* AF_UNSPEC */
    596             if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
    597                 ap += sizeof(struct in6_addr) -
    598                     sizeof(struct in_addr);
    599                 gai_afd = &gai_afdl[N_INET];
    600             } else
    601                 gai_afd = &gai_afdl[N_INET6];
    602             break;
    603 #endif
    604         }
    605 #ifdef FAITH
    606         if (translate && gai_afd->a_af == AF_INET) {
    607             struct in6_addr *in6;
    608 
    609             GET_AI(cur->ai_next, &gai_afdl[N_INET6], ap, port);
    610             in6 = &((struct sockaddr_in6 *)cur->ai_next->ai_addr)->sin6_addr;
    611             memcpy(&in6->s6_addr32[0], &faith_prefix,
    612                 sizeof(struct in6_addr) - sizeof(struct in_addr));
    613             memcpy(&in6->s6_addr32[3], ap, sizeof(struct in_addr));
    614         } else
    615 #endif /* FAITH */
    616         GET_AI(cur->ai_next, gai_afd, ap, port);
    617         if (cur == &sentinel) {
    618             top = cur->ai_next;
    619             GET_CANONNAME(top, hp->h_name);
    620         }
    621         cur = cur->ai_next;
    622     }
    623 #ifdef ENABLE_IPV6
    624     freehostent(hp);
    625 #endif
    626     *res = top;
    627     return SUCCESS;
    628  free:
    629     if (top)
    630         freeaddrinfo(top);
    631 #ifdef ENABLE_IPV6
    632     if (hp)
    633         freehostent(hp);
    634 #endif
    635 /* bad: */
    636     *res = NULL;
    637     return error;
    638 }
    639