Beispiel #1
0
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;
}
Beispiel #2
0
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);
}
Beispiel #3
0
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);
}
Beispiel #5
0
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 },
Beispiel #7
0
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]);
}
Beispiel #9
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;
}
Beispiel #10
0
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);
}
Beispiel #14
0
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;
}
Beispiel #15
0
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;
}
Beispiel #16
0
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);
}
Beispiel #17
0
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);
}
Beispiel #18
0
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);
}
Beispiel #19
0
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);
}
Beispiel #20
0
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];
		}
	}
}
Beispiel #21
0
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;
}
Beispiel #22
0
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;
}
Beispiel #23
0
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;
}