Ejemplo n.º 1
0
const char *IPV4Address::getHostname(void) const
{
    struct hostent *hp = NULL;
    struct in_addr addr0;

    memset(&addr0, 0, sizeof(addr0));
    if(!memcmp(&addr0, &ipaddr[0], sizeof(addr0)))
        return NULL;

#ifdef _MSWINDOWS_
    memset(&addr0, 0xff, sizeof(addr0));
    if(!memcmp(&addr0, &ipaddr[0], sizeof(addr0)))
        return "255.255.255.255";
    long a = inet_addr("127.0.0.1");
    if(!memcmp(&a, &ipaddr[0], sizeof(a)))
        return "localhost";
#endif

#if defined(__GLIBC__)
    char   hbuf[8192];
    struct hostent hb;
    int    rtn;
    if(gethostbyaddr_r((char *)&ipaddr[0], sizeof(addr0), AF_INET, &hb, hbuf, sizeof(hbuf), &hp, &rtn))
        hp = NULL;
#elif defined(sun)
    char   hbuf[8192];
    struct hostent hb;
    int    rtn;
    hp = gethostbyaddr_r((char *)&ipaddr[0], (int)sizeof(addr0), (int)AF_INET, &hb, hbuf, (int)sizeof(hbuf), &rtn);
#elif defined(__osf__) || defined(_MSWINDOWS_)
    hp = gethostbyaddr((char *)&ipaddr[0], sizeof(addr0), AF_INET);
#else
    mutex.enterMutex();
    hp = gethostbyaddr((char *)&ipaddr[0], sizeof(addr0), AF_INET);
    mutex.leaveMutex();
#endif
    if(hp) {
        if(hostname)
            delString(hostname);
        hostname = newString(hp->h_name);
        return hostname;
    } else {
        return inet_ntoa(ipaddr[0]);
    }
}
Ejemplo n.º 2
0
struct hostent *gethostbyaddr(const void *a, socklen_t l, int af)
{
	static struct hostent h;
	static long buf[512/sizeof(long)];
	struct hostent *res;
	if (gethostbyaddr_r(a, l, af, &h,
		(void *)buf, sizeof buf, &res, &h_errno)) return 0;
	return &h;
}
Ejemplo n.º 3
0
static int my_gethostbyaddr_r (const char * addr, socklen_t len,
			       int type,
			       struct hostent * result_buf,
			       char * buf, size_t buflen,
			       struct hostent ** result,
			       int * h_errnop) {
  *result = gethostbyaddr_r(addr, len, type, result_buf, buf, buflen,
			    h_errnop);
  return (result ? 0 : -1);
}
Ejemplo n.º 4
0
TEST(netdb, gethostbyaddr_r_ERANGE) {
  in_addr addr = { htonl(0x7f000001) };
  hostent hent;
  hostent *hp;
  char buf[4]; // Use too small buffer.
  int err;
  int result = gethostbyaddr_r(&addr, sizeof(addr), AF_INET, &hent, buf, sizeof(buf), &hp, &err);
  ASSERT_EQ(ERANGE, result);
  ASSERT_EQ(NULL, hp);
}
Ejemplo n.º 5
0
struct hostent *
linux_gethostbyaddr_r (const char *host, int hostlen, struct hostent *he, char *buffer, int buflen, int *error)
{
	int out;
	*error = 0;
	if ((out = gethostbyaddr_r (host, hostlen, AF_INET, he, buffer, buflen, &he, error) >= 0))
	{
		return he;
	}
	xa_debug (2, "gethostbyaddr_r() returned %d, error is %d", out, *error);
	return NULL;
}
Ejemplo n.º 6
0
int Gethostbyaddr_r(const char *addr, int len, int type, 
 struct hostent *ret, char *buf, size_t buflen,
                struct hostent **result, int *h_errnop)

{
     int p;

