bool threads_resolveIP(intrace_t * intrace, const char *hostname) { struct hostent he; struct hostent *hep; char workspace[4096]; int err; if (intrace->familyMode == ANY || intrace->familyMode == IPV6) { gethostbyname2_r(hostname, AF_INET6, &he, workspace, sizeof(workspace), &hep, &err); if (hep != NULL) { memcpy(intrace->rip6.s6_addr, hep->h_addr, hep->h_length); intrace->isIPv6 = true; return true; } } if (intrace->familyMode == ANY || intrace->familyMode == IPV4) { gethostbyname2_r(hostname, AF_INET, &he, workspace, sizeof(workspace), &hep, &err); if (hep != NULL) { memcpy(&intrace->rip.s_addr, hep->h_addr, hep->h_length); intrace->isIPv6 = false; return true; } } debug_printf(dlError, "Couldn't resolve '%s': '%s'\n", intrace->hostname, thread_err2asc(h_errno)); return false; }
void runSuccess() { struct hostent result_buf; char buf[] = "s"; struct hostent * result; int h_errnop; gethostbyname2_r(anystring(), anyint(), &result_buf, &buf, 1, &result, &h_errnop); }
inline Result<std::string> hostname() { char host[512]; if (gethostname(host, sizeof(host)) < 0) { return Result<std::string>::error(strerror(errno)); } struct hostent he, *hep; char* temp; size_t length; int result; int herrno; // Allocate temporary buffer for gethostbyname2_r. length = 1024; temp = new char[length]; while ((result = gethostbyname2_r(host, AF_INET, &he, temp, length, &hep, &herrno)) == ERANGE) { // Enlarge the buffer. delete[] temp; length *= 2; temp = new char[length]; } if (result != 0 || hep == NULL) { delete[] temp; return Result<std::string>::error(hstrerror(herrno)); } std::string hostname = hep->h_name; delete[] temp; return Result<std::string>::some(hostname); }
TEST(netdb, gethostbyname2_r_ERANGE) { hostent hent; hostent *hp; char buf[4]; // Use too small buffer. int err; int result = gethostbyname2_r("localhost", AF_INET, &hent, buf, sizeof(buf), &hp, &err); ASSERT_EQ(ERANGE, result); ASSERT_EQ(NULL, hp); }
struct hostent *gethostbyname2(const char *name, int af) { static struct hostent h; static long buf[512/sizeof(long)]; struct hostent *res; if (gethostbyname2_r(name, af, &h, (void *)buf, sizeof buf, &res, &h_errno)) return 0; return &h; }
int main(int argc, char **argv) { #ifdef GETHOSTBYNAME2 const char *node = "1:2:3:4:5:6:7:8"; #else const char *node = "1.2.3.4"; #endif struct hostent *result = NULL; #ifdef REENTRANT struct hostent he; size_t buflen = 1024; char buffer[buflen]; int my_errno, my_h_errno; #ifdef GETHOSTBYNAME2 my_errno = gethostbyname2_r(node, AF_INET6, &he, buffer, buflen, &result, &my_h_errno); #else my_errno = gethostbyname_r(node, &he, buffer, buflen, &result, &my_h_errno); #endif assert(!my_errno); assert(result == &he); #else #ifdef GETHOSTBYNAME2 result = gethostbyname2(node, AF_INET6); #else result = gethostbyname(node); #endif #endif assert(result && result->h_addr_list[0]); struct { struct hostent he; char *ha[1]; char *al[2]; #ifdef GETHOSTBYNAME2 struct in6_addr ia; #else struct in_addr ia; #endif } expected = { .he = { .h_name = result->h_name, .h_aliases = result->h_aliases, #ifdef GETHOSTBYNAME2 .h_addrtype = AF_INET6, #else .h_addrtype = AF_INET, #endif .h_length = sizeof expected.ia, .h_addr_list = result->h_addr_list, }, .ha = { NULL }, .al = { *result->h_addr_list, NULL },
void testValues() { f = 2; struct hostent result_buf; char buf[] = "s"; struct hostent * result; int h_errnop; gethostbyname2_r(anystring(), anyint(), &result_buf, &buf, 1, &result, &h_errnop); //@ assert f == 2; //@ assert vacuous: \false; }
TEST(netdb, gethostbyname2_r) { hostent hent; hostent *hp; char buf[512]; int err; int result = gethostbyname2_r("localhost", AF_INET, &hent, buf, sizeof(buf), &hp, &err); ASSERT_EQ(0, result); VerifyLocalhost(hp); // Change hp->h_addr to test reentrancy. hp->h_addr[0] = 0; hostent hent2; hostent *hp2; char buf2[512]; result = gethostbyname2_r("localhost", AF_INET, &hent2, buf2, sizeof(buf2), &hp2, &err); ASSERT_EQ(0, result); VerifyLocalhost(hp2); ASSERT_EQ(0, hp->h_addr[0]); }
int resolve_host(char *name, int family, void *result, int length) { struct hostent host, *bogus; char work[500]; int err, dumb; if ((err = gethostbyname2_r(name, family, &host, work, sizeof(work), &bogus, &dumb))) { errno = err; return -1; } memcpy(result, host.h_addr_list[0], host.h_length); return host.h_length; }
U8_EXPORT struct hostent *u8_gethostbyname(u8_string hname,int type) { char *name=u8_tolibc(hname); struct hostent *fetched, *copied; char _buf[1024], *buf=_buf; int bufsiz=0, herrno=0, retval; #if HAVE_GETHOSTBYNAME2_R struct hostent _fetched, *result; fetched=&_fetched; if (type>0) retval= gethostbyname2_r(name,type,fetched,buf,1024,&result,&herrno); else retval=gethostbyname_r(name,fetched,buf,1024,&result,&herrno); while (retval==ERANGE) { if (bufsiz) bufsiz=2048; else {u8_free(buf); bufsiz=bufsiz*2;} buf=u8_malloc(bufsiz); if (type>0) retval= gethostbyname2_r(name,type,fetched,buf,1024,&result,&herrno); else retval=gethostbyname_r(name,fetched,buf,1024,&result,&herrno);} if (result==NULL) { if (bufsiz) u8_free(buf); u8_graberr(herrno,"u8_gethostbyname",u8_strdup(hname)); return NULL;} copied=((fetched==NULL) ? (NULL) :(copy_hostent(fetched))); if (bufsiz) u8_free(buf); #else u8_lock_mutex(&netfns_lock); fetched=gethostbyname(name); if (fetched==NULL) { u8_seterr(UnknownHost,"u8_gethostbyname",name); u8_unlock_mutex(&netfns_lock); return NULL;} copied=copy_hostent(fetched); u8_unlock_mutex(&netfns_lock); #endif u8_free(name); return copied; }
struct hostent *gethostbyname2(const char *name, int family) { #ifndef __UCLIBC_HAS_IPV6__ return family == AF_INET ? gethostbyname(name) : (struct hostent*)0; #else /* __UCLIBC_HAS_IPV6__ */ static struct hostent h; static char buf[sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 + sizeof(char *)*(ALIAS_DIM) + 256/*namebuffer*/ + 32/* margin */]; struct hostent *hp; gethostbyname2_r(name, family, &h, buf, sizeof(buf), &hp, &h_errno); return hp; #endif /* __UCLIBC_HAS_IPV6__ */ }
static struct in_addr* convertToSockAddr(char const* kms_addr) { struct in_addr *addr = NULL, tmp; if (inet_aton(kms_addr, &tmp) == 0) { addr = kms_calloc(1, sizeof(struct in_addr)); if (addr == NULL) return NULL; addr->s_addr = tmp.s_addr; return addr; } char* buf = NULL; struct hostent result_buf, *result = NULL; uint32_t len = 1024; int32_t h_err; buf = kms_malloc(1024); if (buf == NULL) goto clean_return; int32_t rc; while ((rc = gethostbyname2_r(kms_addr, AF_INET, &result_buf, buf, len, &result, &h_err)) == ERANGE) { len *= 2; buf = realloc(buf, len); if (buf == NULL) goto clean_return; } if (rc != 0) { printf("Host res failed : kms vmx client\n"); goto clean_return; } uint32_t res_cnt = 0; while (result_buf.h_addr_list[res_cnt++] != NULL); res_cnt--; addr = kms_calloc(res_cnt, sizeof(struct in_addr)); if (addr == NULL) goto clean_return; uint32_t i = 0; for (i = 0; i < res_cnt; i++) addr[i].s_addr = ((struct in_addr*)(result_buf.h_addr_list[i]))->s_addr; clean_return: if (buf != NULL) free(buf); return addr; }
int main(void) { struct hostent resbuf = {0,}; struct hostent *result; int herrno; int retval; int af = AF_INET; retval = gethostbyname_r("localhost", &resbuf, temp.buffer, sizeof(temp.buffer), &result, &herrno); if (result) { hostent_print(result); if (*(int*)result->h_addr_list[0] == 0x0100007F) { printf("original gethostbyname_r works\n"); } } else exit(EXIT_FAILURE); result = NULL; retval = gethostbyname2_r("localhost", af, &resbuf, temp.buffer, sizeof(temp.buffer), &result, &herrno); if (result) { hostent_print(result); if (*(int*)result->h_addr_list[0] == 0x0100007F) { printf("original gethostbyname2_r works\n"); } } else exit(EXIT_FAILURE); /*** strlen (name) = size_needed - sizeof (*host_addr) - sizeof (*h_addr_ptrs) - 1; ***/ size_t len = sizeof(temp.buffer) - 16*sizeof(unsigned char) - 2*sizeof(char *) - 1; char name[sizeof(temp.buffer)]; memset(name, '0', len); name[len] = '\0'; retval = gethostbyname_r(name, &resbuf, temp.buffer, sizeof(temp.buffer), &result, &herrno); if (strcmp(temp.canary, CANARY) != 0) { puts("\033[2;31mvulnerable\033[0;39m"); exit(EXIT_SUCCESS); } if (retval == ERANGE) { puts("not vulnerable"); exit(EXIT_SUCCESS); } puts("should not happen"); exit(EXIT_FAILURE); }
struct hostent *gethostbyname2(const char *name, int af) { static struct hostent *h; size_t size = 63; struct hostent *res; int err; do { free(h); h = malloc(size+=size+1); if (!h) { h_errno = NO_RECOVERY; return 0; } err = gethostbyname2_r(name, af, h, (void *)(h+1), size-sizeof *h, &res, &h_errno); } while (err == ERANGE); return err ? 0 : h; }
bool resolveAddress(struct sockaddr_in *address, const char *host, unsigned short port) { assert(address); assert(host); // FIXME -- Need to ignore leading/trailing spaces in hostname. struct hostent *hp; int h_errno_local; #ifdef HAVE_GETHOSTBYNAME2_R struct hostent hostData; char tmpBuffer[2048]; // There are different flavors of gethostbyname_r(), but // latest Linux use the following form: if (gethostbyname2_r(host, AF_INET, &hostData, tmpBuffer, sizeof(tmpBuffer), &hp, &h_errno_local)!=0) { LOG(WARNING) << "gethostbyname2_r() failed for " << host << ", " << hstrerror(h_errno_local); //CERR("WARNING -- gethostbyname2_r() failed for " << host << ", " << hstrerror(h_errno_local)); return false; } #else static Mutex sGethostbynameMutex; // gethostbyname() is NOT thread-safe, so we should use a mutex here. // Ideally it should be a global mutex for all non thread-safe socket // operations and it should protect access to variables such as // global h_errno. sGethostbynameMutex.lock(); hp = gethostbyname(host); h_errno_local = h_errno; sGethostbynameMutex.unlock(); #endif if (hp==NULL) { LOG(WARNING) << "gethostbyname() failed for " << host << ", " << hstrerror(h_errno_local); return false; } if (hp->h_addrtype != AF_INET) { LOG(WARNING) << "gethostbyname() resolved " << host << " to something other then AF_INET"; return false; } address->sin_family = hp->h_addrtype; // Above guarantees it is AF_INET assert(sizeof(address->sin_addr) == hp->h_length); memcpy(&(address->sin_addr), hp->h_addr_list[0], hp->h_length); address->sin_port = htons(port); return true; }
static void run_query (const char *query, const char *address) { char *quoted_query = support_quote_string (query); char *context = xasprintf ("gethostbyname (\"%s\")", quoted_query); char *expected = xasprintf ("name: %s\n" "address: %s\n", query, address); check_hostent (context, gethostbyname (query), expected); free (context); context = xasprintf ("gethostbyname_r \"%s\"", quoted_query); struct hostent storage; char buf[4096]; struct hostent *e = NULL; TEST_COMPARE (gethostbyname_r (query, &storage, buf, sizeof (buf), &e, &h_errno), 0); check_hostent (context, e, expected); free (context); context = xasprintf ("gethostbyname2 (\"%s\", AF_INET)", quoted_query); check_hostent (context, gethostbyname2 (query, AF_INET), expected); free (context); context = xasprintf ("gethostbyname2_r \"%s\" AF_INET", quoted_query); e = NULL; TEST_COMPARE (gethostbyname2_r (query, AF_INET, &storage, buf, sizeof (buf), &e, &h_errno), 0); check_hostent (context, e, expected); free (context); free (expected); free (quoted_query); /* The gethostbyname tests are always valid for getaddrinfo, but not vice versa. */ run_query_addrinfo (query, address); }
static void resolve(sa_family_t srcFamily, const std::string& name, void* address, int addressLength) { hostent hostentBuffer; char stringBuffer[512]; hostent* result = nullptr; int errorCode = 0; if (gethostbyname2_r(name.c_str(), srcFamily, &hostentBuffer, stringBuffer, sizeof(stringBuffer), &result, &errorCode) != 0) { throw std::runtime_error(hstrerror(errorCode)); } assert(result); assert(result->h_addrtype == srcFamily); assert(result->h_length == addressLength); assert(result->h_addr_list); assert(result->h_addr_list[0]); memcpy(address, result->h_addr_list[0], result->h_length); }
int gethostbyname_r(const char *name, struct hostent *h, char *buf, size_t buflen, struct hostent **res, int *err) { return gethostbyname2_r(name, AF_INET, h, buf, buflen, res, err); }
int lookup_host(const char *name, char *addr) { int i, oldest_slot, slot; long int oldest_count; DNS_entry_t *list; int retcode; log_printf(20, "lookup_host: start time=" TT "\n", time(NULL)); if (name[0] == '\0') return(1); //** Return early if name is NULL pthread_mutex_lock(&(_cache->mutex)); bzero(addr,ADDR_LEN); retcode = 1; _cache->count++; list = _cache->list; i = 0; oldest_slot = 0; oldest_count = list[i].count; while ((i<(_cache->size-1)) && (strcmp(name, list[i].name) != 0)) { i++; if (oldest_count > list[i].count) { oldest_slot = i; oldest_count = list[i].count; } } if (strcmp(name, list[i].name) == 0) { //*** Found it! list[i].count = _cache->count; memcpy(addr,&(list[i].addr), ADDR_LEN); retcode = 0; log_printf(20, "lookup_host: Found %s in cache slot %d (%s) \n", name, i, list[i].name); log_printf(20, "lookup_host: Found %s in cache slot %d (%s,%hhu.%hhu.%hhu.%hhu)\n", name, i, list[i].name, list[i].addr[0],list[i].addr[1],list[i].addr[2],list[i].addr[3]); //flush_log(); } else { //*** Got to add it char buf[10000]; struct hostent hostbuf, *host; int err; memset(&hostbuf, 0, sizeof(struct hostent)); slot = oldest_slot; log_printf(10, "lookup_host: Before gethostbyname Hostname: %s\n", name); flush_log(); i = gethostbyname2_r(name, AF_INET, &hostbuf, buf, 10000, &host, &err); log_printf(10, "lookup_host: Hostname: %s err=%d\n", name, err); // n = 0; // while (!host && (n<4)) { // log_printf(10, "lookup_host gethostbyname failed. Hostname: %s err=%d\n", name, err); // sleep(1); // i = gethostbyname2_r(name, AF_INET, &hostbuf, buf, 10000, &host, &err); // n++; // } if (host) { //** Got it list[slot].count = _cache->count; strncpy(list[slot].name, name, BUF_SIZE); list[slot].name[BUF_SIZE-1] = '\0'; memcpy(addr,host->h_addr, ADDR_LEN); memcpy(&(list[slot].addr),host->h_addr, host->h_length); log_printf(15, "lookup_host: Added %s to slot %d (%s,%hhu.%hhu.%hhu.%hhu) h_len=%d\n", name, slot, host->h_name, list[slot].addr[0],list[slot].addr[1],list[slot].addr[2],list[slot].addr[3], host->h_length); retcode = 0; } else { log_printf(10, "lookup_host: %s not found!\n", name); } } if (_cache->count == LONG_MAX) { //*** Got to renumber the counts _cache->count = 0; for (i=0; i<_cache->size; i++) { //This is nonoptimal but shouldn't matter if (list[i].count > 0) list[i].count = _cache->count++; } } pthread_mutex_unlock(&(_cache->mutex)); log_printf(20, "lookup_host: end time=" TT "\n", time(NULL)); return(retcode); }
void IPV6Address::setAddress(const char *host) { if(hostname) delString(hostname); hostname = NULL; if(!host) // The way this is currently used, this can never happen host = "::"; #ifdef WIN32 if(!stricmp(host, "localhost")) host = "::1"; #endif if(!setIPAddress(host)) { struct hostent *hp; struct in6_addr **bptr; #if defined(__GLIBC__) char hbuf[8192]; struct hostent hb; int rtn; if(gethostbyname2_r(host, AF_INET6, &hb, hbuf, sizeof(hbuf), &hp, &rtn)) hp = NULL; #elif defined(sun) char hbuf[8192]; struct hostent hb; int rtn; hp = gethostbyname2_r(host, AF_INET6, &hb, hbuf, sizeof(hbuf), &rtn); #elif (defined(__osf__) || defined(_OSF_SOURCE) || defined(__hpux)) hp = gethostbyname(host); #elif defined(WIN32) && (!defined(_MSC_VER) || _MSC_VER < 1300) hp = gethostbyname(host); #elif defined(WIN32) hp = gethostbyname2(host, AF_INET6); #else mutex.enterMutex(); hp = gethostbyname2(host, AF_INET6); mutex.leaveMutex(); #endif if(!hp) { if(ipaddr) delete[] ipaddr; ipaddr = new struct in6_addr[1]; memset((void *)&ipaddr[0], 0, sizeof(ipaddr)); return; } // Count the number of IP addresses returned addr_count = 0; for(bptr = (struct in6_addr **)hp->h_addr_list; *bptr != NULL; bptr++) { addr_count++; } // Allocate enough memory if(ipaddr) delete[] ipaddr; // Cause this was allocated in base ipaddr = new struct in6_addr[addr_count]; // Now go through the list again assigning to // the member ipaddr; bptr = (struct in6_addr **)hp->h_addr_list; for(unsigned int i = 0; i < addr_count; i++) { if ( validator ) (*validator)(*bptr[i]); ipaddr[i] = *bptr[i]; } } }
int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) { struct addrinfo **tmp; int family; int error=EAI_NONAME; int flags=0; tmp=res; *res=0; if (hints) { if (hints->ai_family && hints->ai_family != PF_INET6 && hints->ai_family != PF_INET) return EAI_FAMILY; if (hints->ai_socktype && hints->ai_socktype != SOCK_STREAM && hints->ai_socktype != SOCK_DGRAM) return EAI_SOCKTYPE; flags=hints->ai_flags; if ((flags&AI_V4MAPPED) && hints->ai_family!=PF_INET6) flags&=~(AI_V4MAPPED|AI_ALL); } for (family=PF_INET6; ; family=PF_INET) { if (!hints || hints->ai_family==family || hints->ai_family==AF_UNSPEC || (flags&(AI_V4MAPPED|AI_ALL))) { struct hostent h; struct hostent *H; int herrno=0; char buf[4096]; int lookupok=0, i; char* interface; h.h_addr_list=(char**)buf+16; h.h_addr_list[1]=0; if (node) { if ((interface=strchr(node,'%'))) ++interface; if (family==PF_INET6 && inet_pton(AF_INET,node,buf)) continue; if (inet_pton(family,node,buf)>0) { h.h_name=(char*)node; h.h_addr_list[0]=buf; lookupok=1; } else if (!(flags&AI_NUMERICHOST) && !gethostbyname2_r(node,family,&h,buf,4096,&H,&herrno)) { lookupok=1; } else { if (herrno==TRY_AGAIN) { freeaddrinfo(*res); return EAI_AGAIN; } } } else { h.h_name=0; h.h_addr_list[0]=buf; interface=0; memset(buf,0,16); if (!(flags&AI_PASSIVE)) { if (family==AF_INET) { buf[0]=127; buf[3]=1; } else buf[15]=1; } lookupok=1; } if (lookupok) { for (i=0; h.h_addr_list[i]; ++i) { struct ai_v6 { struct addrinfo ai; union { struct sockaddr_in6 ip6; struct sockaddr_in ip4; } ip; char name[1]; } *foo; unsigned short port; int len; len=sizeof(struct ai_v6)+(h.h_name?strlen(h.h_name):0); if (!(foo=malloc(len))) goto error; foo->ai.ai_next=0; foo->ai.ai_addrlen=family==PF_INET6?sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in); foo->ai.ai_addr=(struct sockaddr*)&foo->ip; memset(&foo->ip,0,sizeof(foo->ip)); foo->ip.ip6.sin6_family=foo->ai.ai_family=family; if (family==PF_INET6) { memmove(&foo->ip.ip6.sin6_addr,h.h_addr_list[i],16); if (interface) foo->ip.ip6.sin6_scope_id=if_nametoindex(interface); } else { /* IPv4 */ if (flags&AI_V4MAPPED) { foo->ai.ai_addrlen=sizeof(struct sockaddr_in6); foo->ip.ip6.sin6_addr.s6_addr[10]=foo->ip.ip6.sin6_addr.s6_addr[11]=0xff; memmove(foo->ip.ip6.sin6_addr.s6_addr+12,h.h_addr_list[i],4); foo->ip.ip6.sin6_family=foo->ai.ai_family=PF_INET6; } else memmove(&foo->ip.ip4.sin_addr,h.h_addr_list[i],4); } #ifdef WANT_PLUGPLAY_DNS if (family==PF_INET6 && node) { int l=strlen(node); if ((l>6 && !strcmp(node+l-6,".local")) || !strchr(node,'.')) foo->ip.ip6.sin6_scope_id=__dns_plugplay_interface; } #endif if (h.h_name) { foo->ai.ai_canonname=foo->name; memmove(foo->name,h.h_name,strlen(h.h_name)+1); } else foo->ai.ai_canonname=0; for (foo->ai.ai_socktype=SOCK_STREAM; ; foo->ai.ai_socktype=SOCK_DGRAM) { char* type,* x; if (foo->ai.ai_socktype==SOCK_STREAM) { /* TCP */ if (hints && hints->ai_socktype==SOCK_DGRAM) continue; foo->ai.ai_protocol=IPPROTO_TCP; type="tcp"; } else { /* UDP */ if (hints && hints->ai_socktype==SOCK_STREAM) break; foo->ai.ai_protocol=IPPROTO_UDP; type="udp"; } port=htons(strtol(service?service:"0",&x,0)); if (*x) { /* service is not numeric :-( */ struct servent* se; if (!(flags&AI_NUMERICSERV) && (se=getservbyname(service,type))) port=se->s_port; else { /* can't just fail hard here; maybe the port is defined but not for the protocol we are trying */ error=EAI_SERVICE; if (foo->ai.ai_socktype==SOCK_DGRAM) break; continue; } } if (foo->ai.ai_family==PF_INET6) foo->ip.ip6.sin6_port=port; else foo->ip.ip4.sin_port=port; if (!*tmp) *tmp=&(foo->ai); else (*tmp)->ai_next=&(foo->ai); if (!(foo=malloc(len))) goto error; memmove(foo,*tmp,len); tmp=&(*tmp)->ai_next; foo->ai.ai_addr=(struct sockaddr*)&foo->ip; if (foo->ai.ai_canonname) foo->ai.ai_canonname=foo->name; if (foo->ai.ai_socktype==SOCK_DGRAM) break; } free(foo); } } } if (hints && hints->ai_family==PF_INET6 && (flags&AI_V4MAPPED) && *res==0) flags|=AI_ALL; if (family==PF_INET) break; } if (*res==0) return error; /* kludge kludge... */ return 0; error: freeaddrinfo(*res); return EAI_MEMORY; }
int swoole_gethostbyname(int flags, char *name, char *addr) { int __af = flags & (~SW_DNS_LOOKUP_RANDOM); int index = 0; int rc, err; int buf_len = 256; struct hostent hbuf; struct hostent *result; char * buf = (char*) sw_malloc(buf_len); memset(buf, 0, buf_len); while ((rc = gethostbyname2_r(name, __af, &hbuf, buf, buf_len, &result, &err)) == ERANGE) { buf_len *= 2; void *tmp = realloc(buf, buf_len); if (NULL == tmp) { sw_free(buf); return SW_ERR; } else { buf = tmp; } } if (0 != rc || NULL == result) { sw_free(buf); return SW_ERR; } union { char v4[INET_ADDRSTRLEN]; char v6[INET6_ADDRSTRLEN]; } addr_list[SW_DNS_HOST_BUFFER_SIZE]; int i = 0; for (i = 0; i < SW_DNS_HOST_BUFFER_SIZE; i++) { if (hbuf.h_addr_list[i] == NULL) { break; } if (__af == AF_INET) { memcpy(addr_list[i].v4, hbuf.h_addr_list[i], hbuf.h_length); } else { memcpy(addr_list[i].v6, hbuf.h_addr_list[i], hbuf.h_length); } } if (__af == AF_INET) { memcpy(addr, addr_list[index].v4, hbuf.h_length); } else { memcpy(addr, addr_list[index].v6, hbuf.h_length); } sw_free(buf); return SW_OK; }
void runFailure() { gethostbyname2_r(NULL, anyint(), NULL, NULL, anyint(), NULL, NULL); }
int cl_lookup(cl_cluster *asc, char *hostname, short port, cf_vector *sockaddr_in_v) { // do the gethostbyname to find the IP address size_t hstbuflen = 1024; uint8_t stack_hstbuf[hstbuflen]; void *tmphstbuf = stack_hstbuf; int rv, herr, addrmapsz; struct hostent hostbuf, *hp; cl_addrmap *map; int retry = 0; //Find if there is an alternate address that should be used for this hostname. if (asc && (asc->host_addr_map_v.len > 0)) { addrmapsz = asc->host_addr_map_v.len; for (int i=0; i<addrmapsz; i++) { map = cf_vector_pointer_get(&asc->host_addr_map_v, i); if (map && strcmp(map->orig, hostname) == 0) { //found a mapping for this address. Use the alternate one. cf_debug("Using %s instead of %s", map->alt, hostname); hostname = map->alt; break; } } } do { #ifdef OSX // on OSX, gethostbyname is thread safe and there is no '_r' version hp = gethostbyname2(hostname, AF_INET); rv = 0; if(hp == NULL){ herr = h_errno; // I'm hoping this is thread-safe too, in the Mac world... } #else rv = gethostbyname2_r(hostname, AF_INET, &hostbuf, tmphstbuf, hstbuflen, &hp, &herr); #endif /* TRY_AGAIN for a maximun of 3 times, after which throw an error */ if(retry > 2) { cf_error("gethostbyname of %s - maxmimum retries failed", hostname); retry = 0; return -1; } if (hp == NULL) { hostname = hostname ? hostname : "NONAME"; switch(herr) { case HOST_NOT_FOUND: cf_error("gethostbyname says no host at %s", hostname); break; case NO_ADDRESS: cf_error("gethostbyname of %s says invalid address (errno %d)", hostname, herr); break; case NO_RECOVERY: cf_error("gethostbyname of %s says form error (errno %d)", hostname, herr); break; case TRY_AGAIN: cf_error("gethostbyname of %s returned TRY_AGAIN, try again (rv=%d)", hostname, rv); retry++; continue; default: cf_error("gethostbyname of %s returned an unknown error (errno %d)", hostname, herr); break; } if (tmphstbuf != stack_hstbuf) free(tmphstbuf); return(-1); } else if (rv != 0) { if (rv == ERANGE) { hstbuflen *= 2; if (tmphstbuf == stack_hstbuf) tmphstbuf = malloc(hstbuflen); else tmphstbuf = realloc (tmphstbuf, hstbuflen); if (!tmphstbuf) { cf_error("malloc fail"); return(-1); } } else if (rv == EAGAIN || herr == TRY_AGAIN) { cf_error("gethostbyname returned EAGAIN, try again"); retry++; } else if (rv == ETIMEDOUT) { cf_error("gethostbyname for %s timed out", hostname ? (hostname): "NONAME"); if (tmphstbuf != stack_hstbuf) free(tmphstbuf); return(-1); } else { cf_error("gethostbyname returned an unknown error %d %d (errno %d)",rv,herr, errno); if (tmphstbuf != stack_hstbuf) free(tmphstbuf); return(-1); } } } while ((rv != 0) || (hp == NULL)); #ifdef DEBUG cf_debug("host lookup: %s canonical: %s addrtype %d length: %d", hostname, hp->h_name, hp->h_addrtype, hp->h_length); for (int i=0;hp->h_aliases[i];i++) { cf_debug(" alias %d: %s",i, hp->h_aliases[i]); } for (int i=0;hp->h_addr_list[i];i++) { // todo: print something about the actual address cf_debug(" address %d: %x",i,*(uint32_t *) hp->h_addr_list[i]); } #endif if (hp->h_addrtype != AF_INET) { cf_error("unknown address type %d", hp->h_addrtype); if (tmphstbuf != stack_hstbuf) free(tmphstbuf); return(-1); } // sockaddr_in_v is passed as NULL from caller which needs // to only check if lookup succeeds. If reach here it is // a successful lookup. if (sockaddr_in_v == NULL) { goto ret_success; } // Move into vector for (int i=0;hp->h_addr_list[i];i++) { struct sockaddr_in addr; memset(&addr,0,sizeof(addr)); addr.sin_family = hp->h_addrtype; addr.sin_addr.s_addr = *(uint32_t *) hp->h_addr_list[i]; addr.sin_port = htons(port); cf_vector_append_unique(sockaddr_in_v, &addr); } ret_success: if (tmphstbuf != stack_hstbuf) free(tmphstbuf); return(0); }
int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) { struct addrinfo **tmp; int family; tmp=res; *res=0; if (hints) { if (hints->ai_family && hints->ai_family != PF_INET6 && hints->ai_family != PF_INET) return EAI_FAMILY; if (hints->ai_socktype && hints->ai_socktype != SOCK_STREAM && hints->ai_socktype != SOCK_DGRAM) return EAI_SOCKTYPE; } for (family=PF_INET6; ; family=PF_INET) { if (!hints || hints->ai_family==family || hints->ai_family==AF_UNSPEC) { /* IPv6 addresses are OK */ struct hostent h; struct hostent *H; int herrno=0; char buf[4096]; int lookupok=0; char* interface; h.h_addr_list=(char**)buf+16; if (node) { if ((interface=strchr(node,'%'))) ++interface; if (inet_pton(family,node,buf)>0) { h.h_name=(char*)node; h.h_addr_list[0]=buf; lookupok=1; } else if ((!hints || !(hints->ai_flags&AI_NUMERICHOST)) && !gethostbyname2_r(node,family,&h,buf,4096,&H,&herrno)) { lookupok=1; } else { if (herrno==TRY_AGAIN) { freeaddrinfo(*res); return EAI_AGAIN; } } } else { h.h_name=0; h.h_addr_list[0]=buf; interface=0; memset(buf,0,16); if (!hints || !(hints->ai_flags&AI_PASSIVE)) { if (family==AF_INET) { buf[0]=127; buf[3]=1; } else buf[15]=1; } lookupok=1; } if (lookupok) { struct ai_v6 { struct addrinfo ai; union { struct sockaddr_in6 ip6; struct sockaddr_in ip4; } ip; char name[1]; } *foo; unsigned short port; int len=sizeof(struct ai_v6)+(h.h_name?strlen(h.h_name):0); if (!(foo=malloc(len))) goto error; foo->ai.ai_next=0; foo->ai.ai_socktype=SOCK_STREAM; foo->ai.ai_protocol=IPPROTO_TCP; foo->ai.ai_addrlen=family==PF_INET6?sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in); foo->ai.ai_addr=(struct sockaddr*)&foo->ip; if (family==PF_INET6) { memset(&foo->ip,0,sizeof(foo->ip)); memmove(&foo->ip.ip6.sin6_addr,h.h_addr_list[0],16); if (interface) foo->ip.ip6.sin6_scope_id=if_nametoindex(interface); } else { memmove(&foo->ip.ip4.sin_addr,h.h_addr_list[0],4); } foo->ip.ip6.sin6_family=foo->ai.ai_family=family; #ifdef WANT_PLUGPLAY_DNS if (family==AF_INET6) foo->ip.ip6.sin6_scope_id=__dns_plugplay_interface; #endif if (h.h_name) { foo->ai.ai_canonname=foo->name; memmove(foo->name,h.h_name,strlen(h.h_name)+1); } else foo->ai.ai_canonname=0; if (!hints || hints->ai_socktype!=SOCK_DGRAM) { /* TCP is OK */ char *x; port=htons(strtol(service?service:"0",&x,0)); if (*x) { /* service is not numeric :-( */ struct servent* se; if ((se=getservbyname(service,"tcp"))) { /* found a service. */ port=se->s_port; blah1: if (family==PF_INET6) foo->ip.ip6.sin6_port=port; else foo->ip.ip4.sin_port=port; if (!*tmp) *tmp=&(foo->ai); else (*tmp)->ai_next=&(foo->ai); if (!(foo=malloc(len))) goto error; memmove(foo,*tmp,len); tmp=&(*tmp)->ai_next; foo->ai.ai_addr=(struct sockaddr*)&foo->ip; if (foo->ai.ai_canonname) foo->ai.ai_canonname=foo->name; } else { freeaddrinfo(*res); return EAI_SERVICE; } } else goto blah1; } foo->ai.ai_socktype=SOCK_DGRAM; foo->ai.ai_protocol=IPPROTO_UDP; if (!hints || hints->ai_socktype!=SOCK_STREAM) { /* UDP is OK */ char *x; port=htons(strtol(service?service:"0",&x,0)); if (*x) { /* service is not numeric :-( */ struct servent* se; if ((se=getservbyname(service,"udp"))) { /* found a service. */ port=se->s_port; blah2: if (family==PF_INET6) foo->ip.ip6.sin6_port=port; else foo->ip.ip4.sin_port=port; if (!*tmp) *tmp=&(foo->ai); else (*tmp)->ai_next=&(foo->ai); if (!(foo=malloc(len))) goto error; memmove(foo,*tmp,len); tmp=&(*tmp)->ai_next; foo->ai.ai_addr=(struct sockaddr*)&foo->ip; foo->ai.ai_canonname=foo->name; } else { freeaddrinfo(*res); return EAI_SERVICE; } } else goto blah2; } free(foo); } } if (family==PF_INET) break; } if (*res==0) return EAI_NONAME; /* kludge kludge... */ return 0; error: freeaddrinfo(*res); return EAI_MEMORY; }