--- squid-3.2.0.16.orig/src/ip//Address.cc 2012-03-12 17:26:53.395525059 +0400 +++ squid-3.2.0.16/src/ip//Address.cc 2012-03-26 17:39:16.234967644 +0400 @@ -53,6 +53,12 @@ #include #endif +//// Temporary hack for uclibc getaddrinfo problem +#ifdef __UCLIBC__ +#include "AddressLookupHack.cc" +#endif /* __UCLIBC__ */ +//// + /* Debugging only. Dump the address content when a fatal assert is encountered. */ #define IASSERT(a,b) \ if(!(b)){ printf("assert \"%s\" at line %d\n", a, __LINE__); \ @@ -395,21 +401,34 @@ struct addrinfo *res = NULL; struct addrinfo want; + + int (* __getaddrinfo) (const char *nodename, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) = &getaddrinfo; + + void (* __freeaddrinfo) (struct addrinfo *ai) = &freeaddrinfo; memset(&want, 0, sizeof(struct addrinfo)); if (nodns) { want.ai_flags = AI_NUMERICHOST; // prevent actual DNS lookups! + +#ifdef __UCLIBC__ + //HACK: set __getaddrinfo dynamically since uClibc function + // doesn't really care about AI_NUMERICHOST, which can lead + // to performance downgrade! [AK] + __getaddrinfo = &xgetaddrinfo; + __freeaddrinfo = &xfreeaddrinfo; +#endif /* __UCLIBC__ */ } #if 0 else if (!Ip::EnableIpv6) want.ai_family = AF_INET; // maybe prevent IPv6 DNS lookups. #endif - if ( (err = getaddrinfo(s, NULL, &want, &res)) != 0) { + if ( (err = __getaddrinfo(s, NULL, &want, &res)) != 0) { debugs(14,3, HERE << "Given Non-IP '" << s << "': " << gai_strerror(err) ); /* free the memory getaddrinfo() dynamically allocated. */ if (res) { - freeaddrinfo(res); + __freeaddrinfo(res); res = NULL; } return false; @@ -424,7 +443,7 @@ SetPort(port); /* free the memory getaddrinfo() dynamically allocated. */ - freeaddrinfo(res); + __freeaddrinfo(res); res = NULL; --- squid-3.2.0.16.orig/src/ip//AddressLookupHack.cc 1970-01-01 03:00:00.000000000 +0300 +++ squid-3.2.0.16/src/ip//AddressLookupHack.cc 2012-03-26 16:56:30.090828275 +0400 @@ -0,0 +1,116 @@ +/* + * Hack for uClibc getaddrinfo() problems in Ip::Address + * AUTHOR: Alexander Komyagin + * + * By now it seems that uClibc getaddrinfo() totally ingnores + * AF_NUMERICHOST hint flag. That leads to a very huge + * performance downgrade (especially with additional overhead + * provided by RSBAC Networking when enabled). + * + */ + +//all these were gracefully taken from +// squid compat and reduced when necessary +// to fit their particular purpose in our +// situation + +static struct addrinfo * +dup_addrinfo (struct addrinfo *info, void *addr, size_t addrlen) { + struct addrinfo *ret; + + ret = (struct addrinfo *)malloc (sizeof (struct addrinfo)); + if (ret == NULL) + return NULL; + memcpy (ret, info, sizeof (struct addrinfo)); + ret->ai_addr = (struct sockaddr *)malloc (addrlen); + if (ret->ai_addr == NULL) { + free (ret); + return NULL; + } + memcpy (ret->ai_addr, addr, addrlen); + ret->ai_addrlen = addrlen; + return ret; +} + +static int +xgetaddrinfo (const char *nodename, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) +{ + int port = 0; + struct addrinfo result; + int ret; + + if (servname == NULL && nodename == NULL) + return EAI_NONAME; + + memset (&result, 0, sizeof result); + + assert(hints != NULL); + assert(servname == NULL); + + /* if nodename == NULL refer to the local host for a client or any + for a server */ + if (nodename == NULL) { + struct sockaddr_in sin; + + /* check protocol family is PF_UNSPEC or PF_INET - could try harder + for IPv6 but that's more code than I'm prepared to write */ + if (hints->ai_family == PF_UNSPEC || hints->ai_family == PF_INET) + result.ai_family = AF_INET; + else + return EAI_FAMILY; + + sin.sin_family = result.ai_family; + sin.sin_port = htons (port); + if (hints->ai_flags & AI_PASSIVE) + sin.sin_addr.s_addr = htonl (INADDR_ANY); + else + sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + /* Duplicate result and addr and return */ + *res = dup_addrinfo (&result, &sin, sizeof sin); + return (*res == NULL) ? EAI_MEMORY : 0; + } + + /* If AI_NUMERIC is specified, use xinet_pton to translate numbers and + dots notation. */ + assert(hints->ai_flags & AI_NUMERICHOST); + + struct sockaddr_in sin; + + /* check protocol family is PF_UNSPEC or PF_INET */ + if (hints->ai_family == PF_UNSPEC || hints->ai_family == PF_INET) + result.ai_family = AF_INET; + else + return EAI_FAMILY; + + sin.sin_family = result.ai_family; + sin.sin_port = htons (port); + + ret = inet_pton(result.ai_family, nodename, &sin.sin_addr); + if (ret != 1) + { + debugs(14,3, HERE << "inet_pton: " << ret); + return EAI_NONAME; + } + sin.sin_addr.s_addr = inet_addr (nodename); + /* Duplicate result and addr and return */ + *res = dup_addrinfo (&result, &sin, sizeof sin); + return (*res == NULL) ? EAI_MEMORY : 0; +} + +static void +xfreeaddrinfo (struct addrinfo *ai) +{ + struct addrinfo *next; + + while (ai != NULL) { + next = ai->ai_next; + if (ai->ai_canonname != NULL) + free (ai->ai_canonname); + if (ai->ai_addr != NULL) + free (ai->ai_addr); + free (ai); + ai = next; + } +} +