    p = gethostbyaddr_r(addr, len, type, ret, buf, buflen, result, h_errnop);
	if (p)
		dns_error("Gethostbyaddr error");
    return p;
}
Ejemplo n.º 7
0
TEST(netdb, gethostbyaddr_r) {
  in_addr addr = { htonl(0x7f000001) };
  hostent hent;
  hostent *hp;
  char buf[512];
  int err;
  int result = gethostbyaddr_r(&addr, sizeof(addr), 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 = gethostbyaddr_r(&addr, sizeof(addr), AF_INET, &hent2, buf2, sizeof(buf2), &hp2, &err);
  ASSERT_EQ(0, result);
  VerifyLocalhost(hp2);

  ASSERT_EQ(0, hp->h_addr[0]);
}
Ejemplo n.º 8
0
bool CDomainNameService::CreatePeer(
    unsigned long RemoteAddress, 
    CVector<CString>& PeerAddresses, 
    CVector<CString>& PeerAliases
    ) {

    Trace(tagDns, levInfo, ("CDns :: CreatePeer(R6)"));
    
    bool bResult = false;
    struct hostent hostbuf;
    struct hostent * hp = NULL;
	int herr = 0;
    int res = 0;
    size_t hstbuflen = 1024;
    char * tmphstbuf = new char[hstbuflen];
    memset(tmphstbuf, 0, hstbuflen);

	while (( res = 
             gethostbyaddr_r (
                 (const char *) RemoteAddress,
                 sizeof(RemoteAddress),
                 AF_INET,
                 & hostbuf,
                 tmphstbuf,
                 hstbuflen,                 
                 & hp,
                 & herr))
           && (herr == ERANGE))
	{

        Trace(tagDns, levInfo, ("CDns :: CreatePeer(R6) - ERANGE, current buffer size is %d bytes.", hstbuflen));
    
		hstbuflen *= 2;
        delete[] tmphstbuf;
		tmphstbuf = (char *) new char[hstbuflen];
        memset(tmphstbuf, 0, hstbuflen);
	}

    Trace(tagDns, levInfo, ("CDns :: CreatePeer(R6) - gethostbyaddr_r done, returned %d.", res));
    
	if (! res) {        
        bResult = WalkHostent(hp, PeerAddresses, PeerAliases);
    }
    
    delete[] tmphstbuf;

    Trace(tagDns, levInfo, ("CDns :: CreatePeer(R6) - returning %s", bResult?"true":"false"));
    
    return bResult;
}
Ejemplo n.º 9
0
void addr2name(struct in_addr addr, char *name, int namelen) {
   char buf[GETHOST_BUFSIZE];
   int h_error;
   struct hostent *hp;
   struct hostent result;

   hp = gethostbyaddr_r((char *)&addr, 4, AF_INET, &result, buf,
                         GETHOST_BUFSIZE, &h_error);
   if (hp == NULL)
      strncpy(name, inet_ntoa(addr), namelen-1);
   else
      strncpy(name, hp->h_name, namelen-1);
   name[namelen-1] = 0;
}
Ejemplo n.º 10
0
int
main()
{
    char                *address;
    int                 length; q
    int                 type;
    struct hostent      h;
    struct hostent_data hdata;
    int                 rc;

#ifndef gethostbyaddr_r
    (void)gethostbyaddr_r;
#endif
    rc = gethostbyaddr_r(address, length, type, &h, &hdata);
    ;
    return 0;
}
Ejemplo n.º 11
0
/**
	host_reverse : 'int32 -> string
	<doc>Reverse the DNS of the given IP address.</doc>
**/
static value host_reverse( value host ) {
	struct hostent *h;
	unsigned int ip;
	val_check(host,int32);
	ip = val_int32(host);
#	if defined(NEKO_WINDOWS) || defined(NEKO_MAC)
	h = gethostbyaddr((char *)&ip,4,AF_INET);
#	else
	struct hostent htmp;
	int errcode;
	char buf[1024];
	gethostbyaddr_r((char *)&ip,4,AF_INET,&htmp,buf,1024,&h,&errcode);
#	endif
	if( h == NULL )
		neko_error();
	return alloc_string( h->h_name );
}
Ejemplo n.º 12
0
struct hostent *gethostbyaddr(const char *addr, int len, int type)
{
	struct res_data *data = _res_init();

	if (!data)
		return NULL;
	if (!data->buf) {
		data->buf = malloc(sizeof(struct hostent) + HOST_BUFSIZE);
		if (!data->buf) {
			errno = 0;
			data->errval = NO_RECOVERY;
			return NULL;
		}
	}
	return gethostbyaddr_r(addr, len, type, (struct hostent *) data->buf,
						   data->buf + sizeof(struct hostent), HOST_BUFSIZE,
						   &data->errval);
}
Ejemplo n.º 13
0
HL_PRIM vbyte *hl_host_reverse( int ip ) {
	struct hostent *h;
	hl_blocking(true);
#	if defined(HL_WIN) || defined(HL_MAC) || defined(HL_IOS) || defined(HL_TVOS) || defined(HL_CYGWIN) || defined(HL_CONSOLE)
	h = gethostbyaddr((char *)&ip,4,AF_INET);
#	elif defined(__ANDROID__)
	hl_error("hl_host_reverse() not available for this platform");
#	else
	struct hostent htmp;
	int errcode;
	char buf[1024];
	gethostbyaddr_r((char*)&ip,4,AF_INET,&htmp,buf,1024,&h,&errcode);
#	endif
	hl_blocking(false);
	if( h == NULL )
		return NULL;
	return (vbyte*)h->h_name;
}
Ejemplo n.º 14
0
/**
	host_reverse : 'int32 -> string
	<doc>Reverse the DNS of the given IP address.</doc>
**/
static value host_reverse( value host ) {
	struct hostent *h;
	unsigned int ip;
	val_check(host,int);
	ip = val_int(host);
   gc_enter_blocking();
#	if defined(NEKO_WINDOWS) || defined(NEKO_MAC) || defined(ANDROID) || defined(BLACKBERRY)
	h = gethostbyaddr((char *)&ip,4,AF_INET);
#	else
	struct hostent htmp;
	int errcode;
	char buf[1024];
	gethostbyaddr_r((char *)&ip,4,AF_INET,&htmp,buf,1024,&h,&errcode);
#	endif
   gc_exit_blocking();
	if( h == NULL )
		return alloc_null();
	return alloc_string( h->h_name );
}
Ejemplo n.º 15
0
int
main()
{
    char           *address;
    int            length;
    int            type;
    struct hostent h;
    char           buffer[8192];
    int            h_errnop;
    struct hostent *hp;

#ifndef gethostbyaddr_r
    (void)gethostbyaddr_r;
#endif
    hp = gethostbyaddr_r(address, length, type, &h,
                         buffer, 8192, &h_errnop);
    ;
    return 0;
}
int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host,
		size_t hostlen, char *serv, size_t servlen, int flags) {
  sa_family_t f=((struct sockaddr_storage *)sa)->ss_family;
  (void)salen;	/* shut gcc up about unused salen */
  if (host && hostlen>0) {	/* user wants me to resolve the host name */
    register const char*addr=(f==AF_INET6)?(char*)&((struct sockaddr_in6*)sa)->sin6_addr:
					   (char*)&((struct sockaddr_in*)sa)->sin_addr;
    if (flags&NI_NUMERICHOST) {
      if (!inet_ntop(f,addr,host,hostlen))
	return EAI_NONAME;
    } else {
      char buf[4096];
      struct hostent h;
      struct hostent *H;
      int herrno;
      if (gethostbyaddr_r(addr,f==AF_INET6?16:4,f,&h,buf,4096,&H,&herrno)) {
	switch (herrno) {
	case TRY_AGAIN: return EAI_AGAIN;
	case NO_DATA:
	case HOST_NOT_FOUND: return EAI_NONAME;
	}
      }
      strncpy(host,h.h_name,hostlen-1);
      host[hostlen-1]=0;
    }
  }
  if (serv && servlen>0) {
    register short int port=(f==AF_INET6)?((struct sockaddr_in6*)sa)->sin6_port:((struct sockaddr_in*)sa)->sin_port;
    if (flags&NI_NUMERICSERV) {
      __ltostr(serv,servlen,ntohs(port),10,0);
    } else {
      struct servent *s;
      if (!(s=getservbyport(port,flags&NI_DGRAM?"udp":"tcp")))
	return EAI_SERVICE;
      strncpy(serv,s->s_name,servlen-1);
      serv[servlen-1]=0;
    }
  }
  return 0;
}
Ejemplo n.º 17
0
static int
do_ipv46(char *host, size_t hostlen, char *serv, size_t servlen,
		 void *aptr, size_t alen, int family, int port)
{
	struct hostent		*hptr, hent;
	struct servent		*sptr, sent;
	char				hentbuf[HENTBUFSIZ];

	if (hostlen > 0) {
#ifdef	REENTRANT
		hptr = gethostbyaddr_r(aptr, alen, family,
							   &hent, hentbuf, HENTBUFSIZ, &h_errno);
#else
		hptr = gethostbyaddr(aptr, alen, family);
#endif
		if (hptr != NULL && hptr->h_name != NULL)
			strncpy(host, hptr->h_name, hostlen);
		else
			return(1);
	}

	if (servlen > 0) {
		/*
		 * Notice that we do not have enough information to pass a
		 * "protocol" argument to getservbyport(), so the assumption
		 * is that the protocol (TCP or UDP) does not matter.
		 */
#ifdef	REENTRANT
		sptr = getservbyport_r(port, NULL,
							   &sent, hentbuf, HENTBUFSIZ);
#else
		sptr = getservbyport(port, NULL);
#endif
		if (sptr != NULL && sptr->s_name != NULL)
			strncpy(serv, sptr->s_name, servlen);
		else
			return(1);
	}
	return(0);
}
Ejemplo n.º 18
0
int main(void) {
    struct in_addr localhost;
    struct hostent hostbuf, *hp;
    char *buf;
    int res, herr;
    size_t buflen = 1024;
    
    localhost.s_addr = htonl(INADDR_LOOPBACK);
    buf = malloc(buflen);
    while ((res = gethostbyaddr_r((char*)&localhost, sizeof localhost, AF_INET,
                                  &hostbuf, buf, buflen, &hp, &herr))
                    == ERANGE)
        buf = (char*)realloc(buf, buflen *= 2);

    /* We assume that the loopback address can always be resolved if
     * gethostbyaddr_r is actually working. */
    if (res || hp == NULL) {
        fprintf(stderr, "errno = %d, herr = %d, res = %d\n", errno, herr, res);
        return -1;
    } else
        return 0;
}
Ejemplo n.º 19
0
static char *get_peer(int sd, char *buffer)
{
int addrlen, h_errno;
struct sockaddr_in cli_addr, *cli_addrp;
struct hostent *hp, result;
static char *fid = "get_peer";
 
    addrlen = sizeof(cli_addr);
    cli_addrp = &cli_addr;
    if (getpeername(sd, (struct sockaddr *)cli_addrp, &addrlen) != 0) {
        util_log(1, "%s: getpeername: %s", fid, syserrmsg(errno));
        return NULL;
    }
#ifdef SOLARIS
    hp = gethostbyaddr_r(
        (char *) &cli_addrp->sin_addr,
        sizeof(struct in_addr),
        cli_addrp->sin_family,
        &result,
        buffer,
        MAXPATHLEN,
        &h_errno
    );
#else
    hp = gethostbyaddr(
        (char *) &cli_addrp->sin_addr,
        sizeof(struct in_addr),
        cli_addrp->sin_family
    );
#endif
    if (hp != NULL) {
        strcpy(buffer, hp->h_name);
    } else {
        strcpy(buffer, inet_ntoa(cli_addrp->sin_addr));
    }

    return buffer;
}
Ejemplo n.º 20
0
/* begin pr_ipv4 */
void
pr_ipv4(char **listptr)
{
    struct in_addr	inaddr;
    struct hostent	*hptr, hent;
    char			buf[8192];
    int				h_errno;

    for ( ; *listptr != NULL; listptr++)
    {
        inaddr = *((struct in_addr *) (*listptr));
        printf("	IPv4 address: %s", Inet_ntoa(inaddr));

        if ( (hptr = gethostbyaddr_r((char *) &inaddr, sizeof(struct in_addr),
                                     AF_INET, &hent,
                                     buf, sizeof(buf), &h_errno)) == NULL)
            printf("    (gethostbyaddr failed: %s)\n", hstrerror(h_errno));
        else if (hptr->h_name != NULL)
            printf("    name = %s\n", hptr->h_name);
        else
            printf("    (no hostname returned by gethostbyaddr)\n");
    }
}
Ejemplo n.º 21
0
struct hostent *
solaris_gethostbyaddr_r (const char *host, int hostlen, struct hostent *he, char *buffer, int buflen, int *error)
{
	*error = 0;
	return gethostbyaddr_r (host, hostlen, AF_INET, he, buffer, buflen, error);
}
Ejemplo n.º 22
0
APR_DECLARE(apr_status_t) apr_getnameinfo(char **hostname,
                                          apr_sockaddr_t *sockaddr,
                                          apr_int32_t flags)
{
#if defined(HAVE_GETNAMEINFO)
    int rc;
#if defined(NI_MAXHOST)
    char tmphostname[NI_MAXHOST];
#else
    char tmphostname[256];
#endif

    /* don't know if it is portable for getnameinfo() to set h_errno;
     * clear it then see if it was set */
    SET_H_ERRNO(0);

    /* default flags are NI_NAMREQD; otherwise, getnameinfo() will return
     * a numeric address string if it fails to resolve the host name;
     * that is *not* what we want here
     *
     * For IPv4-mapped IPv6 addresses, drop down to IPv4 before calling
     * getnameinfo() to avoid getnameinfo bugs (MacOS X, glibc).
     */
#if APR_HAVE_IPV6
    if (sockaddr->family == AF_INET6 &&
        IN6_IS_ADDR_V4MAPPED(&sockaddr->sa.sin6.sin6_addr)) {
        struct sockaddr_in tmpsa;
        tmpsa.sin_family = AF_INET;
        tmpsa.sin_port = 0;
        tmpsa.sin_addr.s_addr = ((apr_uint32_t *)sockaddr->ipaddr_ptr)[3];
#ifdef SIN6_LEN
        tmpsa.sin_len = sizeof(tmpsa);
#endif

        rc = getnameinfo((const struct sockaddr *)&tmpsa, sizeof(tmpsa),
                         tmphostname, sizeof(tmphostname), NULL, 0,
                         flags != 0 ? flags : NI_NAMEREQD);
    }
    else
#endif
    rc = getnameinfo((const struct sockaddr *)&sockaddr->sa, sockaddr->salen,
                     tmphostname, sizeof(tmphostname), NULL, 0,
                     flags != 0 ? flags : NI_NAMEREQD);
    if (rc != 0) {
        *hostname = NULL;

#ifndef WIN32
        /* something went wrong. Look at the EAI_ error code */
        if (rc == EAI_SYSTEM) {
            /* EAI_SYSTEM      System error returned in errno. */
            /* IMHO, Implementations that set h_errno a simply broken. */
            if (h_errno) { /* for broken implementations which set h_errno */
                return h_errno + APR_OS_START_SYSERR;
            }
            else { /* "normal" case */
                return errno + APR_OS_START_SYSERR;
            }
        }
        else 
#endif
        {
#if defined(NEGATIVE_EAI)
            if (rc < 0) rc = -rc;
#endif
            return rc + APR_OS_START_EAIERR; /* return the EAI_ error */
        }
    }
    *hostname = sockaddr->hostname = apr_pstrdup(sockaddr->pool, 
                                                 tmphostname);
    return APR_SUCCESS;
#else
#if APR_HAS_THREADS && !defined(GETHOSTBYADDR_IS_THREAD_SAFE) && \
    defined(HAVE_GETHOSTBYADDR_R) && !defined(BEOS)
#ifdef GETHOSTBYNAME_R_HOSTENT_DATA
    struct hostent_data hd;
#else
    char tmp[GETHOSTBYNAME_BUFLEN];
#endif
    int hosterror;
    struct hostent hs, *hptr;

#if defined(GETHOSTBYNAME_R_HOSTENT_DATA)
    /* AIX, HP/UX, D/UX et alia */
    gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr, 
                  sizeof(struct in_addr), AF_INET, &hs, &hd);
    hptr = &hs;
