rem: if (sa.sin_addr.s_addr != INADDR_NONE) { hePtr = gethostbyaddr_r(addr, strlen(addr), AF_INET, &he, buf, sizeof(buf), &h_errnop); if (he == NULL) { LogError("gethostbyaddr_r", h_errnop); } else if (he.h_name != NULL) { Ns_DStringAppend(dsPtr, he.h_name); status = NS_TRUE; }
add: hePtr = gethostbyaddr_r((char *) &sa.sin_addr, sizeof(struct in_addr), AF_INET, &he, buf, sizeof(buf), &h_errnop); if (hePtr == NULL) { LogError("gethostbyaddr_r", h_errnop); } else if (he.h_name != NULL) { Ns_DStringAppend(dsPtr, he.h_name); status = NS_TRUE;
context: static GetProc GetAddr;static GetProc GetHost;static int DnsGet(GetProc *getProc, Ns_DString *dsPtr,	Ns_Cache **cachePtr, char *key);#if !defined(HAVE_GETADDRINFO) && !defined(HAVE_GETNAMEINFO)static void LogError(char *func, int h_errnop);#endif/* *---------------------------------------------------------------------- * Ns_GetHostByAddr, Ns_GetAddrByHost -- * *      Convert an IP address to a hostname or vice versa. * * Results: *	See DnsGet(). * * Side effects: *      A new entry is entered into the hash table. * *---------------------------------------------------------------------- */intNs_GetHostByAddr(Ns_DString *dsPtr, char *addr){    return DnsGet(GetHost, dsPtr, &hostCache, addr);}intNs_GetAddrByHost(Ns_DString *dsPtr, char *host){    return DnsGet(GetAddr, dsPtr, &addrCache, host);}static intDnsGet(GetProc *getProc, Ns_DString *dsPtr, Ns_Cache **cachePtr, char *key){    int             status = NS_FALSE, new, timeout;    Value   	   *vPtr  = NULL;    Ns_Entry       *ePtr  = NULL;    Ns_Cache	   *cache = NULL;    time_t	    now;    /*     * Get the cache, if enabled.     */    Ns_MutexLock(&lock);    cache = *cachePtr;    timeout = cachetimeout;    Ns_MutexUnlock(&lock);    /*     * Call getProc directly or through cache.     */    if (cache == NULL) {        status = (*getProc)(dsPtr, key);    } else {	time(&now);	Ns_CacheLock(cache);	ePtr = Ns_CacheCreateEntry(cache, key, &new);	if (!new) {	    while (ePtr != NULL &&		    (vPtr = Ns_CacheGetValue(ePtr)) == NULL) {		Ns_CacheWait(cache);		ePtr = Ns_CacheFindEntry(cache, key);	    }	    if (ePtr == NULL) {	        status = NS_FALSE;	    } else if (vPtr->expires < now) {		Ns_CacheUnsetValue(ePtr);		new = 1;	    } else {		Ns_DStringAppend(dsPtr, vPtr->value);		status = NS_TRUE;	    }	}	if (new) {	    Ns_CacheUnlock(cache);	    status = (*getProc)(dsPtr, key);	    Ns_CacheLock(cache);	    ePtr = Ns_CacheCreateEntry(cache, key, &new);	    if (status != NS_TRUE) {		Ns_CacheFlushEntry(ePtr);	    } else {	    	Ns_CacheUnsetValue(ePtr);		vPtr = ns_malloc(sizeof(Value) + dsPtr->length);		vPtr->expires = now + timeout;		strcpy(vPtr->value, dsPtr->string);		Ns_CacheSetValueSz(ePtr, vPtr, 1);	    }	    Ns_CacheBroadcast(cache);	}	Ns_CacheUnlock(cache);    }    return status;}/* *---------------------------------------------------------------------- * NsEnableDNSCache -- * *      Enable DNS results caching. * * Results: *      None. * * Side effects: *	Futher DNS lookups will be cached up to given timeout. * *---------------------------------------------------------------------- */voidNsEnableDNSCache(int timeout, int maxentries){    Ns_MutexSetName(&lock, "ns:dns");    Ns_MutexLock(&lock);    cachetimeout = timeout;    hostCache = Ns_CacheCreateSz("ns:dnshost", TCL_STRING_KEYS,	(size_t) maxentries, ns_free);    addrCache = Ns_CacheCreateSz("ns:dnsaddr", TCL_STRING_KEYS,	(size_t) maxentries, ns_free);    Ns_MutexUnlock(&lock);}/* *---------------------------------------------------------------------- * GetHost, GetAddr -- * *      Perform the actual lookup by host or address. * *	NOTE: A critical section is used instead of a mutex *	to ensure waiting on a condition and not mutex spin waiting. * * Results: *      If a name can be found, the function returns NS_TRUE; otherwise,  *	it returns NS_FALSE. * * Side effects: *      Result is appended to dsPtr. * *---------------------------------------------------------------------- */#if defined(HAVE_GETNAMEINFO)static intGetHost(Ns_DString *dsPtr, char *addr){    struct sockaddr_in sa;    char buf[NI_MAXHOST];    int result;    int status = NS_FALSE;    sa.sin_family = AF_INET;    sa.sin_addr.s_addr = inet_addr(addr);    if ((result = getnameinfo((const struct sockaddr *) &sa,                    sizeof(struct sockaddr_in), buf, sizeof(buf),                    NULL, 0, NI_NAMEREQD)) != 0) {        Ns_Log(Error, "dns: getnameinfo failed: %s", gai_strerror(result));    } else {        Ns_DStringAppend(dsPtr, buf);        status = NS_TRUE;            }    return status;}#elif defined(HAVE_GETHOSTBYADDR_R)static intGetHost(Ns_DString *dsPtr, char *addr){    struct hostent he, *hePtr;    struct sockaddr_in sa;    char buf[2048];    int h_errnop;    int status = NS_FALSE;    sa.sin_addr.s_addr = inet_addr(addr);    if (sa.sin_addr.s_addr != INADDR_NONE) {        hePtr = gethostbyaddr_r(addr, strlen(addr), AF_INET, &he,                buf, sizeof(buf), &h_errnop);	if (he == NULL) {	    LogError("gethostbyaddr_r", h_errnop);	} else if (he.h_name != NULL) {	    Ns_DStringAppend(dsPtr, he.h_name);	    status = NS_TRUE;	}    }    return status;}#else/* * This version is not thread-safe, but we have no thread-safe * alternative on this platform.  Use critsec to try and serialize * calls, but beware: Tcl core as of 8.4.6 still calls gethostbyaddr() * as well, so it's still possible for two threads to call it at * the same time. */static intGetHost(Ns_DString *dsPtr, char *addr){    struct hostent *he;    struct sockaddr_in sa;    static Ns_Cs cs;    int status = NS_FALSE;    sa.sin_addr.s_addr = inet_addr(addr);    if (sa.sin_addr.s_addr != INADDR_NONE) {	Ns_CsEnter(&cs);        he = gethostbyaddr((char *) &sa.sin_addr,			   sizeof(struct in_addr), AF_INET);	if (he == NULL) {	    LogError("gethostbyaddr", h_errno);	} else if (he->h_name != NULL) {	    Ns_DStringAppend(dsPtr, he->h_name);	    status = NS_TRUE;	}	Ns_CsLeave(&cs);    }    return status;}#endif#if defined(HAVE_GETADDRINFO)static intGetAddr(Ns_DString *dsPtr, char *host){    struct addrinfo hints;    struct addrinfo *res;    int result;    int status = NS_FALSE;        memset(&hints, 0, sizeof(hints));    hints.ai_family = AF_INET;    if ((result = getaddrinfo(host, NULL, &hints, &res)) != 0) {        Ns_Log(Error, "dns: getaddrinfo failed: %s", gai_strerror(result));    } else {        Ns_DStringAppend(dsPtr, ns_inet_ntoa(                    ((struct sockaddr_in *) res->ai_addr)->sin_addr));        status = NS_TRUE;    }    return status;}#elif defined(HAVE_GETHOSTBYNAME_R)static intGetAddr(Ns_DString *dsPtr, char *host){    struct hostent he, *res;    struct in_addr ia;#ifdef HAVE_GETHOSTBYNAME_R_3    struct hostent_data data;#endif    char buf[2048];    int result;    int h_errnop;    int status = NS_FALSE;    #if defined(HAVE_GETHOSTBYNAME_R_6)    result = gethostbyname_r(host, &he, buf, sizeof(buf), &res, &h_errnop);#elif defined(HAVE_GETHOSTBYNAME_R_5)    result = gethostbyname_r(host, &he, buf, sizeof(buf), &h_errnop);#elif defined(HAVE_GETHOSTBYNAME_R_3)    result = gethostbyname_r(host, &he, &data);    h_errnop = h_errno;#endif    if (result != 0) { 	LogError("gethostbyname_r", h_errnop);    } else {        if (he.h_addr != NULL) {            ia.s_addr = ((struct in_addr *) he.h_addr)->s_addr;            Ns_DStringAppend(dsPtr, ns_inet_ntoa(ia));            status = NS_TRUE;        }    }    return status;}#else/* * This version is not thread-safe, but we have no thread-safe * alternative on this platform.  Use critsec to try and serialize * calls, but beware: Tcl core as of 8.4.6 still calls gethostbyname() * as well, so it's still possible for two threads to call it at * the same time. */static intGetAddr(Ns_DString *dsPtr, char *host){    struct hostent *he;    struct in_addr ia;    static Ns_Cs cs;    int status = NS_FALSE;    Ns_CsEnter(&cs);    he = gethostbyname(host);    if (he == NULL) {	LogError("gethostbyname", h_errno);    } else if (he->h_addr != NULL) {        ia.s_addr = ((struct in_addr *) he->h_addr)->s_addr;	Ns_DStringAppend(dsPtr, ns_inet_ntoa(ia));	status = NS_TRUE;    }    Ns_CsLeave(&cs);    return status;}