--------------------- PatchSet 5754 Date: 2007/09/26 03:59:51 Author: amosjeffries Branch: squid3-ipv6 Tag: (none) Log: Reduce duplicate addresses from dnsserver when using multiple NS getaddrinfo() used with more than one nameserver is known to return all IP results from all servers, sorted by preferred use. Until now dnsserver has returned all results found. This can cause genuine results to be dropped when duplicates fill up the 32 IP allowed in a response. Also when the response is full of IPv6 addresses buffers may truncate the final one on an overflow. This patch makes dnsserver drop all sequential duplicates as encountered reducing the occurance of these two problems. Members: src/dnsserver.cc:1.7.4.22->1.7.4.23 Index: squid3/src/dnsserver.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/dnsserver.cc,v retrieving revision 1.7.4.22 retrieving revision 1.7.4.23 diff -u -r1.7.4.22 -r1.7.4.23 --- squid3/src/dnsserver.cc 24 Sep 2007 02:15:47 -0000 1.7.4.22 +++ squid3/src/dnsserver.cc 26 Sep 2007 03:59:51 -0000 1.7.4.23 @@ -1,6 +1,6 @@ /* - * $Id: dnsserver.cc,v 1.7.4.22 2007/09/24 02:15:47 amosjeffries Exp $ + * $Id: dnsserver.cc,v 1.7.4.23 2007/09/26 03:59:51 amosjeffries Exp $ * * DEBUG: section 0 DNS Resolver * AUTHOR: Harvest Derived @@ -171,6 +171,7 @@ struct addrinfo hints; struct addrinfo *AI = NULL; struct addrinfo *aiptr = NULL; + struct addrinfo *prev_addr = NULL; int res = 0; if (0 == strcmp(buf, "$shutdown")) @@ -221,23 +222,41 @@ aiptr = AI; while(NULL != aiptr && 32 >= i) { memset(ntoabuf, 0, MAX_IPSTRLEN); + + /* getaddrinfo given a host has a nasty tendency to return duplicate addr's */ + /* BUT sorted fortunately, so we can drop most of them easily */ + if( prev_addr && + prev_addr->ai_family==aiptr->ai_family && + memcmp(aiptr->ai_addr, prev_addr->ai_addr, aiptr->ai_addrlen)==0 + ) { + prev_addr = aiptr; + aiptr = aiptr->ai_next; + continue; + } + else { + prev_addr = aiptr; + } + /* annoying inet_ntop breaks the nice code by requiring the in*_addr */ switch(aiptr->ai_family) { case AF_INET: xinet_ntop(aiptr->ai_family, &((struct sockaddr_in*)aiptr->ai_addr)->sin_addr, ntoabuf, MAX_IPSTRLEN); break; +#if USE_IPV6 case AF_INET6: xinet_ntop(aiptr->ai_family, &((struct sockaddr_in6*)aiptr->ai_addr)->sin6_addr, ntoabuf, MAX_IPSTRLEN); break; +#endif default: + aiptr = aiptr->ai_next; continue; } printf(" %s", ntoabuf); - i++; aiptr = aiptr->ai_next; } + prev_addr=NULL; printf("\n"); } }