#else
#if defined(GETHOSTBYNAME_R_GLIBC2)
    /* Linux glibc2+ */
    gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr, 
                    sizeof(struct in_addr), AF_INET,
                    &hs, tmp, GETHOSTBYNAME_BUFLEN - 1, &hptr, &hosterror);
#else
    /* Solaris, Irix et alia */
    hptr = gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr, 
                           sizeof(struct in_addr), AF_INET,
                           &hs, tmp, GETHOSTBYNAME_BUFLEN, &hosterror);
#endif /* !defined(GETHOSTBYNAME_R_GLIBC2) */
    if (!hptr) {
        *hostname = NULL;
        return hosterror + APR_OS_START_SYSERR;
    }
#endif /* !defined(GETHOSTBYNAME_R_HOSTENT_DATA) */
#else
    struct hostent *hptr;
    hptr = gethostbyaddr((char *)&sockaddr->sa.sin.sin_addr, 
                         sizeof(struct in_addr), AF_INET);
#endif

    if (hptr) {
        *hostname = sockaddr->hostname = apr_pstrdup(sockaddr->pool, hptr->h_name);
        return APR_SUCCESS;
    }
    *hostname = NULL;
#if defined(WIN32)
    return apr_get_netos_error();
#elif defined(OS2)
    return h_errno;
#else
    return h_errno + APR_OS_START_SYSERR;
