From e8f39ca4898237cf71657500f0b11534c47a0521 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Sun, 1 Jun 2014 00:09:28 -0400 Subject: improve gethostbyname2_r using new resolver backend these changes reduce the size of the function somewhat and remove many of its dependencies, including free. in principle it should now be async-signal-safe, but this has not been verified in detail. minor changes to error handling are also made. --- src/network/gethostbyname2_r.c | 57 ++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/src/network/gethostbyname2_r.c b/src/network/gethostbyname2_r.c index 27eb080f..aa8b0a9e 100644 --- a/src/network/gethostbyname2_r.c +++ b/src/network/gethostbyname2_r.c @@ -6,41 +6,31 @@ #include #include #include +#include "lookup.h" int gethostbyname2_r(const char *name, int af, struct hostent *h, char *buf, size_t buflen, struct hostent **res, int *err) { - struct addrinfo hint = { - .ai_family = af==AF_INET6 ? af : AF_INET, - .ai_flags = AI_CANONNAME - }; - struct addrinfo *ai, *p; - int i; - size_t need; - const char *canon; + struct address addrs[MAXADDRS]; + char canon[256]; + int i, cnt; + size_t align, need; - af = hint.ai_family; - - /* Align buffer */ - i = (uintptr_t)buf & sizeof(char *)-1; - if (i) { - if (buflen < sizeof(char *)-i) return ERANGE; - buf += sizeof(char *)-i; - buflen -= sizeof(char *)-i; - } - - switch (getaddrinfo(name, 0, &hint, &ai)) { + cnt = __lookup_name(addrs, canon, name, af, AI_CANONNAME); + if (cnt<0) switch (cnt) { case EAI_NONAME: *err = HOST_NOT_FOUND; - return errno; + return ENOENT; case EAI_AGAIN: *err = TRY_AGAIN; - return errno; + return EAGAIN; default: + case EAI_FAIL: + *err = NO_RECOVERY; + return EBADMSG; case EAI_MEMORY: case EAI_SYSTEM: - case EAI_FAIL: *err = NO_RECOVERY; return errno; case 0: @@ -50,22 +40,22 @@ int gethostbyname2_r(const char *name, int af, h->h_addrtype = af; h->h_length = af==AF_INET6 ? 16 : 4; - canon = ai->ai_canonname ? ai->ai_canonname : name; + /* Align buffer */ + align = -(uintptr_t)buf & sizeof(char *)-1; + need = 4*sizeof(char *); - for (i=0, p=ai; p; i++, p=p->ai_next) - need += sizeof(char *) + h->h_length; + need += (cnt + 1) * (sizeof(char *) + h->h_length); need += strlen(name)+1; need += strlen(canon)+1; + need += align; - if (need > buflen) { - freeaddrinfo(ai); - return ERANGE; - } + if (need > buflen) return ERANGE; + buf += align; h->h_aliases = (void *)buf; buf += 3*sizeof(char *); h->h_addr_list = (void *)buf; - buf += (i+1)*sizeof(char *); + buf += (cnt+1)*sizeof(char *); h->h_name = h->h_aliases[0] = buf; strcpy(h->h_name, canon); @@ -79,16 +69,13 @@ int gethostbyname2_r(const char *name, int af, h->h_aliases[2] = 0; - for (i=0, p=ai; p; i++, p=p->ai_next) { + for (i=0; ih_addr_list[i] = (void *)buf; buf += h->h_length; - memcpy(h->h_addr_list[i], - &((struct sockaddr_in *)p->ai_addr)->sin_addr, - h->h_length); + memcpy(h->h_addr_list[i], addrs[i].addr, h->h_length); } h->h_addr_list[i] = 0; *res = h; - freeaddrinfo(ai); return 0; } -- cgit v1.2.1