diff options
Diffstat (limited to 'sysdeps/posix/getaddrinfo.c')
-rw-r--r-- | sysdeps/posix/getaddrinfo.c | 913 |
1 files changed, 423 insertions, 490 deletions
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c index fb9709fee7..fec30f97d7 100644 --- a/sysdeps/posix/getaddrinfo.c +++ b/sysdeps/posix/getaddrinfo.c @@ -44,92 +44,98 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* getaddrinfo() v1.13 */ -/* To do what POSIX says, even when it's broken: */ -#define BROKEN_LIKE_POSIX 1 -#define LOCAL 1 -#define INET6 1 -#define HOSTTABLE 0 -#define RESOLVER 1 - #include <sys/types.h> #include <stdlib.h> #include <unistd.h> #include <sys/socket.h> -#if LOCAL #include <stdio.h> #include <string.h> #include <sys/utsname.h> #include <sys/un.h> -#endif /* LOCAL */ #include <netinet/in.h> #include <netdb.h> #include <errno.h> #include <arpa/inet.h> -#ifndef AF_LOCAL -#define AF_LOCAL AF_UNIX -#endif /* AF_LOCAL */ -#ifndef PF_LOCAL -#define PF_LOCAL PF_UNIX -#endif /* PF_LOCAL */ -#ifndef UNIX_PATH_MAX -#define UNIX_PATH_MAX 108 -#endif /* UNIX_PATH_MAX */ - #define GAIH_OKIFUNSPEC 0x0100 #define GAIH_EAI ~(GAIH_OKIFUNSPEC) -#if HOSTTABLE -struct hostent *_hostname2addr_hosts(const char *name, int); -struct hostent *_addr2hostname_hosts(const char *name, int, int); -#endif /* HOSTTABLE */ +#ifndef UNIX_PATH_MAX +#define UNIX_PATH_MAX 108 +#endif -static struct addrinfo nullreq = -{ 0, PF_UNSPEC, 0, 0, 0, NULL, NULL, NULL }; +struct gaih_service + { + const char *name; + int num; + }; -struct gaih_service { - char *name; - int num; -}; +struct gaih_servtuple + { + struct gaih_servtuple *next; + int socktype; + int protocol; + int port; + }; -struct gaih_servtuple { - struct gaih_servtuple *next; - int socktype; - int protocol; - int port; -}; +static struct gaih_servtuple nullserv = { NULL, 0, 0, 0 }; -static struct gaih_servtuple nullserv = { - NULL, 0, 0, 0 -}; +struct gaih_addrtuple + { + struct gaih_addrtuple *next; + int family; + char addr[16]; + }; -struct gaih_addrtuple { - struct gaih_addrtuple *next; - int family; - char addr[16]; -}; +struct gaih_typeproto + { + int socktype; + int protocol; + char *name; + }; -struct gaih_typeproto { - int socktype; - int protocol; - char *name; +static struct gaih_typeproto gaih_inet_typeproto[] = +{ + { 0, 0, NULL }, + { SOCK_STREAM, IPPROTO_TCP, (char *) "tcp" }, + { SOCK_DGRAM, IPPROTO_UDP, (char *) "udp" }, + { 0, 0, NULL } }; -#if LOCAL -static int gaih_local(const char *name, const struct gaih_service *service, - const struct addrinfo *req, struct addrinfo **pai) +struct gaih + { + int family; + int (*gaih)(const char *name, const struct gaih_service *service, + const struct addrinfo *req, struct addrinfo **pai); + }; + +static struct addrinfo default_hints = + { 0, PF_UNSPEC, 0, 0, 0, NULL, NULL, NULL }; + + +static int +gaih_local (const char *name, const struct gaih_service *service, + const struct addrinfo *req, struct addrinfo **pai) { struct utsname utsname; - if (name || (req->ai_flags & AI_CANONNAME)) + if ((name != NULL) || (req->ai_flags & AI_CANONNAME)) if (uname(&utsname)) return -EAI_SYSTEM; - if (name) { - if (strcmp(name, "localhost") && strcmp(name, "local") && strcmp(name, "unix") && strcmp(name, utsname.nodename)) - return (GAIH_OKIFUNSPEC | -EAI_NONAME); - }; - if (!(*pai = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_un) + ((req->ai_flags & AI_CANONNAME) ? (strlen(utsname.nodename) + 1): 0)))) + if (name != NULL) + { + if (strcmp(name, "localhost") && + strcmp(name, "local") && + strcmp(name, "unix") && + strcmp(name, utsname.nodename)) + return GAIH_OKIFUNSPEC | -EAI_NONAME; + } + + *pai = malloc (sizeof(struct addrinfo) + sizeof(struct sockaddr_un) + + ((req->ai_flags & AI_CANONNAME) + ? (strlen(utsname.nodename) + 1): 0)); + if (*pai == NULL) return -EAI_MEMORY; (*pai)->ai_next = NULL; @@ -139,63 +145,79 @@ static int gaih_local(const char *name, const struct gaih_service *service, (*pai)->ai_protocol = req->ai_protocol; (*pai)->ai_addrlen = sizeof(struct sockaddr_un); (*pai)->ai_addr = (void *)(*pai) + sizeof(struct addrinfo); + #if SALEN - ((struct sockaddr_un *)(*pai)->ai_addr)->sun_len = sizeof(struct sockaddr_un); + ((struct sockaddr_un *) (*pai)->ai_addr)->sun_len = + sizeof (struct sockaddr_un); #endif /* SALEN */ + ((struct sockaddr_un *)(*pai)->ai_addr)->sun_family = AF_LOCAL; memset(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, 0, UNIX_PATH_MAX); - if (service) { - char *c; - if (c = strchr(service->name, '/')) { - if (strlen(service->name) >= sizeof(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path)) - return (GAIH_OKIFUNSPEC | -EAI_SERVICE); - strcpy(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, service->name); - } else { - if (strlen(P_tmpdir "/") + 1 + strlen(service->name) >= sizeof(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path)) - return (GAIH_OKIFUNSPEC | -EAI_SERVICE); - strcpy(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, P_tmpdir "/"); - strcat(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path, service->name); - }; - } else { - if (!tmpnam(((struct sockaddr_un *)(*pai)->ai_addr)->sun_path)) - return -EAI_SYSTEM; - }; + + if (service) + { + struct sockaddr_un *sunp = (struct sockaddr_un *) (*pai)->ai_addr; + + if (strchr (service->name, '/') != NULL) + { + if (strlen (service->name) >= sizeof (sunp->sun_path)) + return GAIH_OKIFUNSPEC | -EAI_SERVICE; + + strcpy (sunp->sun_path, service->name); + } + else + { + if (strlen (P_tmpdir "/") + 1 + strlen (service->name) >= + sizeof (sunp->sun_path)) + return GAIH_OKIFUNSPEC | -EAI_SERVICE; + + __stpcpy (__stpcpy (sunp->sun_path, P_tmpdir "/"), service->name); + } + } + else + { + if (tmpnam (((struct sockaddr_un *) (*pai)->ai_addr)->sun_path) == NULL) + return -EAI_SYSTEM; + } + if (req->ai_flags & AI_CANONNAME) - strcpy((*pai)->ai_canonname = (char *)(*pai) + sizeof(struct addrinfo) + sizeof(struct sockaddr_un), utsname.nodename); + strcpy ((*pai)->ai_canonname = (char *)(*pai) + sizeof(struct addrinfo) + + sizeof(struct sockaddr_un), utsname.nodename); else (*pai)->ai_canonname = NULL; return 0; -}; -#endif /* LOCAL */ - -static struct gaih_typeproto gaih_inet_typeproto[] = -{ - { 0, 0, NULL }, - { SOCK_STREAM, IPPROTO_TCP, (char *) "tcp" }, - { SOCK_DGRAM, IPPROTO_UDP, (char *) "udp" }, - { 0, 0, NULL } -}; +} -static int gaih_inet_serv(char *servicename, struct gaih_typeproto *tp, struct gaih_servtuple **st) +static int +gaih_inet_serv (const char *servicename, struct gaih_typeproto *tp, + struct gaih_servtuple **st) { struct servent *s; - int tmpbuflen = 1024; + size_t tmpbuflen = 1024; struct servent ts; - char *tmpbuf = __alloca (tmpbuflen); - while (__getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen, &s)) + char *tmpbuf; + int r; + + do { - if (errno == ERANGE) - { - tmpbuflen *= 2; - tmpbuf = __alloca (tmpbuflen); - } - else + tmpbuf = __alloca (tmpbuflen); + if (tmpbuf == NULL) + return -EAI_MEMORY; + + r = __getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen, + &s); + if (r) { - return GAIH_OKIFUNSPEC | -EAI_SERVICE; + if (errno == ERANGE) + tmpbuflen *= 2; + else + return GAIH_OKIFUNSPEC | -EAI_SERVICE; } } + while (r); - if (!(*st = malloc (sizeof (struct gaih_servtuple)))) + *st = malloc (sizeof (struct gaih_servtuple)); + if (*st == NULL) return -EAI_MEMORY; (*st)->next = NULL; @@ -206,426 +228,330 @@ static int gaih_inet_serv(char *servicename, struct gaih_typeproto *tp, struct g return 0; } -static int gaih_inet(const char *name, const struct gaih_service *service, - const struct addrinfo *req, struct addrinfo **pai) +#define gethosts(_family, _type) \ + { \ + int i, herrno; \ + size_t tmpbuflen; \ + struct hostent th; \ + char *tmpbuf; \ + tmpbuflen = 512; \ + do { \ + tmpbuflen *= 2; \ + tmpbuf = __alloca (tmpbuflen); \ + if (tmpbuf == NULL) \ + return -EAI_MEMORY; \ + rc = __gethostbyname2_r (name, _family, &th, tmpbuf, \ + tmpbuflen, &h, &herrno); \ + } while ((rc != 0) && \ + (herrno == NETDB_INTERNAL) && (errno == ERANGE)); \ + if ((rc != 0) && (herrno == NETDB_INTERNAL)) \ + { \ + __set_h_errno (herrno); \ + return -EAI_SYSTEM; \ + } \ + if (h != NULL) \ + { \ + for (i = 0; h->h_addr_list[i]; i++) \ + { \ + if (*pat == NULL) \ + { \ + *pat = __alloca (sizeof(struct gaih_addrtuple)); \ + if (*pat == NULL) \ + return -EAI_MEMORY; \ + } \ + (*pat)->next = NULL; \ + (*pat)->family = _family; \ + memcpy ((*pat)->addr, h->h_addr_list[i], \ + sizeof(_type)); \ + pat = &((*pat)->next); \ + } \ + } \ + } + +static int +gaih_inet (const char *name, const struct gaih_service *service, + const struct addrinfo *req, struct addrinfo **pai) { struct gaih_typeproto *tp = gaih_inet_typeproto; struct gaih_servtuple *st = &nullserv; struct gaih_addrtuple *at = NULL; - int i; - - if (req->ai_protocol || req->ai_socktype) { - for (tp++; tp->name && - ((req->ai_socktype != tp->socktype) || !req->ai_socktype) && - ((req->ai_protocol != tp->protocol) || !req->ai_protocol); tp++); - if (!tp->name) - if (req->ai_socktype) - return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE); - else - return (GAIH_OKIFUNSPEC | -EAI_SERVICE); - } + int rc; - if (service) { - if (service->num < 0) { - if (tp->name) { - if (i = gaih_inet_serv(service->name, tp, &st)) - return i; - } else { - struct gaih_servtuple **pst = &st; - for (tp++; tp->name; tp++) { - if (i = gaih_inet_serv(service->name, tp, pst)) { - if (i & GAIH_OKIFUNSPEC) - continue; - goto ret; - } - pst = &((*pst)->next); + if (req->ai_protocol || req->ai_socktype) + { + for (tp++; tp->name && + ((req->ai_socktype != tp->socktype) || !req->ai_socktype) && + ((req->ai_protocol != tp->protocol) || !req->ai_protocol); tp++); + if (tp->name == NULL) + if (req->ai_socktype) + return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE); + else + return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + } + + if (service != NULL) + { + if (service->num < 0) + { + if (tp->name != NULL) + { + if (rc = gaih_inet_serv (service->name, tp, &st)) + return rc; + } + else + { + struct gaih_servtuple **pst = &st; + for (tp++; tp->name; tp++) + { + if (rc = gaih_inet_serv (service->name, tp, pst)) + { + if (rc & GAIH_OKIFUNSPEC) + continue; + return rc; + } + pst = &((*pst)->next); + } + if (st == &nullserv) + return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + } } - if (st == &nullserv) { - i = (GAIH_OKIFUNSPEC | -EAI_SERVICE); - goto ret; + else + { + st = __alloca (sizeof(struct gaih_servtuple)); + if (st == NULL) + return -EAI_MEMORY; + + st->next = NULL; + st->socktype = tp->socktype; + st->protocol = tp->protocol; + st->port = htons (service->num); } - } - } else { - if (!(st = malloc(sizeof(struct gaih_servtuple)))) + } + + if (name != NULL) + { + at = __alloca (sizeof(struct gaih_addrtuple)); + if (at == NULL) return -EAI_MEMORY; - st->next = NULL; - st->socktype = tp->socktype; - st->protocol = tp->protocol; - st->port = htons(service->num); - } - } + at->family = 0; + at->next = NULL; - if (name) { - if (!(at = malloc(sizeof(struct gaih_addrtuple)))) { - i = -EAI_MEMORY; - goto ret; - } + if (at->family || !req->ai_family || (req->ai_family == AF_INET)) + if (inet_pton (AF_INET, name, at->addr) > 0) + at->family = AF_INET; - at->family = 0; - at->next = NULL; - - if (!at->family || !req->ai_family || (req->ai_family == AF_INET)) - if (inet_pton(AF_INET, name, at->addr) > 0) - at->family = AF_INET; - -#if INET6 - if (!at->family && (!req->ai_family || (req->ai_family == AF_INET6))) - if (inet_pton(AF_INET6, name, at->addr) > 0) - at->family = AF_INET6; -#endif /* INET6 */ - -#if HOSTTABLE - if (!at->family) { - struct hostent *h; - struct gaih_addrtuple **pat = &at; - -#if INET6 - if (!req->ai_family || (req->ai_family == AF_INET6)) - if (h = _hostname2addr_hosts(name, AF_INET6)) { - for (i = 0; h->h_addr_list[i]; i++) { - if (!*pat) { - if (!(*pat = malloc(sizeof(struct gaih_addrtuple)))) { - i = -EAI_MEMORY; - goto ret; - } - } - (*pat)->next = NULL; - (*pat)->family = AF_INET6; - memcpy((*pat)->addr, h->h_addr_list[i], sizeof(struct in6_addr)); - pat = &((*pat)->next); - } - } -#endif /* INET6 */ - - if (!req->ai_family || (req->ai_family == AF_INET)) - if (h = _hostname2addr_hosts(name, AF_INET)) { - for (i = 0; h->h_addr_list[i]; i++) { - if (!*pat) { - if (!(*pat = malloc(sizeof(struct gaih_addrtuple)))) { - i = -EAI_MEMORY; - goto ret; - } - } - (*pat)->next = NULL; - (*pat)->family = AF_INET; - memcpy((*pat)->addr, h->h_addr_list[i], sizeof(struct in_addr)); - pat = &((*pat)->next); - } + if (!at->family && (!req->ai_family || (req->ai_family == AF_INET6))) + if (inet_pton (AF_INET6, name, at->addr) > 0) + at->family = AF_INET6; + + if (at->family == AF_UNSPEC) + { + struct hostent *h; + struct gaih_addrtuple **pat = &at; + + if ((req->ai_family == AF_UNSPEC) || (req->ai_family == AF_INET6)) + gethosts (AF_INET6, struct in6_addr); + + if ((req->ai_family == AF_UNSPEC) || (req->ai_family == AF_INET)) + gethosts (AF_INET, struct in_addr); } + + if (at->family == AF_UNSPEC) + return (GAIH_OKIFUNSPEC | -EAI_NONAME); + } -#endif /* HOSTTABLE */ - -#if RESOLVER - if (!at->family) { - struct hostent *h; - struct gaih_addrtuple **pat = &at; - -#if INET6 - if (!req->ai_family || (req->ai_family == AF_INET6)) { - int herrno; - int tmpbuflen = 1024; - struct hostent th; - char *tmpbuf = __alloca(tmpbuflen); - while (__gethostbyname2_r(name, AF_INET6, &th, tmpbuf, tmpbuflen, - &h, &herrno)) { - if (herrno == NETDB_INTERNAL) { - if (errno == ERANGE) { - /* Need more buffer */ - tmpbuflen *= 2; - tmpbuf = __alloca(tmpbuflen); - } else { - /* Bail out */ - __set_h_errno(herrno); - i = -EAI_SYSTEM; - goto ret; - } - } else { - break; - } - } - if (h) { - for (i = 0; h->h_addr_list[i]; i++) { - if (!*pat) { - if (!(*pat = malloc(sizeof(struct gaih_addrtuple)))) { - i = -EAI_MEMORY; - goto ret; - } - } - (*pat)->next = NULL; - (*pat)->family = AF_INET6; - memcpy((*pat)->addr, h->h_addr_list[i], sizeof(struct in6_addr)); - pat = &((*pat)->next); - } - } - } -#endif /* INET6 */ - - if (!req->ai_family || (req->ai_family == AF_INET)) { - int herrno; - struct hostent th; - int tmpbuflen = 1024; - char *tmpbuf = __alloca(tmpbuflen); - while (__gethostbyname2_r(name, AF_INET, &th, tmpbuf, tmpbuflen, - &h, &herrno)) { - if (herrno == NETDB_INTERNAL) { - if (errno == ERANGE) { - /* Need more buffer */ - tmpbuflen *= 2; - tmpbuf = __alloca(tmpbuflen); - } else { - /* Bail out */ - __set_h_errno(herrno); - i = -EAI_SYSTEM; - goto ret; - } - } else { - break; - } - } - if (h) { - for (i = 0; h->h_addr_list[i]; i++) { - if (!*pat) { - if (!(*pat = malloc(sizeof(struct gaih_addrtuple)))) { - i = -EAI_MEMORY; - goto ret; - } - } - (*pat)->next = NULL; - (*pat)->family = AF_INET; - memcpy((*pat)->addr, h->h_addr_list[i], sizeof(struct in_addr)); - pat = &((*pat)->next); - } - } - } + else + { + at = __alloca (sizeof(struct gaih_addrtuple)); + if (at == NULL) + return -EAI_MEMORY; + + memset (at, 0, sizeof(struct gaih_addrtuple)); + + at->next = __alloca (sizeof(struct gaih_addrtuple)); + if (at->next == NULL) + return -EAI_MEMORY; + + at->family = AF_INET6; + + memset (at->next, 0, sizeof(struct gaih_addrtuple)); + at->next->family = AF_INET; } -#endif /* RESOLVER */ - - if (!at->family) - return (GAIH_OKIFUNSPEC | -EAI_NONAME); - } else { - if (!(at = malloc(sizeof(struct gaih_addrtuple)))) { - i = -EAI_MEMORY; - goto ret; - }; - - memset(at, 0, sizeof(struct gaih_addrtuple)); - -#if INET6 - if (!(at->next = malloc(sizeof(struct gaih_addrtuple)))) { - i = -EAI_MEMORY; - goto ret; - }; - - at->family = AF_INET6; - - memset(at->next, 0, sizeof(struct gaih_addrtuple)); - at->next->family = AF_INET; -#else /* INET6 */ - at->family = AF_INET; -#endif /* INET6 */ - }; - if (!pai) { - i = 0; - goto ret; - }; + if (pai == NULL) + return 0; { const char *c = NULL; struct gaih_servtuple *st2; struct gaih_addrtuple *at2 = at; - int j; + size_t socklen, namelen; + /* buffer is the size of an unformatted IPv6 address in printable format. */ char buffer[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; - while(at2) { - if (req->ai_flags & AI_CANONNAME) { - struct hostent *h = NULL; - -#if RESOLVER - int herrno; - struct hostent th; - int tmpbuflen = 1024; - char *tmpbuf = __alloca(tmpbuflen); - while (__gethostbyaddr_r(at2->addr, -#if INET6 - (at2->family == AF_INET6) ? sizeof(struct in6_addr) : -#endif /* INET6 */ - sizeof(struct in_addr), at2->family, - &th, tmpbuf, tmpbuflen, &h, &herrno)) { - if (herrno == NETDB_INTERNAL) { - if (errno == ERANGE) { - /* Need more buffer */ - tmpbuflen *= 2; - tmpbuf = __alloca(tmpbuflen); - } else { - /* Bail out */ - __set_h_errno(herrno); - i = -EAI_SYSTEM; - goto ret; - } - } else { - break; - } - } -#endif /* RESOLVER */ -#if HOSTTABLE - if (!h) - h = _addr2hostname_hosts(at2->addr, -#if INET6 - (at2->family == AF_INET6) ? sizeof(struct in6_addr) : -#endif /* INET6 */ - sizeof(struct in_addr), at2->family); -#endif /* HOSTTABLE */ - - if (!h) - c = inet_ntop(at2->family, at2->addr, buffer, sizeof(buffer)); - else - c = h->h_name; + while (at2 != NULL) + { + if (req->ai_flags & AI_CANONNAME) + { + struct hostent *h = NULL; - if (!c) { - i = (GAIH_OKIFUNSPEC | -EAI_NONAME); - goto ret; - } + int herrno; + struct hostent th; + size_t tmpbuflen = 512; + char *tmpbuf; - j = strlen(c) + 1; - } else - j = 0; + do + { + tmpbuflen *= 2; + tmpbuf = __alloca (tmpbuflen); -#if INET6 - if (at2->family == AF_INET6) - i = sizeof(struct sockaddr_in6); - else -#endif /* INET6 */ - i = sizeof(struct sockaddr_in); - - st2 = st; - while(st2) { - if (!(*pai = malloc(sizeof(struct addrinfo) + i + j))) { - i = -EAI_MEMORY; - goto ret; - } - (*pai)->ai_flags = req->ai_flags; - (*pai)->ai_family = at2->family; - (*pai)->ai_socktype = st2->socktype; - (*pai)->ai_protocol = st2->protocol; - (*pai)->ai_addrlen = i; - (*pai)->ai_addr = (void *)(*pai) + sizeof(struct addrinfo); + if (tmpbuf == NULL) + return -EAI_MEMORY; + + rc = __gethostbyaddr_r (at2->addr, + ((at2->family == AF_INET6) + ? sizeof(struct in6_addr) + : sizeof(struct in_addr)), + at2->family, &th, tmpbuf, tmpbuflen, + &h, &herrno); + + } + while ((rc != 0) && (herrno == NETDB_INTERNAL) + && (errno == ERANGE)); + + if ((rc != 0) && (herrno == NETDB_INTERNAL)) + { + __set_h_errno (herrno); + return -EAI_SYSTEM; + } + + if (h == NULL) + c = inet_ntop (at2->family, at2->addr, buffer, sizeof(buffer)); + else + c = h->h_name; + + if (c == NULL) + return GAIH_OKIFUNSPEC | -EAI_NONAME; + + namelen = strlen (c) + 1; + } + else + namelen = 0; + + if (at2->family == AF_INET6) + socklen = sizeof (struct sockaddr_in6); + else + socklen = sizeof (struct sockaddr_in); + + for (st2 = st; st2 != NULL; st2 = st2->next) + { + *pai = malloc (sizeof (struct addrinfo) + socklen + namelen); + if (*pai == NULL) + return -EAI_MEMORY; + + (*pai)->ai_flags = req->ai_flags; + (*pai)->ai_family = at2->family; + (*pai)->ai_socktype = st2->socktype; + (*pai)->ai_protocol = st2->protocol; + (*pai)->ai_addrlen = socklen; + (*pai)->ai_addr = (void *) (*pai) + sizeof(struct addrinfo); #if SALEN - ((struct sockaddr_in *)(*pai)->ai_addr)->sin_len = i; + ((struct sockaddr_in *) (*pai)->ai_addr)->sin_len = i; #endif /* SALEN */ - ((struct sockaddr_in *)(*pai)->ai_addr)->sin_family = at2->family; - ((struct sockaddr_in *)(*pai)->ai_addr)->sin_port = st2->port; - -#if INET6 - if (at2->family == AF_INET6) { - ((struct sockaddr_in6 *)(*pai)->ai_addr)->sin6_flowinfo = 0; - memcpy(&((struct sockaddr_in6 *)(*pai)->ai_addr)->sin6_addr, at2->addr, sizeof(struct in6_addr)); - } else -#endif /* INET6 */ - { - memcpy(&((struct sockaddr_in *)(*pai)->ai_addr)->sin_addr, at2->addr, sizeof(struct in_addr)); - memset(((struct sockaddr_in *)(*pai)->ai_addr)->sin_zero, 0, sizeof(((struct sockaddr_in *)(*pai)->ai_addr)->sin_zero)); - } + ((struct sockaddr_in *) (*pai)->ai_addr)->sin_family = at2->family; + ((struct sockaddr_in *) (*pai)->ai_addr)->sin_port = st2->port; - if (c) { - (*pai)->ai_canonname = (void *)(*pai) + sizeof(struct addrinfo) + i; - strcpy((*pai)->ai_canonname, c); - } else - (*pai)->ai_canonname = NULL; - (*pai)->ai_next = NULL; + if (at2->family == AF_INET6) + { + struct sockaddr_in6 *sin6p = + (struct sockaddr_in6 *) (*pai)->ai_addr; - pai = &((*pai)->ai_next); + sin6p->sin6_flowinfo = 0; + memcpy (&sin6p->sin6_addr, + at2->addr, sizeof (struct in6_addr)); + } + else + { + struct sockaddr_in *sinp = + (struct sockaddr_in *) (*pai)->ai_addr; + memcpy (&sinp->sin_addr, + at2->addr, sizeof (struct in_addr)); + memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero)); + } - st2 = st2->next; - } - at2 = at2->next; - } - } + if (c) + { + (*pai)->ai_canonname = ((void *) (*pai) + + sizeof (struct addrinfo) + socklen); + strcpy ((*pai)->ai_canonname, c); + } + else + (*pai)->ai_canonname = NULL; - i = 0; + (*pai)->ai_next = NULL; + pai = &((*pai)->ai_next); + } -ret: - if (st != &nullserv) { - struct gaih_servtuple *st2 = st; - while(st) { - st2 = st->next; - free(st); - st = st2; - } - } - if (at) { - struct gaih_addrtuple *at2 = at; - while(at) { - at2 = at->next; - free(at); - at = at2; - } + at2 = at2->next; + } } - return i; + return 0; } -struct gaih { - int family; - int (*gaih)(const char *name, const struct gaih_service *service, - const struct addrinfo *req, struct addrinfo **pai); -}; - -static struct gaih gaih[] = { -#if INET6 - { PF_INET6, gaih_inet }, -#endif /* INET6 */ - { PF_INET, gaih_inet }, -#if LOCAL - { PF_LOCAL, gaih_local }, -#endif /* LOCAL */ - { PF_UNSPEC, NULL } -}; +static struct gaih gaih[] = + { + { PF_INET6, gaih_inet }, + { PF_INET, gaih_inet }, + { PF_LOCAL, gaih_local }, + { PF_UNSPEC, NULL } + }; -int getaddrinfo(const char *name, const char *service, - const struct addrinfo *req, struct addrinfo **pai) +int +getaddrinfo (const char *name, const char *service, + const struct addrinfo *hints, struct addrinfo **pai) { int i = 0, j = 0; struct addrinfo *p = NULL, **end; struct gaih *g = gaih, *pg = NULL; struct gaih_service gaih_service, *pservice; - if (name && (name[0] == '*') && !name[1]) + if (name != NULL && name[0] == '*' && name[1] == 0) name = NULL; - if (service && (service[0] == '*') && !service[1]) + if (service != NULL && service[0] == '*' && service[1] == 0) service = NULL; -#if BROKEN_LIKE_POSIX - if (!name && !service) + if (name == NULL && service == NULL) return EAI_NONAME; -#endif /* BROKEN_LIKE_POSIX */ - if (!req) - req = &nullreq; + if (hints == NULL) + hints = &default_hints; - if (req->ai_flags & ~3) + if (hints->ai_flags & ~3) return EAI_BADFLAGS; - if ((req->ai_flags & AI_CANONNAME) && !name) + if ((hints->ai_flags & AI_CANONNAME) && name == NULL) return EAI_BADFLAGS; - if (service && *service) { - char *c; - gaih_service.num = strtoul(gaih_service.name = (void *)service, &c, 10); - if (*c) { - gaih_service.num = -1; - } -#if BROKEN_LIKE_POSIX + if (service && service[0]) + { + char *c; + gaih_service.name = service; + gaih_service.num = strtoul (gaih_service.name, &c, 10); + if (*c) + gaih_service.num = -1; else - if (!req->ai_socktype) + /* Can't specify a numerical socket unless a protocol family was + given. */ + if (hints->ai_socktype == 0) return EAI_SERVICE; -#endif /* BROKEN_LIKE_POSIX */ - pservice = &gaih_service; - } else + pservice = &gaih_service; + } + else pservice = NULL; if (pai) @@ -633,51 +559,58 @@ int getaddrinfo(const char *name, const char *service, else end = NULL; - while(g->gaih) { - if ((req->ai_family == g->family) || !req->ai_family) { - j++; - if (!((pg && (pg->gaih == g->gaih)))) { - pg = g; - if (i = g->gaih(name, pservice, req, end)) { - if (!req->ai_family && (i & GAIH_OKIFUNSPEC)) - continue; - goto gaih_err; + while (g->gaih) + { + if ((hints->ai_family == g->family) || (hints->ai_family == AF_UNSPEC)) + { + j++; + if ((pg == NULL) || (pg->gaih != g->gaih)) + { + pg = g; + if (i = g->gaih (name, pservice, hints, end)) + { + if ((hints->ai_family == AF_UNSPEC) && (i & GAIH_OKIFUNSPEC)) + continue; + + if (p) + freeaddrinfo (p); + + return (i)?-(i & GAIH_EAI):EAI_NONAME; + } + if (end) + while(*end) end = &((*end)->ai_next); + } } - if (end) - while(*end) end = &((*end)->ai_next); - } + ++g; } - g++; - } - if (!j) + if (j == 0) return EAI_FAMILY; - if (p) { - *pai = p; - return 0; - } + if (p) + { + *pai = p; + return 0; + } - if (!pai && !i) + if (pai == NULL && i == 0) return 0; -gaih_err: if (p) - freeaddrinfo(p); - - if (i) - return -(i & GAIH_EAI); + freeaddrinfo (p); - return EAI_NONAME; + return i ? -(i & GAIH_EAI) : EAI_NONAME; } -void freeaddrinfo(struct addrinfo *ai) +void +freeaddrinfo (struct addrinfo *ai) { struct addrinfo *p; - while(ai) { - p = ai; - ai = ai->ai_next; - free((void *)p); - } + while (ai != NULL) + { + p = ai; + ai = ai->ai_next; + free (p); + } } |