#endif
#endif
}
Ejemplo n.º 23
0
//
// Returns a string:
//
// host (ip address)
//
std::string TcpSocket::getClientName() const
{

	//
	// Get the name of the client.
	//
	struct sockaddr_in lvClient;
	int lvClientSize = sizeof( lvClient );
	memset( & lvClient, 0, sizeof( lvClient ) );

#if !defined( WIN32 )
	const int lvStatus = getpeername( getSocketId(), ( struct sockaddr * )& lvClient,
		( socklen_t * )& lvClientSize );
#else // defined( WIN32 )
	const int lvStatus = getpeername( getSocketId(), ( struct sockaddr * )& lvClient,
		& lvClientSize );
#endif // defined( WIN32 )

	if ( 0 > lvStatus )
	{

		//throw exception
		std::ostringstream streamErrInfo;
		std::string strErrorInfo;

		streamErrInfo << "Unable to determine peer name";
		strErrorInfo = streamErrInfo.str();

		throw std::exception(strErrorInfo.c_str());
	}

	//
	// Resolve the network address.
	//
	int nClientPort = lvClient.sin_port;//client port
	std::string lvAddress = inet_ntoa( lvClient.sin_addr );//client ip
	struct hostent *lvHostPtr = 0;
	int lvAddr = inet_addr( lvAddress.c_str() );
#if defined( SOLARIS )
	struct hostent lvHost;
	char lvData[ 256 ];
	int lvError = 0;
	lvHostPtr = gethostbyaddr_r( ( char * )& lvAddr, sizeof( lvAddr ),
		AF_INET, & lvHost, lvData,
		sizeof( lvData ), & lvError );
#else // !defined( SOLARIS )
	lvHostPtr = gethostbyaddr( ( const char * )& lvAddr, sizeof( lvAddr ),
		AF_INET );//client host name
#endif // !defined( SOLARIS )

#if 0
	//
	// Now construct the string.
	//
	std::string lvAddressString;

	// If we can't resolve, just use the raw IP... an exception isn't required.
	if ( lvHostPtr == NULL )
	{
		lvAddressString.append( lvAddress );
	}
	else
	{
		lvAddressString.append( lvHostPtr->h_name );
	}

	lvAddressString.append( " (" );
	lvAddressString.append( lvAddress );
	lvAddressString.append( ")" );

#endif


	//
	// Now construct the string.
	//
	std::string lvAddressString;
	std::ostringstream streamInfo;
	if ( lvHostPtr == NULL )
	{
		streamInfo << lvAddress;
	}
	else
	{
		streamInfo << lvHostPtr->h_name;
	}
	streamInfo <<" (" << lvAddress << ":" << nClientPort << ")";

	lvAddressString = streamInfo.str();
	
	return lvAddressString;
}
Ejemplo n.º 24
0
int ldap_pvt_gethostbyaddr_a(
	const char *addr,
	int len,
	int type,
	struct hostent *resbuf,
	char **buf,
	struct hostent **result,
	int *herrno_ptr )
{
#if defined( HAVE_GETHOSTBYADDR_R )

# undef NEED_SAFE_REALLOC
# define NEED_SAFE_REALLOC   
	int r=-1;
	int buflen=BUFSTART;
	*buf = NULL;   
	for(;buflen<BUFMAX;) {
		if (safe_realloc( buf, buflen )==NULL)
			return r;
#if (GETHOSTBYADDR_R_NARGS < 8)
		*result=gethostbyaddr_r( addr, len, type,
			resbuf, *buf, buflen, herrno_ptr );
		r = (*result == NULL) ? -1 : 0;
#else
		r = gethostbyaddr_r( addr, len, type,
			resbuf, *buf, buflen, 
			result, herrno_ptr );
#endif

#ifdef NETDB_INTERNAL
		if ((r<0) &&
			(*herrno_ptr==NETDB_INTERNAL) &&
			(errno==ERANGE))
		{
			buflen*=2;
			continue;
		}
#endif
		return r;
	}
	return -1;
#elif defined( LDAP_R_COMPILE )
# undef NEED_COPY_HOSTENT
# define NEED_COPY_HOSTENT   
	struct hostent *he;
	int	retval;
	*buf = NULL;   
	
	ldap_pvt_thread_mutex_lock( &ldap_int_resolv_mutex );
	
	he = gethostbyaddr( addr, len, type );
	
	if (he==NULL) {
		*herrno_ptr = h_errno;
		retval = -1;
	} else if (copy_hostent( resbuf, buf, he )<0) {
		*herrno_ptr = -1;
		retval = -1;
	} else {
		*result = resbuf;
		retval = 0;
	}
	
	ldap_pvt_thread_mutex_unlock( &ldap_int_resolv_mutex );
	
	return retval;

#else /* gethostbyaddr() */
	*buf = NULL;   
	*result = gethostbyaddr( addr, len, type );

	if (*result!=NULL) {
		return 0;
	}
	return -1;
#endif	
}
Ejemplo n.º 25
0
int ldap_pvt_get_hname(
	const struct sockaddr *sa,
	int len,
	char *name,
	int namelen,
	char **err )
{
	int rc;
#if defined( HAVE_GETNAMEINFO )

#if defined( LDAP_R_COMPILE )
	ldap_pvt_thread_mutex_lock( &ldap_int_resolv_mutex );
#endif
	rc = getnameinfo( sa, len, name, namelen, NULL, 0, 0 );
#if defined( LDAP_R_COMPILE )
	ldap_pvt_thread_mutex_unlock( &ldap_int_resolv_mutex );
#endif
	if ( rc ) *err = (char *)AC_GAI_STRERROR( rc );
	return rc;

#else /* !HAVE_GETNAMEINFO */
	char *addr;
	int alen;
	struct hostent *hp = NULL;
#ifdef HAVE_GETHOSTBYADDR_R
	struct hostent hb;
	int buflen=BUFSTART, h_errno;
	char *buf=NULL;
#endif

#ifdef LDAP_PF_INET6
	if (sa->sa_family == AF_INET6) {
		struct sockaddr_in6 *sin = (struct sockaddr_in6 *)sa;
		addr = (char *)&sin->sin6_addr;
		alen = sizeof(sin->sin6_addr);
	} else
#endif
	if (sa->sa_family == AF_INET) {
		struct sockaddr_in *sin = (struct sockaddr_in *)sa;
		addr = (char *)&sin->sin_addr;
		alen = sizeof(sin->sin_addr);
	} else {
		rc = NO_RECOVERY;
		*err = (char *)HSTRERROR( rc );
		return rc;
	}
#if defined( HAVE_GETHOSTBYADDR_R )
	for(;buflen<BUFMAX;) {
		if (safe_realloc( &buf, buflen )==NULL) {
			*err = (char *)STRERROR( ENOMEM );
			return ENOMEM;
		}
#if (GETHOSTBYADDR_R_NARGS < 8)
		hp=gethostbyaddr_r( addr, alen, sa->sa_family,
			&hb, buf, buflen, &h_errno );
		rc = (hp == NULL) ? -1 : 0;
#else
		rc = gethostbyaddr_r( addr, alen, sa->sa_family,
			&hb, buf, buflen, 
			&hp, &h_errno );
#endif
#ifdef NETDB_INTERNAL
		if ((rc<0) &&
			(h_errno==NETDB_INTERNAL) &&
			(errno==ERANGE))
		{
			buflen*=2;
			continue;
		}
#endif
		break;
	}
	if (hp) {
		strncpy( name, hp->h_name, namelen );
	} else {
		*err = (char *)HSTRERROR( h_errno );
	}
	LDAP_FREE(buf);
#else /* HAVE_GETHOSTBYADDR_R */

#if defined( LDAP_R_COMPILE )
	ldap_pvt_thread_mutex_lock( &ldap_int_resolv_mutex );
#endif
	hp = gethostbyaddr( addr, alen, sa->sa_family );
	if (hp) {
		strncpy( name, hp->h_name, namelen );
		rc = 0;
	} else {
		rc = h_errno;
		*err = (char *)HSTRERROR( h_errno );
	}
#if defined( LDAP_R_COMPILE )
	ldap_pvt_thread_mutex_unlock( &ldap_int_resolv_mutex );
#endif

#endif	/* !HAVE_GETHOSTBYADDR_R */
	return rc;
#endif	/* !HAVE_GETNAMEINFO */
}
Ejemplo n.º 26
0
int ResolveUtil::getHostnameByAddress(bsl::string        *canonicalHostname,
                                      const IPv4Address&  address,
                                      int                *errorCode)
{
    BSLS_ASSERT(canonicalHostname);

    struct hostent *hp = NULL;
    unsigned int    addr = address.ipAddress();   // in network order

#if defined(BSLS_PLATFORM_OS_AIX)
    struct hostent      hent;
    struct hostent_data hdt;

    if (gethostbyaddr_r(reinterpret_cast<char *>(&addr),
                        sizeof (struct in_addr),
                        AF_INET,
                        &hent,
                        &hdt)) {
        if (errorCode) {
            *errorCode = h_errno;
        }
        return -1;                                                    // RETURN
    }

    *canonicalHostname = hent.h_name;

#elif defined(BSLS_PLATFORM_OS_SUNOS) || defined(BSLS_PLATFORM_OS_SOLARIS)
    struct hostent hent;
    char           hdt[2048];
    int            err;

    hp = gethostbyaddr_r(reinterpret_cast<char *>(&addr),
                         sizeof (struct in_addr),
                         AF_INET,
                         &hent,
                         hdt,
                         sizeof(hdt),
                         &err);

    if (0 == hp) {
        if (errorCode) {
            *errorCode = err;
        }
        return -1;                                                    // RETURN
    }

    *canonicalHostname = hp->h_name;

#elif defined(BSLS_PLATFORM_OS_LINUX) \
   || defined(BSLS_PLATFORM_OS_FREEBSD)
    struct hostent hent;
    char           hdt[2048];
    int            err;

    if (gethostbyaddr_r(reinterpret_cast<char *>(&addr),
                        sizeof (struct in_addr),
                        AF_INET,
                        &hent,
                        hdt,
                        sizeof(hdt),
                        &hp,
                        &err) || 0 == hp) {
        if (errorCode) {
            *errorCode = err;
        }
        return -1;                                                    // RETURN
    }

    *canonicalHostname = hp->h_name;

#elif defined(BSLS_PLATFORM_OS_UNIX)
    // Standard call cannot be assumed to be re-entrant (it often is not).
    {
        static bslmt::Mutex            mutex;
        bslmt::LockGuard<bslmt::Mutex> guard(&mutex);

        hp = gethostbyaddr(reinterpret_cast<char *>(&addr),
                           sizeof (struct in_addr),
                           AF_INET);

        if (0 == hp) {
            if (errorCode) {
#ifdef BSLS_PLATFORM_OS_HPUX
                *errorCode = h_errno;
#else
                *errorCode = errno;
#endif
            }
            return -1;                                                // RETURN
        }

        *canonicalHostname = hp->h_name;
    }

#elif defined(BSLS_PLATFORM_OS_WINDOWS)
    unsigned short port = address.portNumber();  // in host order

    struct sockaddr_in saGNI;
    char               hostName[NI_MAXHOST];
    char               servInfo[NI_MAXSERV];

    saGNI.sin_family = AF_INET;
    saGNI.sin_addr.s_addr = addr;
    saGNI.sin_port = htons(port);

    if (getnameinfo(reinterpret_cast<SOCKADDR *>(&saGNI),
                    sizeof(sockaddr),
                    hostName,
                    sizeof(hostName),
                    servInfo,
                    sizeof(servInfo),
                    NI_NUMERICSERV|NI_NAMEREQD)) {
        if (errorCode) {
            *errorCode = WSAGetLastError();
        }
        return -1;                                                    // RETURN
    }

    *canonicalHostname = hostName; // a Fully Qualified Domain Name (FQDN)

#else

#error getHostnameByAddress does not handle current platform type!

#endif

    return 0;
}
Ejemplo n.º 27
0
static int
gaih_inet(const char *name, const struct gaih_service *service,
		const struct addrinfo *req, struct addrinfo **pai)
{
	struct gaih_servtuple nullserv;

	const struct gaih_typeproto *tp = gaih_inet_typeproto;
	struct gaih_servtuple *st = &nullserv;
	struct gaih_addrtuple *at = NULL;
	int rc;
	int v4mapped = (req->ai_family == PF_UNSPEC || req->ai_family == PF_INET6)
			&& (req->ai_flags & AI_V4MAPPED);
	unsigned seen = __check_pf();

	memset(&nullserv, 0, sizeof(nullserv));

	if (req->ai_protocol || req->ai_socktype) {
		++tp;
		while (tp->name[0]
			&& ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
			    || (req->ai_protocol != 0 && !(tp->protoflag & GAI_PROTO_PROTOANY) && req->ai_protocol != tp->protocol)
			)
		) {
			++tp;
		}
		if (! tp->name[0]) {
			if (req->ai_socktype)
				return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE);
			return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
		}
	}

	if (service != NULL) {
		if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
			return (GAIH_OKIFUNSPEC | -EAI_SERVICE);

		if (service->num < 0) {
			if (tp->name[0]) {
				st = alloca(sizeof(struct gaih_servtuple));
				rc = gaih_inet_serv(service->name, tp, req, st);
				if (rc)
					return rc;
			} else {
				struct gaih_servtuple **pst = &st;
				for (tp++; tp->name[0]; tp++) {
					struct gaih_servtuple *newp;

					if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
						continue;

					if (req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
						continue;
					if (req->ai_protocol != 0
					 && !(tp->protoflag & GAI_PROTO_PROTOANY)
					 && req->ai_protocol != tp->protocol)
						continue;

					newp = alloca(sizeof(struct gaih_servtuple));
					rc = gaih_inet_serv(service->name, tp, req, newp);
					if (rc) {
						if (rc & GAIH_OKIFUNSPEC)
							continue;
						return rc;
					}

					*pst = newp;
					pst = &(newp->next);
				}
				if (st == &nullserv)
					return (GAIH_OKIFUNSPEC | -EAI_SERVICE);
			}
		} else {
			st = alloca(sizeof(struct gaih_servtuple));
			st->next = NULL;
			st->socktype = tp->socktype;
			st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
					? req->ai_protocol : tp->protocol);
			st->port = htons(service->num);
		}
	} else if (req->ai_socktype || req->ai_protocol) {
		st = alloca(sizeof(struct gaih_servtuple));
		st->next = NULL;
		st->socktype = tp->socktype;
		st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
				? req->ai_protocol : tp->protocol);
		st->port = 0;
	} else {
		/*
		 * Neither socket type nor protocol is set.  Return all socket types
		 * we know about.
		 */
		struct gaih_servtuple **lastp = &st;
		for (++tp; tp->name[0]; ++tp) {
			struct gaih_servtuple *newp;

			newp = alloca(sizeof(struct gaih_servtuple));
			newp->next = NULL;
			newp->socktype = tp->socktype;
			newp->protocol = tp->protocol;
			newp->port = 0;

			*lastp = newp;
			lastp = &newp->next;
		}
	}

	if (name != NULL) {
		at = alloca(sizeof(struct gaih_addrtuple));
		at->family = AF_UNSPEC;
		at->scopeid = 0;
		at->next = NULL;

		if (inet_pton(AF_INET, name, at->addr) > 0) {
			if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET || v4mapped)
				at->family = AF_INET;
			else
				return -EAI_FAMILY;
		}

