ext/socket/getaddrinfo.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the project nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  */
00029 
00030 /*
00031  * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
00032  *
00033  * Issues to be discussed:
00034  * - Thread safe-ness must be checked.
00035  * - Return values.  There are nonstandard return values defined and used
00036  *   in the source code.  This is because RFC2133 is silent about which error
00037  *   code must be returned for which situation.
00038  * - PF_UNSPEC case would be handled in getipnodebyname() with the AI_ALL flag.
00039  */
00040 
00041 #include "ruby/config.h"
00042 #ifdef RUBY_EXTCONF_H
00043 #include RUBY_EXTCONF_H
00044 #endif
00045 #include <sys/types.h>
00046 #ifndef _WIN32
00047 #include <sys/param.h>
00048 #if defined(__BEOS__) && !defined(__HAIKU__) && !defined(BONE)
00049 # include <net/socket.h>
00050 #else
00051 # include <sys/socket.h>
00052 #endif
00053 #include <netinet/in.h>
00054 #if defined(HAVE_ARPA_INET_H)
00055 #include <arpa/inet.h>
00056 #endif
00057 #if defined(HAVE_ARPA_NAMESER_H)
00058 #include <arpa/nameser.h>
00059 #endif
00060 #include <netdb.h>
00061 #if defined(HAVE_RESOLV_H)
00062 #ifdef _SX
00063 #include <stdio.h>
00064 #endif
00065 #include <resolv.h>
00066 #endif
00067 #include <unistd.h>
00068 #else
00069 #include <winsock2.h>
00070 #include <ws2tcpip.h>
00071 #include <io.h>
00072 #endif
00073 #include <string.h>
00074 #include <stdio.h>
00075 #include <stdlib.h>
00076 #include <stddef.h>
00077 #include <ctype.h>
00078 
00079 #ifdef SOCKS5
00080 #include <socks.h>
00081 #endif
00082 
00083 #ifndef HAVE_TYPE_SOCKLEN_T
00084 typedef int socklen_t;
00085 #endif
00086 
00087 #include "addrinfo.h"
00088 #include "sockport.h"
00089 
00090 #define SUCCESS 0
00091 #define ANY 0
00092 #define YES 1
00093 #define NO  0
00094 
00095 #ifdef FAITH
00096 static int translate = NO;
00097 static struct in6_addr faith_prefix = IN6ADDR_ANY_INIT;
00098 #endif
00099 
00100 static const char in_addrany[] = { 0, 0, 0, 0 };
00101 static const char in6_addrany[] = {
00102         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00103 };
00104 static const char in_loopback[] = { 127, 0, 0, 1 };
00105 static const char in6_loopback[] = {
00106         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
00107 };
00108 
00109 struct sockinet {
00110         u_char  si_len;
00111         u_char  si_family;
00112         u_short si_port;
00113 };
00114 
00115 static const struct afd {
00116         int a_af;
00117         int a_addrlen;
00118         int a_socklen;
00119         int a_off;
00120         const char *a_addrany;
00121         const char *a_loopback;
00122 } afdl [] = {
00123 #ifdef INET6
00124 #define N_INET6 0
00125         {PF_INET6, sizeof(struct in6_addr),
00126          sizeof(struct sockaddr_in6),
00127          offsetof(struct sockaddr_in6, sin6_addr),
00128          in6_addrany, in6_loopback},
00129 #define N_INET  1
00130 #else
00131 #define N_INET  0
00132 #endif
00133         {PF_INET, sizeof(struct in_addr),
00134          sizeof(struct sockaddr_in),
00135          offsetof(struct sockaddr_in, sin_addr),
00136          in_addrany, in_loopback},
00137         {0, 0, 0, 0, NULL, NULL},
00138 };
00139 
00140 #ifdef INET6
00141 #define PTON_MAX        16
00142 #else
00143 #define PTON_MAX        4
00144 #endif
00145 
00146 static int get_name __P((const char *, const struct afd *,
00147                           struct addrinfo **, char *, struct addrinfo *,
00148                           int));
00149 static int get_addr __P((const char *, int, struct addrinfo **,
00150                         struct addrinfo *, int));
00151 static int str_isnumber __P((const char *));
00152 
00153 static const char *const ai_errlist[] = {
00154         "success.",
00155         "address family for hostname not supported.",   /* EAI_ADDRFAMILY */
00156         "temporary failure in name resolution.",        /* EAI_AGAIN      */
00157         "invalid value for ai_flags.",                  /* EAI_BADFLAGS   */
00158         "non-recoverable failure in name resolution.",  /* EAI_FAIL       */
00159         "ai_family not supported.",                     /* EAI_FAMILY     */
00160         "memory allocation failure.",                   /* EAI_MEMORY     */
00161         "no address associated with hostname.",         /* EAI_NODATA     */
00162         "hostname nor servname provided, or not known.",/* EAI_NONAME     */
00163         "servname not supported for ai_socktype.",      /* EAI_SERVICE    */
00164         "ai_socktype not supported.",                   /* EAI_SOCKTYPE   */
00165         "system error returned in errno.",              /* EAI_SYSTEM     */
00166         "invalid value for hints.",                     /* EAI_BADHINTS   */
00167         "resolved protocol is unknown.",                /* EAI_PROTOCOL   */
00168         "unknown error.",                               /* EAI_MAX        */
00169 };
00170 
00171 #define GET_CANONNAME(ai, str) \
00172 if (pai->ai_flags & AI_CANONNAME) {\
00173         if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\
00174                 strcpy((ai)->ai_canonname, (str));\
00175         } else {\
00176                 error = EAI_MEMORY;\
00177                 goto free;\
00178         }\
00179 }
00180 
00181 #define GET_AI(ai, afd, addr, port) {\
00182         char *p;\
00183         if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\
00184                                               ((afd)->a_socklen)))\
00185             == NULL) {\
00186                 error = EAI_MEMORY;\
00187                 goto free;\
00188         }\
00189         memcpy((ai), pai, sizeof(struct addrinfo));\
00190         (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\
00191         (ai)->ai_family = (afd)->a_af;\
00192         (ai)->ai_addrlen = (afd)->a_socklen;\
00193         INIT_SOCKADDR((ai)->ai_addr, (afd)->a_af, (afd)->a_socklen);\
00194         ((struct sockinet *)(ai)->ai_addr)->si_port = (port);\
00195         p = (char *)((ai)->ai_addr);\
00196         memcpy(p + (afd)->a_off, (addr), (afd)->a_addrlen);\
00197 }
00198 
00199 #define ERR(err) { error = (err); goto bad; }
00200 
00201 #ifndef HAVE_GAI_STRERROR
00202 #ifdef GAI_STRERROR_CONST
00203 const
00204 #endif
00205 char *
00206 gai_strerror(int ecode)
00207 {
00208         if (ecode < 0 || ecode > EAI_MAX)
00209                 ecode = EAI_MAX;
00210         return (char *)ai_errlist[ecode];
00211 }
00212 #endif
00213 
00214 void
00215 freeaddrinfo(struct addrinfo *ai)
00216 {
00217         struct addrinfo *next;
00218 
00219         do {
00220                 next = ai->ai_next;
00221                 if (ai->ai_canonname)
00222                         free(ai->ai_canonname);
00223                 /* no need to free(ai->ai_addr) */
00224                 free(ai);
00225         } while ((ai = next) != NULL);
00226 }
00227 
00228 static int
00229 str_isnumber(const char *p)
00230 {
00231         char *q = (char *)p;
00232         while (*q) {
00233                 if (! isdigit(*q))
00234                         return NO;
00235                 q++;
00236         }
00237         return YES;
00238 }
00239 
00240 #ifndef HAVE_INET_PTON
00241 
00242 static int
00243 inet_pton(int af, const char *hostname, void *pton)
00244 {
00245         struct in_addr in;
00246 
00247 #ifdef HAVE_INET_ATON
00248         if (!inet_aton(hostname, &in))
00249             return 0;
00250 #else
00251         int d1, d2, d3, d4;
00252         char ch;
00253 
00254         if (sscanf(hostname, "%d.%d.%d.%d%c", &d1, &d2, &d3, &d4, &ch) == 4 &&
00255             0 <= d1 && d1 <= 255 && 0 <= d2 && d2 <= 255 &&
00256             0 <= d3 && d3 <= 255 && 0 <= d4 && d4 <= 255) {
00257             in.s_addr = htonl(
00258                 ((long) d1 << 24) | ((long) d2 << 16) |
00259                 ((long) d3 << 8) | ((long) d4 << 0));
00260         }
00261         else {
00262             return 0;
00263         }
00264 #endif
00265         memcpy(pton, &in, sizeof(in));
00266         return 1;
00267 }
00268 #endif
00269 
00270 int
00271 getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res)
00272 {
00273         struct addrinfo sentinel;
00274         struct addrinfo *top = NULL;
00275         struct addrinfo *cur;
00276         int i, error = 0;
00277         char pton[PTON_MAX];
00278         struct addrinfo ai;
00279         struct addrinfo *pai;
00280         u_short port;
00281 
00282 #ifdef FAITH
00283         static int firsttime = 1;
00284 
00285         if (firsttime) {
00286                 /* translator hack */
00287                 {
00288                         char *q = getenv("GAI");
00289                         if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1)
00290                                 translate = YES;
00291                 }
00292                 firsttime = 0;
00293         }
00294 #endif
00295 
00296         /* initialize file static vars */
00297         sentinel.ai_next = NULL;
00298         cur = &sentinel;
00299         pai = &ai;
00300         pai->ai_flags = 0;
00301         pai->ai_family = PF_UNSPEC;
00302         pai->ai_socktype = ANY;
00303         pai->ai_protocol = ANY;
00304         pai->ai_addrlen = 0;
00305         pai->ai_canonname = NULL;
00306         pai->ai_addr = NULL;
00307         pai->ai_next = NULL;
00308         port = ANY;
00309 
00310         if (hostname == NULL && servname == NULL)
00311                 return EAI_NONAME;
00312         if (hints) {
00313                 /* error check for hints */
00314                 if (hints->ai_addrlen || hints->ai_canonname ||
00315                     hints->ai_addr || hints->ai_next)
00316                         ERR(EAI_BADHINTS); /* xxx */
00317                 if (hints->ai_flags & ~AI_MASK)
00318                         ERR(EAI_BADFLAGS);
00319                 switch (hints->ai_family) {
00320                 case PF_UNSPEC:
00321                 case PF_INET:
00322 #ifdef INET6
00323                 case PF_INET6:
00324 #endif
00325                         break;
00326                 default:
00327                         ERR(EAI_FAMILY);
00328                 }
00329                 memcpy(pai, hints, sizeof(*pai));
00330                 switch (pai->ai_socktype) {
00331                 case ANY:
00332                         switch (pai->ai_protocol) {
00333                         case ANY:
00334                                 break;
00335                         case IPPROTO_UDP:
00336                                 pai->ai_socktype = SOCK_DGRAM;
00337                                 break;
00338                         case IPPROTO_TCP:
00339                                 pai->ai_socktype = SOCK_STREAM;
00340                                 break;
00341                         default:
00342 #if defined(SOCK_RAW)
00343                                 pai->ai_socktype = SOCK_RAW;
00344 #endif
00345                                 break;
00346                         }
00347                         break;
00348 #if defined(SOCK_RAW)
00349                 case SOCK_RAW:
00350                         break;
00351 #endif
00352                 case SOCK_DGRAM:
00353                         if (pai->ai_protocol != IPPROTO_UDP &&
00354                             pai->ai_protocol != ANY)
00355                                 ERR(EAI_BADHINTS);      /*xxx*/
00356                         pai->ai_protocol = IPPROTO_UDP;
00357                         break;
00358                 case SOCK_STREAM:
00359                         if (pai->ai_protocol != IPPROTO_TCP &&
00360                             pai->ai_protocol != ANY)
00361                                 ERR(EAI_BADHINTS);      /*xxx*/
00362                         pai->ai_protocol = IPPROTO_TCP;
00363                         break;
00364                 default:
00365                         ERR(EAI_SOCKTYPE);
00366                         break;
00367                 }
00368         }
00369 
00370         /*
00371          * service port
00372          */
00373         if (servname) {
00374                 if (str_isnumber(servname)) {
00375                         if (pai->ai_socktype == ANY) {
00376                                 /* caller accept *ANY* socktype */
00377                                 pai->ai_socktype = SOCK_DGRAM;
00378                                 pai->ai_protocol = IPPROTO_UDP;
00379                         }
00380                         port = htons((unsigned short)atoi(servname));
00381                 } else if (pai->ai_flags & AI_NUMERICSERV) {
00382                         ERR(EAI_NONAME);
00383                 } else {
00384                         struct servent *sp;
00385                         const char *proto;
00386 
00387                         proto = NULL;
00388                         switch (pai->ai_socktype) {
00389                         case ANY:
00390                                 proto = NULL;
00391                                 break;
00392                         case SOCK_DGRAM:
00393                                 proto = "udp";
00394                                 break;
00395                         case SOCK_STREAM:
00396                                 proto = "tcp";
00397                                 break;
00398                         default:
00399                                 fprintf(stderr, "panic!\n");
00400                                 break;
00401                         }
00402                         if ((sp = getservbyname((char*)servname, proto)) == NULL)
00403                                 ERR(EAI_SERVICE);
00404                         port = sp->s_port;
00405                         if (pai->ai_socktype == ANY)
00406                                 if (strcmp(sp->s_proto, "udp") == 0) {
00407                                         pai->ai_socktype = SOCK_DGRAM;
00408                                         pai->ai_protocol = IPPROTO_UDP;
00409                                 } else if (strcmp(sp->s_proto, "tcp") == 0) {
00410                                         pai->ai_socktype = SOCK_STREAM;
00411                                         pai->ai_protocol = IPPROTO_TCP;
00412                                 } else
00413                                         ERR(EAI_PROTOCOL);      /*xxx*/
00414                 }
00415         }
00416 
00417         /*
00418          * hostname == NULL.
00419          * passive socket -> anyaddr (0.0.0.0 or ::)
00420          * non-passive socket -> localhost (127.0.0.1 or ::1)
00421          */
00422         if (hostname == NULL) {
00423                 const struct afd *afd;
00424                 int s;
00425 
00426                 for (afd = &afdl[0]; afd->a_af; afd++) {
00427                         if (!(pai->ai_family == PF_UNSPEC
00428                            || pai->ai_family == afd->a_af)) {
00429                                 continue;
00430                         }
00431 
00432                         /*
00433                          * filter out AFs that are not supported by the kernel
00434                          * XXX errno?
00435                          */
00436                         s = socket(afd->a_af, SOCK_DGRAM, 0);
00437                         if (s < 0)
00438                                 continue;
00439 #if defined(__BEOS__)
00440                         closesocket(s);
00441 #else
00442                         close(s);
00443 #endif
00444 
00445                         if (pai->ai_flags & AI_PASSIVE) {
00446                                 GET_AI(cur->ai_next, afd, afd->a_addrany, port);
00447                                 /* xxx meaningless?
00448                                  * GET_CANONNAME(cur->ai_next, "anyaddr");
00449                                  */
00450                         } else {
00451                                 GET_AI(cur->ai_next, afd, afd->a_loopback,
00452                                         port);
00453                                 /* xxx meaningless?
00454                                  * GET_CANONNAME(cur->ai_next, "localhost");
00455                                  */
00456                         }
00457                         cur = cur->ai_next;
00458                 }
00459                 top = sentinel.ai_next;
00460                 if (top)
00461                         goto good;
00462                 else
00463                         ERR(EAI_FAMILY);
00464         }
00465 
00466         /* hostname as numeric name */
00467         for (i = 0; afdl[i].a_af; i++) {
00468                 if (inet_pton(afdl[i].a_af, hostname, pton)) {
00469                         u_long v4a;
00470 #ifdef INET6
00471                         u_char pfx;
00472 #endif
00473 
00474                         switch (afdl[i].a_af) {
00475                         case AF_INET:
00476                                 v4a = ((struct in_addr *)pton)->s_addr;
00477                                 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
00478                                         pai->ai_flags &= ~AI_CANONNAME;
00479                                 v4a >>= IN_CLASSA_NSHIFT;
00480                                 if (v4a == 0 || v4a == IN_LOOPBACKNET)
00481                                         pai->ai_flags &= ~AI_CANONNAME;
00482                                 break;
00483 #ifdef INET6
00484                         case AF_INET6:
00485                                 pfx = ((struct in6_addr *)pton)->s6_addr[0];
00486                                 if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
00487                                         pai->ai_flags &= ~AI_CANONNAME;
00488                                 break;
00489 #endif
00490                         }
00491 
00492                         if (pai->ai_family == afdl[i].a_af ||
00493                             pai->ai_family == PF_UNSPEC) {
00494                                 if (! (pai->ai_flags & AI_CANONNAME)) {
00495                                         GET_AI(top, &afdl[i], pton, port);
00496                                         goto good;
00497                                 }
00498                                 /*
00499                                  * if AI_CANONNAME and if reverse lookup
00500                                  * fail, return ai anyway to pacify
00501                                  * calling application.
00502                                  *
00503                                  * XXX getaddrinfo() is a name->address
00504                                  * translation function, and it looks strange
00505                                  * that we do addr->name translation here.
00506                                  */
00507                                 get_name(pton, &afdl[i], &top, pton, pai, port);
00508                                 goto good;
00509                         } else
00510                                 ERR(EAI_FAMILY);        /*xxx*/
00511                 }
00512         }
00513 
00514         if (pai->ai_flags & AI_NUMERICHOST)
00515                 ERR(EAI_NONAME);
00516 
00517         /* hostname as alphabetical name */
00518         error = get_addr(hostname, pai->ai_family, &top, pai, port);
00519         if (error == 0) {
00520                 if (top) {
00521  good:
00522                         *res = top;
00523                         return SUCCESS;
00524                 } else
00525                         error = EAI_FAIL;
00526         }
00527  free:
00528         if (top)
00529                 freeaddrinfo(top);
00530  bad:
00531         *res = NULL;
00532         return error;
00533 }
00534 
00535 static int
00536 get_name(const char *addr, const struct afd *afd, struct addrinfo **res, char *numaddr, struct addrinfo *pai, int port0)
00537 {
00538         u_short port = port0 & 0xffff;
00539         struct hostent *hp;
00540         struct addrinfo *cur;
00541         int error = 0;
00542 #ifdef INET6
00543         int h_error;
00544 #endif
00545 
00546 #ifdef INET6
00547         hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
00548 #else
00549         hp = gethostbyaddr((char*)addr, afd->a_addrlen, AF_INET);
00550 #endif
00551         if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
00552                 GET_AI(cur, afd, hp->h_addr_list[0], port);
00553                 GET_CANONNAME(cur, hp->h_name);
00554         } else
00555                 GET_AI(cur, afd, numaddr, port);
00556 
00557 #ifdef INET6
00558         if (hp)
00559                 freehostent(hp);
00560 #endif
00561         *res = cur;
00562         return SUCCESS;
00563  free:
00564         if (cur)
00565                 freeaddrinfo(cur);
00566 #ifdef INET6
00567         if (hp)
00568                 freehostent(hp);
00569 #endif
00570  /* bad: */
00571         *res = NULL;
00572         return error;
00573 }
00574 
00575 static int
00576 get_addr(const char *hostname, int af, struct addrinfo **res, struct addrinfo *pai, int port0)
00577 {
00578         u_short port = port0 & 0xffff;
00579         struct addrinfo sentinel;
00580         struct hostent *hp;
00581         struct addrinfo *top, *cur;
00582         const struct afd *afd;
00583         int i, error = 0, h_error;
00584         char *ap;
00585 
00586         top = NULL;
00587         sentinel.ai_next = NULL;
00588         cur = &sentinel;
00589 #ifdef INET6
00590         if (af == AF_UNSPEC) {
00591                 hp = getipnodebyname(hostname, AF_INET6,
00592                                 AI_ADDRCONFIG|AI_ALL|AI_V4MAPPED, &h_error);
00593         } else
00594                 hp = getipnodebyname(hostname, af, AI_ADDRCONFIG, &h_error);
00595 #else
00596         hp = gethostbyname((char*)hostname);
00597         h_error = h_errno;
00598 #endif
00599         if (hp == NULL) {
00600                 switch (h_error) {
00601                 case HOST_NOT_FOUND:
00602                 case NO_DATA:
00603                         error = EAI_NODATA;
00604                         break;
00605                 case TRY_AGAIN:
00606                         error = EAI_AGAIN;
00607                         break;
00608                 case NO_RECOVERY:
00609                 default:
00610                         error = EAI_FAIL;
00611                         break;
00612                 }
00613                 goto bad;
00614         }
00615 
00616         if ((hp->h_name == NULL) || (hp->h_name[0] == 0) ||
00617             (hp->h_addr_list[0] == NULL))
00618                 ERR(EAI_FAIL);
00619 
00620         for (i = 0; (ap = hp->h_addr_list[i]) != NULL; i++) {
00621                 switch (af) {
00622 #ifdef INET6
00623                 case AF_INET6:
00624                         afd = &afdl[N_INET6];
00625                         break;
00626 #endif
00627 #ifndef INET6
00628                 default:        /* AF_UNSPEC */
00629 #endif
00630                 case AF_INET:
00631                         afd = &afdl[N_INET];
00632                         break;
00633 #ifdef INET6
00634                 default:        /* AF_UNSPEC */
00635                         if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
00636                                 ap += sizeof(struct in6_addr) -
00637                                         sizeof(struct in_addr);
00638                                 afd = &afdl[N_INET];
00639                         } else
00640                                 afd = &afdl[N_INET6];
00641                         break;
00642 #endif
00643                 }
00644 #ifdef FAITH
00645                 if (translate && afd->a_af == AF_INET) {
00646                         struct in6_addr *in6;
00647 
00648                         GET_AI(cur->ai_next, &afdl[N_INET6], ap, port);
00649                         in6 = &((struct sockaddr_in6 *)cur->ai_next->ai_addr)->sin6_addr;
00650                         memcpy(&in6->s6_addr, &faith_prefix,
00651                                sizeof(struct in6_addr) - sizeof(struct in_addr));
00652                         memcpy(&in6->s6_addr + sizeof(struct in_addr), ap,
00653                                sizeof(struct in_addr));
00654                 } else
00655 #endif /* FAITH */
00656                 GET_AI(cur->ai_next, afd, ap, port);
00657                 if (cur == &sentinel) {
00658                         top = cur->ai_next;
00659                         GET_CANONNAME(top, hp->h_name);
00660                 }
00661                 cur = cur->ai_next;
00662         }
00663 #ifdef INET6
00664         freehostent(hp);
00665 #endif
00666         *res = top;
00667         return SUCCESS;
00668  free:
00669         if (top)
00670                 freeaddrinfo(top);
00671 #ifdef INET6
00672         if (hp)
00673                 freehostent(hp);
00674 #endif
00675  bad:
00676         *res = NULL;
00677         return error;
00678 }
00679 

Generated on 19 Jul 2016 for Ruby by  doxygen 1.4.7