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]); } }
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; }
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); }
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); }
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; }
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; }
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]); }
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; }
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; }
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; }
/** 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 ); }
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); }
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; }
/** 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 ); }
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; }
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); }
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; }
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; }
/* 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"); } }
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); }
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 }
// // 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; }
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 }
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 */ }
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; }
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; }
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 */ }
/* * 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); }