#if defined __UCLIBC_HAS_IPV6__
		if (at->family == AF_UNSPEC) {
			char *namebuf = strdupa(name);
			char *scope_delim;

			scope_delim = strchr(namebuf, SCOPE_DELIMITER);
			if (scope_delim != NULL)
				*scope_delim = '\0';

			if (inet_pton(AF_INET6, namebuf, at->addr) > 0) {
				if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
					at->family = AF_INET6;
				else
					return -EAI_FAMILY;

				if (scope_delim != NULL) {
					int try_numericscope = 0;
					if (IN6_IS_ADDR_LINKLOCAL(at->addr) || IN6_IS_ADDR_MC_LINKLOCAL(at->addr)) {
						at->scopeid = if_nametoindex(scope_delim + 1);
						if (at->scopeid == 0)
							try_numericscope = 1;
					} else
						try_numericscope = 1;

					if (try_numericscope != 0) {
						char *end;
						assert(sizeof(uint32_t) <= sizeof(unsigned long));
						at->scopeid = (uint32_t)strtoul(scope_delim + 1, &end, 10);
						if (*end != '\0')
							return (GAIH_OKIFUNSPEC | -EAI_NONAME);
					}
				}
			}
		}
#endif

		if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0) {
			struct hostent *h;
			struct gaih_addrtuple **pat = &at;
			int no_data = 0;
			int no_inet6_data;

			/*
			 * If we are looking for both IPv4 and IPv6 address we don't want
			 * the lookup functions to automatically promote IPv4 addresses to
			 * IPv6 addresses.
			 */
#if defined __UCLIBC_HAS_IPV6__
			if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
				if (!(req->ai_flags & AI_ADDRCONFIG) || (seen & SEEN_IPV6))
					gethosts(AF_INET6, struct in6_addr);
#endif
			no_inet6_data = no_data;

			if (req->ai_family == AF_INET
			 || (!v4mapped && req->ai_family == AF_UNSPEC)
			 || (v4mapped && (no_inet6_data != 0 || (req->ai_flags & AI_ALL)))
			) {
				if (!(req->ai_flags & AI_ADDRCONFIG) || (seen & SEEN_IPV4))
					gethosts(AF_INET, struct in_addr);
			}

			if (no_data != 0 && no_inet6_data != 0) {
				/* If both requests timed out report this. */
				if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
					return -EAI_AGAIN;
				/*
				 * We made requests but they turned out no data.
				 * The name is known, though.
				 */
				return (GAIH_OKIFUNSPEC | -EAI_AGAIN);
			}
		}

		if (at->family == AF_UNSPEC)
			return (GAIH_OKIFUNSPEC | -EAI_NONAME);
	} else {
		struct gaih_addrtuple *atr;

		atr = at = alloca(sizeof(struct gaih_addrtuple));
		memset(at, '\0', sizeof(struct gaih_addrtuple));
		if (req->ai_family == 0) {
			at->next = alloca(sizeof(struct gaih_addrtuple));
			memset(at->next, '\0', sizeof(struct gaih_addrtuple));
		}
#if defined __UCLIBC_HAS_IPV6__
		if (req->ai_family == 0 || req->ai_family == AF_INET6) {
			at->family = AF_INET6;
			if ((req->ai_flags & AI_PASSIVE) == 0)
				memcpy(at->addr, &in6addr_loopback, sizeof(struct in6_addr));
			atr = at->next;
		}
#endif
		if (req->ai_family == 0 || req->ai_family == AF_INET) {
			atr->family = AF_INET;
			if ((req->ai_flags & AI_PASSIVE) == 0)
				*(uint32_t*)atr->addr = htonl(INADDR_LOOPBACK);
		}
	}

	if (pai == NULL)
		return 0;

	{
		const char *c = NULL;
		struct gaih_servtuple *st2;
		struct gaih_addrtuple *at2 = at;
		size_t socklen, namelen;
		sa_family_t family;

		/*
		 * 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 != NULL) {
			if (req->ai_flags & AI_CANONNAME) {
				struct hostent *h = NULL;
				int herrno;
				struct hostent th;
				size_t tmpbuflen = 512;
				char *tmpbuf;

				do {
					tmpbuflen *= 2;
					tmpbuf = alloca(tmpbuflen);
					//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 == errno && herrno == NETDB_INTERNAL);

				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 defined __UCLIBC_HAS_IPV6__
			if (at2->family == AF_INET6 || v4mapped) {
				family = AF_INET6;
				socklen = sizeof(struct sockaddr_in6);
			}
#endif
#if defined __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__
			else
#endif
#if defined __UCLIBC_HAS_IPV4__
			{
				family = AF_INET;
				socklen = sizeof(struct sockaddr_in);
			}
#endif
			for (st2 = st; st2 != NULL; st2 = st2->next) {
				if (req->ai_flags & AI_ADDRCONFIG) {
					if (family == AF_INET && !(seen & SEEN_IPV4))
						break;
#if defined __UCLIBC_HAS_IPV6__
					else if (family == AF_INET6 && !(seen & SEEN_IPV6))
						break;
#endif
				}
				*pai = malloc(sizeof(struct addrinfo) + socklen + namelen);
				if (*pai == NULL)
					return -EAI_MEMORY;

				(*pai)->ai_flags = req->ai_flags;
				(*pai)->ai_family = 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
				(*pai)->ai_addr->sa_len = socklen;
#endif /* SALEN */
				(*pai)->ai_addr->sa_family = family;

#if defined __UCLIBC_HAS_IPV6__
				if (family == AF_INET6)	{
					struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *) (*pai)->ai_addr;

					sin6p->sin6_flowinfo = 0;
					if (at2->family == AF_INET6) {
						memcpy(&sin6p->sin6_addr,
							at2->addr, sizeof(struct in6_addr));
					} else {
						sin6p->sin6_addr.s6_addr32[0] = 0;
						sin6p->sin6_addr.s6_addr32[1] = 0;
						sin6p->sin6_addr.s6_addr32[2] = htonl(0x0000ffff);
						memcpy(&sin6p->sin6_addr.s6_addr32[3],
							at2->addr, sizeof(sin6p->sin6_addr.s6_addr32[3]));
					}
					sin6p->sin6_port = st2->port;
					sin6p->sin6_scope_id = at2->scopeid;
				}
#endif
#if defined __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__
				else
#endif
#if defined __UCLIBC_HAS_IPV4__
				{
					struct sockaddr_in *sinp = (struct sockaddr_in *) (*pai)->ai_addr;

					memcpy(&sinp->sin_addr, at2->addr, sizeof(struct in_addr));
					sinp->sin_port = st2->port;
					memset(sinp->sin_zero, '\0', sizeof(sinp->sin_zero));
				}
#endif
				if (c) {
					(*pai)->ai_canonname = ((void *) (*pai) +
							sizeof(struct addrinfo) + socklen);
					strcpy((*pai)->ai_canonname, c);
				} else {
					(*pai)->ai_canonname = NULL;
				}
				(*pai)->ai_next = NULL;
				pai = &((*pai)->ai_next);
			}

			at2 = at2->next;
		}
	}
	return 0;
}
Ejemplo n.º 28
0
int
getnameinfo(struct sockaddr const  *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen,
	    unsigned int flags)
{
    const struct sockaddr_in *sin = (struct sockaddr_in const *)sa;
    struct hostent *hp;
    struct hostent result;
    char tmpserv[16];
    char buffer[2048];
    int error;

    if (serv) {
	snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port));
	if (strlen(tmpserv) > servlen)
	    return EAI_MEMORY;
	else
	    strcpy(serv, tmpserv);
    }
    if (host) {
	if (flags & NI_NUMERICHOST) {
	    /*  No Reverse DNS lookup */
	    if (flags & NI_NAMEREQD)
		return EAI_NONAME;
	    if (strlen(inet_ntoa(sin->sin_addr)) >= hostlen)
		return EAI_MEMORY;
	    else {
		strcpy(host, inet_ntoa(sin->sin_addr));
		return 0;
	    }
	} else {
	/*  Reverse DNS lookup required */
#ifdef GETHOSTBYADDRRSTYLE
#if GETHOSTBYADDRRSTYLE == SYSVSTYLE
	    hp = gethostbyaddr_r((char const *)&sin->sin_addr,
			       salen, AF_INET,
			       &result, buffer, sizeof(buffer), &error);
#elif GETHOSTBYADDRRSTYLE == GNUSTYLE
	    if (gethostbyaddr_r((char const *)&sin->sin_addr,
			       salen, AF_INET,
				    &result, buffer, sizeof(buffer),
				    &hp, &error) != 0) {
			hp = NULL;
	     }
#else
	    hp = gethostbyaddr_r((char const *)&sin->sin_addr,
			       salen, AF_INET,
			       &result, buffer, sizeof(buffer), &error);
#endif
#else
	    hp = gethostbyaddr_r((char const *)&sin->sin_addr,
			       salen, AF_INET,
			       &result, buffer, sizeof(buffer), &error);
#endif
	    if (hp)
		if (strlen(hp->h_name) >= hostlen)
		    return EAI_MEMORY;
		else {
		    strcpy(host, hp->h_name);
		    return 0;
		}
	    else if (flags & NI_NAMEREQD)
		return EAI_NONAME;
	    else if (strlen(inet_ntoa(sin->sin_addr)) >= hostlen)
		return EAI_MEMORY;
	    else {
		strcpy(host, inet_ntoa(sin->sin_addr));
		return 0;
	    }
	}
    }
    return 0;
}
static int
camel_gethostbyaddr_r (const char *addr, int addrlen, int type, struct hostent *host,
		       char *buf, size_t buflen, int *herr)
{
#ifdef ENABLE_IPv6
	int retval, len;

	if ((retval = getnameinfo (addr, addrlen, buf, buflen, NULL, 0, NI_NAMEREQD)) != 0) {
		*herr = ai_to_herr (retval);
		return -1;
	}

	len = ALIGN (strlen (buf) + 1);
	if (buflen < IPv6_BUFLEN_MIN + len + addrlen + sizeof (char *))
		return ERANGE;

	/* h_name */
	host->h_name = buf;
	buf += len;

	/* h_aliases */
	((char **) buf)[0] = NULL;
	host->h_aliases = (char **) buf;
	buf += sizeof (char *);

	/* h_addrtype and h_length */
	host->h_length = addrlen;
	host->h_addrtype = type;

	memcpy (buf, addr, host->h_length);
	addr = buf;
	buf += ALIGN (host->h_length);

	/* h_addr_list */
	((char **) buf)[0] = addr;
	((char **) buf)[1] = NULL;
	host->h_addr_list = (char **) buf;

	return 0;
#else /* No support for IPv6 addresses */
#ifdef HAVE_GETHOSTBYADDR_R
#ifdef GETHOSTBYADDR_R_SEVEN_ARGS
	if (gethostbyaddr_r (addr, addrlen, type, host, buf, buflen, herr))
		return 0;
	else
		return errno;
#else
	struct hostent *hp;
	int retval;

	retval = gethostbyaddr_r (addr, addrlen, type, host, buf, buflen, &hp, herr);
	if (hp != NULL) {
		*herr = 0;
		retval = 0;
	} else if (retval == 0) {
		/* glibc 2.3.2 workaround - it seems that
		 * gethostbyaddr_r will sometimes return 0 on fail and
		 * fill @host with garbage strings from /etc/hosts
		 * (failure to parse the file? who knows). Luckily, it
		 * seems that we can rely on @hp being NULL on
		 * fail.
		 */
		retval = -1;
	}

	return retval;
#endif
#else /* No support for gethostbyaddr_r */
	struct hostent *h;

	G_LOCK (gethost_mutex);

	h = gethostbyaddr (addr, addrlen, type);

	if (!h) {
		*herr = h_errno;
		G_UNLOCK (gethost_mutex);
		return -1;
	}

	GETHOST_PROCESS (h, host, buf, buflen, herr);

	G_UNLOCK (gethost_mutex);

	return 0;
#endif /* HAVE_GETHOSTBYADDR_R */
#endif /* ENABLE_IPv6 */
}
Ejemplo n.º 30
0
/*
 * We are guaranteed that the packet received is a BOOTP request packet,
 * e.g., *NOT* a DHCP packet.
 */
void
bootp(dsvc_clnt_t *pcd, PKT_LIST *plp)
{
	boolean_t	result, existing_offer = B_FALSE;
	int		err, write_error = DSVC_SUCCESS, flags = 0;
	int		pkt_len;
	uint_t		crecords = 0, irecords = 0, srecords = 0, clen;
	uint32_t	query;
	PKT		*rep_pktp = NULL;
	IF		*ifp = pcd->ifp;
	dsvc_dnet_t	*pnd = pcd->pnd;
	uchar_t		*optp;
	dn_rec_t	dn, ndn, *dnp;
	dn_rec_list_t	*dncp = NULL, *dnip = NULL, *dnlp = NULL;
	struct in_addr	ciaddr;
	struct in_addr	no_ip;	/* network order IP */
	ENCODE		*ecp, *hecp;
	MACRO		*mp, *nmp, *cmp;
	time_t		now = time(NULL);
	DHCP_MSG_CATEGORIES	log;
	struct		hostent	h, *hp;
	char		ntoab[INET_ADDRSTRLEN], cipbuf[INET_ADDRSTRLEN];
	char		cidbuf[DHCP_MAX_OPT_SIZE];
	char		hbuf[NSS_BUFLEN_HOSTS];

	ciaddr.s_addr = htonl(INADDR_ANY);

#ifdef	DEBUG
	dhcpmsg(LOG_DEBUG, "BOOTP request received on %s\n", ifp->nm);
#endif	/* DEBUG */

	if (pcd->off_ip.s_addr != htonl(INADDR_ANY) &&
	    PCD_OFFER_TIMEOUT(pcd, now))
		purge_offer(pcd, B_TRUE, B_TRUE);

	if (pcd->off_ip.s_addr != htonl(INADDR_ANY)) {
		existing_offer = B_TRUE;
		dnlp = pcd->dnlp;
		assert(dnlp != NULL);
		dnp = dnlp->dnl_rec;
		no_ip.s_addr = htonl(dnp->dn_cip.s_addr);
		crecords = 1;
	} else {
		/*
		 * Try to find a CID entry for the client. We don't care about
		 * lease info here, since a BOOTP client always has a permanent
		 * lease. We also don't care about the entry owner either,
		 * unless we end up allocating a new entry for the client.
		 */
		DSVC_QINIT(query);

		DSVC_QEQ(query, DN_QCID);
		(void) memcpy(dn.dn_cid, pcd->cid, pcd->cid_len);
		dn.dn_cid_len = pcd->cid_len;

		DSVC_QEQ(query, DN_QFBOOTP_ONLY);
		dn.dn_flags = DN_FBOOTP_ONLY;

		/*
		 * If a client address (ciaddr) is given, we simply trust that
		 * the client knows what it's doing, and we use that IP address
		 * to locate the client's record. If we can't find the client's
		 * record, then we keep silent. If the client id of the record
		 * doesn't match this client, then either the client or our
		 * database is inconsistent, and we'll ignore it (notice
		 * message generated).
		 */
		ciaddr.s_addr = plp->pkt->ciaddr.s_addr;
		if (ciaddr.s_addr != htonl(INADDR_ANY)) {
			DSVC_QEQ(query, DN_QCIP);
			dn.dn_cip.s_addr = ntohl(ciaddr.s_addr);
		}

		dnlp = dhcp_lookup_dd_classify(pcd->pnd, B_FALSE, query,
		    -1, &dn, (void **)&dncp, S_CID);
		if (dnlp != NULL) {
			crecords = 1;
			dnp = dnlp->dnl_rec;
			if (dnp->dn_flags & DN_FUNUSABLE)
				goto leave_bootp;
			no_ip.s_addr = htonl(dnp->dn_cip.s_addr);
		}
	}

	(void) inet_ntop(AF_INET, &no_ip, cipbuf, sizeof (cipbuf));

	if (crecords == 0 && !be_automatic) {
		if (verbose) {
			dhcpmsg(LOG_INFO, "BOOTP client: %1$s is looking for "
			    "a configuration on net %2$s\n", pcd->cidbuf,
			    pnd->network);
		}
		goto leave_bootp;
	}

	/*
	 * If the client thinks it knows who it is (ciaddr), and this doesn't
	 * match our registered IP address, then display an error message and
	 * give up.
	 */
	if (ciaddr.s_addr != htonl(INADDR_ANY) && crecords == 0) {
		/*
		 * If the client specified an IP address, then let's check
		 * whether it is available, since we have no CID mapping
		 * registered for this client. If it is available and
		 * unassigned but owned by a different server, we ignore the
		 * client.
		 */
		DSVC_QINIT(query);

		DSVC_QEQ(query, DN_QCIP);
		dn.dn_cip.s_addr = ntohl(ciaddr.s_addr);
		(void) inet_ntop(AF_INET, &ciaddr, cipbuf, sizeof (cipbuf));

		DSVC_QEQ(query, DN_QFBOOTP_ONLY);
		dn.dn_flags = DN_FBOOTP_ONLY;

		dnip = NULL;
		dnlp = dhcp_lookup_dd_classify(pcd->pnd, B_FALSE, query,
		    -1, &dn, (void **)&dncp, S_CID);
		if (dnlp == NULL) {
			/*
			 * We have no record of this client's IP address, thus
			 * we really can't respond to this client, because it
			 * doesn't have a configuration.
			 */
			if (verbose) {
				dhcpmsg(LOG_INFO, "No configuration for BOOTP "
				    "client: %1$s. IP address: %2$s not "
				    "administered by this server.\n",
				    pcd->cidbuf, inet_ntop(AF_INET, &ciaddr,
				    ntoab, sizeof (ntoab)));
			}
			goto leave_bootp;
		} else
			irecords = 1;

		dnp = dnlp->dnl_rec;
		if (dnp->dn_flags & DN_FUNUSABLE)
			goto leave_bootp;

		if (dn.dn_cid_len != 0) {
			if (dn.dn_cid_len != pcd->cid_len || memcmp(dn.dn_cid,
			    pcd->cid, pcd->cid_len) != 0) {
				if (verbose) {
					clen = sizeof (cidbuf);
					(void) octet_to_hexascii(dn.dn_cid,
					    dn.dn_cid_len, cidbuf, &clen);
					dhcpmsg(LOG_INFO, "BOOTP client: %1$s "
					    "thinks it owns %2$s, but that "
					    "address belongs to %3$s. Ignoring "
					    "client.\n", pcd->cidbuf, cipbuf,
					    cidbuf);
				}
				goto leave_bootp;
			}
		} else {
			if (match_ownerip(htonl(dn.dn_sip.s_addr)) == NULL) {
				if (verbose) {
					no_ip.s_addr =
					    htonl(dnp->dn_sip.s_addr);
					dhcpmsg(LOG_INFO, "BOOTP client: %1$s "
					    "believes it owns %2$s. That "
					    "address is free, but is owned by "
					    "DHCP server %3$s. Ignoring "
					    "client.\n", pcd->cidbuf, cipbuf,
					    inet_ntop(AF_INET, &no_ip, ntoab,
					    sizeof (ntoab)));
				}
				goto leave_bootp;
			}
		}
		no_ip.s_addr = htonl(dnp->dn_cip.s_addr);
		(void) inet_ntop(AF_INET, &no_ip, cipbuf, sizeof (cipbuf));
	}

	if (crecords == 0) {
		/*
		 * The dhcp-network table did not have any matching entries.
		 * Try to allocate a new one if possible.
		 */
		if (irecords == 0 && select_offer(pnd, plp, pcd, &dnlp)) {
			dnp = dnlp->dnl_rec;
			no_ip.s_addr = htonl(dnp->dn_cip.s_addr);
			(void) inet_ntop(AF_INET, &no_ip, cipbuf,
			    sizeof (cipbuf));
			srecords = 1;
		}
	}

	if (crecords == 0 && irecords == 0 && srecords == 0) {
		dhcpmsg(LOG_NOTICE,
		    "(%1$s) No more BOOTP IP addresses for %2$s network.\n",
		    pcd->cidbuf, pnd->network);
		goto leave_bootp;
	}

	/* Check the address. But only if client doesn't know its address. */
	ndn = *dnp;	/* struct copy */
	no_ip.s_addr = htonl(ndn.dn_cip.s_addr);
	(void) inet_ntop(AF_INET, &no_ip, cipbuf, sizeof (cipbuf));
	if (ciaddr.s_addr == htonl(INADDR_ANY)) {
		if ((ifp->flags & IFF_NOARP) == 0)
			(void) set_arp(ifp, &no_ip, NULL, 0, DHCP_ARP_DEL);
		if (!noping) {
			/*
			 * If icmp echo check fails,
			 * let the plp fall by the wayside.
			 */
			errno = icmp_echo_check(&no_ip, &result);
			if (errno != 0) {
				dhcpmsg(LOG_ERR, "ICMP ECHO check cannot be "
				    "performed for: %s, ignoring\n", cipbuf);
				goto leave_bootp;
			}
			if (result) {
				dhcpmsg(LOG_ERR, "ICMP ECHO reply to BOOTP "
				    "OFFER candidate: %s, disabling.\n",
				    cipbuf);

				ndn.dn_flags |= DN_FUNUSABLE;

				if ((err = dhcp_modify_dd_entry(pnd->dh,
				    dnp, &ndn)) == DSVC_SUCCESS) {
					/* Keep the cached entry current. */
					*dnp = ndn;    /* struct copy */
				}

				logtrans(P_BOOTP, L_ICMP_ECHO, 0, no_ip,
				    server_ip, plp);

				goto leave_bootp;
			}
		}
	}

	/*
	 * It is possible that the client could specify a REQUEST list,
	 * but then it would be a DHCP client, wouldn't it? Only copy the
	 * std option list, since that potentially could be changed by
	 * load_options().
	 */
	ecp = NULL;
	if (!no_dhcptab) {
		open_macros();
		if ((nmp = get_macro(pnd->network)) != NULL)
			ecp = dup_encode_list(nmp->head);
		if ((mp = get_macro(dnp->dn_macro)) != NULL)
			ecp = combine_encodes(ecp, mp->head, ENC_DONT_COPY);
		if ((cmp = get_macro(pcd->cidbuf)) != NULL)
			ecp = combine_encodes(ecp, cmp->head, ENC_DONT_COPY);

		/* If dhcptab configured to return hostname, do so. */
		if (find_encode(ecp, DSYM_INTERNAL, CD_BOOL_HOSTNAME) !=
		    NULL) {
			hp = gethostbyaddr_r((char *)&ndn.dn_cip,
			    sizeof (struct in_addr), AF_INET, &h, hbuf,
			    sizeof (hbuf), &err);
			if (hp != NULL) {
				hecp = make_encode(DSYM_STANDARD,
				    CD_HOSTNAME, strlen(hp->h_name),
				    hp->h_name, ENC_COPY);
				replace_encode(&ecp, hecp, ENC_DONT_COPY);
			}
		}
	}

	/* Produce a BOOTP reply. */
	rep_pktp = gen_bootp_pkt(sizeof (PKT), plp->pkt);

	rep_pktp->op = BOOTREPLY;
	optp = rep_pktp->options;

	/*
	 * Set the client's "your" IP address if client doesn't know it,
	 * otherwise echo the client's ciaddr back to him.
	 */
	if (ciaddr.s_addr == htonl(INADDR_ANY))
		rep_pktp->yiaddr.s_addr = htonl(ndn.dn_cip.s_addr);
	else
		rep_pktp->ciaddr.s_addr = ciaddr.s_addr;

	/*
	 * Omit lease time options implicitly, e.g.
	 * ~(DHCP_DHCP_CLNT | DHCP_SEND_LEASE)
	 */

	if (!plp->rfc1048)
		flags |= DHCP_NON_RFC1048;

	/* Now load in configured options. */
	pkt_len = load_options(flags, plp, rep_pktp, sizeof (PKT), optp, ecp,
	    NULL);

	free_encode_list(ecp);
	if (!no_dhcptab)
		close_macros();

	if (pkt_len < sizeof (PKT))
		pkt_len = sizeof (PKT);

	/*
	 * Only perform a write if we have selected an entry not yet
	 * assigned to the client (a matching DN_FBOOTP_ONLY entry from
	 * ip address lookup, or an unassigned entry from select_offer()).
	 */
	if (srecords > 0 || irecords > 0) {
		(void) memcpy(&ndn.dn_cid, pcd->cid, pcd->cid_len);
		ndn.dn_cid_len = pcd->cid_len;

		write_error = dhcp_modify_dd_entry(pnd->dh, dnp, &ndn);

		/* Keep state of the cached entry current. */
		*dnp = ndn;	/* struct copy */

		log = L_ASSIGN;
	} else {
		if (verbose) {
			dhcpmsg(LOG_INFO, "Database write unnecessary for "
			    "BOOTP client: %1$s, %2$s\n",
			    pcd->cidbuf, cipbuf);
		}
		log = L_REPLY;
	}

	if (write_error == DSVC_SUCCESS) {
		if (send_reply(ifp, rep_pktp, pkt_len, &no_ip) != 0) {
			dhcpmsg(LOG_ERR,
			    "Reply to BOOTP client %1$s with %2$s failed.\n",
			    pcd->cidbuf, cipbuf);
		} else {
			/* Note that the conversation has completed. */
			pcd->state = ACK;

			(void) update_offer(pcd, &dnlp, 0, &no_ip, B_TRUE);
			existing_offer = B_TRUE;
		}

		logtrans(P_BOOTP, log, ndn.dn_lease, no_ip, server_ip, plp);
	}

leave_bootp:
	if (rep_pktp != NULL)
		free(rep_pktp);
	if (dncp != NULL)
		dhcp_free_dd_list(pnd->dh, dncp);
	if (dnip != NULL)
		dhcp_free_dd_list(pnd->dh, dnip);
	if (dnlp != NULL && !existing_offer)
		dhcp_free_dd_list(pnd->dh, dnlp);
}