From: amosjeffries <> Date: Fri, 11 Jan 2008 10:49:18 +0000 (+0000) Subject: AAAA/A failover fix and CNAME recursion deprecation X-Git-Tag: BASIC_TPROXY4~197 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bae9832dd15d8221a56cae6e5f8c699a8621ce2d;p=thirdparty%2Fsquid.git AAAA/A failover fix and CNAME recursion deprecation A bug in the final version of squid internal DNS resolver logics caused any failover A results to overwrite the paired previous AAAA. This patch adds state to store the DNS results between failover queries and to merge the final sets before passing them out to the requestor. Lookups should now be seemlessly handled within the DNS resolver stub. CNAME recursion at the ipcache level should now be obsolete and has been wrapped in a new ./configure --with-dns-cname option which defaults off. That code has proven to be problematic anyway and will be no great loss. Additional counters have been added to the squid statistics to track the amount of queries of each type have been encountered. --- diff --git a/configure.in b/configure.in index b0248288b0..976104b0aa 100644 --- a/configure.in +++ b/configure.in @@ -1,7 +1,7 @@ dnl Configuration input file for Squid dnl -dnl $Id: configure.in,v 1.493 2007/12/27 15:48:53 hno Exp $ +dnl $Id: configure.in,v 1.494 2008/01/11 03:49:18 amosjeffries Exp $ dnl dnl dnl @@ -11,7 +11,7 @@ AM_CONFIG_HEADER(include/autoconf.h) AC_CONFIG_AUX_DIR(cfgaux) AC_CONFIG_SRCDIR([src/main.cc]) AM_INIT_AUTOMAKE([tar-ustar]) -AC_REVISION($Revision: 1.493 $)dnl +AC_REVISION($Revision: 1.494 $)dnl AC_PREFIX_DEFAULT(/usr/local/squid) AM_MAINTAINER_MODE @@ -1790,6 +1790,15 @@ AC_ARG_WITH(localhost-ipv6, # end IPv6-only options fi +dnl Optional CNAME-Recursion by Internal DNS engine +AC_MSG_CHECKING([whether DNS CNAME recursion wanted]) +AC_ARG_WITH(dns-cname, + [ --with-dns-cname Enable CNAME-Recursion in Internal DNS stub.], + [AC_DEFINE(DNS_CNAME, 1, [ 1 == Enable expermental CNAME recursion inside Squid DNS resolver stub]) AC_MSG_RESULT(yes)], + [AC_DEFINE(DNS_CNAME, 0, [ 0 == Disable expermental CNAME recursion inside Squid DNS resolver stub]) AC_MSG_RESULT(no)] +) + + AC_ARG_WITH(filedescriptors, [ --with-filedescriptors=NUMBER Force squid to support NUMBER filedescriptors], diff --git a/doc/release-notes/release-3.1.html b/doc/release-notes/release-3.1.html index 5afdc230b0..23f45698c9 100644 --- a/doc/release-notes/release-3.1.html +++ b/doc/release-notes/release-3.1.html @@ -7,7 +7,7 @@

Squid 3.1.PRE1 release notes

-

Squid Developers

$Id: release-3.1.html,v 1.3 2008/01/11 02:38:58 amosjeffries Exp $ +

Squid Developers

$Id: release-3.1.html,v 1.4 2008/01/11 03:49:18 amosjeffries Exp $
This document contains the release notes for version 3.1 of Squid. Squid is a WWW Cache application developed by the National Laboratory @@ -50,7 +50,7 @@ While this release is not deemed ready for production use, we believe it is read

Internet Protocol version 6 (IPv6)

-

Squid 3.1 supports IPv6. To enable IPv6 support, use the --enable-ipv6 ./configure option

+

Squid 3.1 supports IPv6. To enable IPv6 support, use the ./configure --enable-ipv6 option

New Features for IPv6

@@ -185,7 +185,6 @@ Squid will follow a policy of prefering IPv6 links, keeping the IPv4 only as a s

-

Changes to existing tags

@@ -202,7 +201,9 @@ Squid will follow a policy of prefering IPv6 links, keeping the IPv4 only as a s

external_acl_type

New options 'ipv4' and 'ipv6' are added to set the IPv4/v6 protocol between squid and its helpers. -Please be aware of some limits to these options. see IPv6 Limits in section 2 above. +Please be aware of some limits to these options. These options only affet the transport protocol used +to send data to and from the helpers. Squid in IPv6-mode may still send %SRC addresses in IPv4 or IPv6 +format, so all helpers will need to be checked and converted to cope with such information cleanly.

           ipv4 / ipv6   IP-mode used to communicate to this helper.
                         For compatability with older configurations and helpers
@@ -300,7 +301,7 @@ It has thus been turned off by default. Making the 'best choice' IP continue in
 The default is to build with 127.0.0.1 and ::1 being considered seperate IP.
 see the IPv6 details above for a better description. 

-
--with-ipv6-split-stack<
+
--with-ipv6-split-stack

Enable special additions for IPv6 support in Windows XP. see the IPv6 details above for a better description.

@@ -308,6 +309,15 @@ see the IPv6 details above for a better description.

Enable special additions for IPv6 support in Windows Vista. see the IPv6 details above for a better description.

+
--with-dns-cname
+

Enable CNAME recursion within the Internal DNS resolver stub squid uses. +This has no effect on the external DNS helper. +Please note this extension is still experimental and may encounter problems. +To see if it is actually needed you can run squid without it for a period and +check the CNAME-Only Requests statistics squid maintains. +If it produces ongoing serious problems the external helper may be needed +but please report the bugs anyway.

+

Changes to existing options

diff --git a/doc/release-notes/release-3.1.man b/doc/release-notes/release-3.1.man index 2eb458621a..b183dac3b7 100644 --- a/doc/release-notes/release-3.1.man +++ b/doc/release-notes/release-3.1.man @@ -1,4 +1,4 @@ -Squid 3.1.PRE1 release notesSquid Developers$Id: release-3.1.man,v 1.3 2008/01/11 02:38:58 amosjeffries Exp $This document contains the release notes for version 3.1 of Squid. +Squid 3.1.PRE1 release notesSquid Developers$Id: release-3.1.man,v 1.4 2008/01/11 03:49:18 amosjeffries Exp $This document contains the release notes for version 3.1 of Squid. Squid is a WWW Cache application developed by the National Laboratory for Applied Network Research and members of the Web Caching community.Notice @@ -45,7 +45,7 @@ Most user-facing changes are reflected in squid.conf (see below). Internet Protocol version 6 (IPv6) .Pp -Squid 3.1 supports IPv6. To enable IPv6 support, use the --enable-ipv6 ./configure option +Squid 3.1 supports IPv6. To enable IPv6 support, use the ./configure --enable-ipv6 option .Pp New Features for IPv6 @@ -231,7 +231,6 @@ New option to import entire secondary configuration files into squid.conf. .if \n(ll>1 .RE .nr ll -1 .Pp -.Pp Changes to existing tags .Pp @@ -260,7 +259,9 @@ New preset content .nr bi 1 .Pp New options 'ipv4' and 'ipv6' are added to set the IPv4/v6 protocol between squid and its helpers. -Please be aware of some limits to these options. see IPv6 Limits in section 2 above. +Please be aware of some limits to these options. These options only affet the transport protocol used +to send data to and from the helpers. Squid in IPv6-mode may still send %SRC addresses in IPv4 or IPv6 +format, so all helpers will need to be checked and converted to cope with such information cleanly. .DS .sp .ft RR @@ -391,7 +392,7 @@ Build support for squid to map all 127.0.0.1 traffic onto ::1. The default is to build with 127.0.0.1 and ::1 being considered seperate IP. see the IPv6 details above for a better description. .Pp -.IP "--with-ipv6-split-stack<" +.IP "--with-ipv6-split-stack" .nr bi 1 .Pp Enable special additions for IPv6 support in Windows XP. @@ -403,6 +404,17 @@ see the IPv6 details above for a better description. Enable special additions for IPv6 support in Windows Vista. see the IPv6 details above for a better description. .Pp +.IP "--with-dns-cname" +.nr bi 1 +.Pp +Enable CNAME recursion within the Internal DNS resolver stub squid uses. +This has no effect on the external DNS helper. +Please note this extension is still experimental and may encounter problems. +To see if it is actually needed you can run squid without it for a period and +check the CNAME-Only Requests statistics squid maintains. +If it produces ongoing serious problems the external helper may be needed +but please report the bugs anyway. +.Pp .if \n(ll>1 .RE .nr ll -1 Changes to existing options diff --git a/doc/release-notes/release-3.1.sgml b/doc/release-notes/release-3.1.sgml index f83dd7a499..a1fd8fbdf2 100644 --- a/doc/release-notes/release-3.1.sgml +++ b/doc/release-notes/release-3.1.sgml @@ -2,7 +2,7 @@
Squid 3.1.PRE1 release notes Squid Developers -$Id: release-3.1.sgml,v 1.3 2008/01/11 02:38:58 amosjeffries Exp $ +$Id: release-3.1.sgml,v 1.4 2008/01/11 03:49:18 amosjeffries Exp $ This document contains the release notes for version 3.1 of Squid. @@ -47,7 +47,7 @@ Most user-facing changes are reflected in squid.conf (see below). Internet Protocol version 6 (IPv6) -

Squid 3.1 supports IPv6. To enable IPv6 support, use the --enable-ipv6 ./configure option +

Squid 3.1 supports IPv6. To enable IPv6 support, use the ./configure --enable-ipv6 option New Features for IPv6 @@ -168,7 +168,6 @@ This section gives a thorough account of those changes in three categories: - Changes to existing tags

@@ -182,7 +181,9 @@ This section gives a thorough account of those changes in three categories: external_acl_type

New options 'ipv4' and 'ipv6' are added to set the IPv4/v6 protocol between squid and its helpers. - Please be aware of some limits to these options. see IPv6 Limits in section 2 above. + Please be aware of some limits to these options. These options only affet the transport protocol used + to send data to and from the helpers. Squid in IPv6-mode may still send %SRC addresses in IPv4 or IPv6 + format, so all helpers will need to be checked and converted to cope with such information cleanly. ipv4 / ipv6 IP-mode used to communicate to this helper. For compatability with older configurations and helpers @@ -267,7 +268,7 @@ This section gives an account of those changes in three categories: see the IPv6 details above for a better description.

- --with-ipv6-split-stack< + --with-ipv6-split-stack

Enable special additions for IPv6 support in Windows XP. see the IPv6 details above for a better description.

@@ -275,6 +276,16 @@ This section gives an account of those changes in three categories:

Enable special additions for IPv6 support in Windows Vista. see the IPv6 details above for a better description.

+ --with-dns-cname +

Enable CNAME recursion within the Internal DNS resolver stub squid uses. + This has no effect on the external DNS helper. + Please note this extension is still experimental and may encounter problems. + To see if it is actually needed you can run squid without it for a period and + check the CNAME-Only Requests statistics squid maintains. + If it produces ongoing serious problems the external helper may be needed + but please report the bugs anyway. +

+

diff --git a/include/rfc1035.h b/include/rfc1035.h index 8ef3625c53..81ab436640 100644 --- a/include/rfc1035.h +++ b/include/rfc1035.h @@ -1,5 +1,5 @@ /* - * $Id: rfc1035.h,v 1.19 2007/12/14 23:11:44 amosjeffries Exp $ + * $Id: rfc1035.h,v 1.20 2008/01/11 03:49:20 amosjeffries Exp $ * * AUTHOR: Duane Wessels * @@ -95,6 +95,7 @@ SQUIDCEXTERN int rfc1035MessageUnpack(const char *buf, size_t sz, rfc1035_message ** answer); SQUIDCEXTERN int rfc1035QueryCompare(const rfc1035_query *, const rfc1035_query *); +SQUIDCEXTERN void rfc1035RRDestroy(rfc1035_rr ** rr, int n); SQUIDCEXTERN void rfc1035MessageDestroy(rfc1035_message ** message); SQUIDCEXTERN int rfc1035_errno; SQUIDCEXTERN const char *rfc1035_error_message; diff --git a/lib/rfc1035.c b/lib/rfc1035.c index c9db5520b4..70d8c2b61c 100644 --- a/lib/rfc1035.c +++ b/lib/rfc1035.c @@ -1,6 +1,6 @@ /* - * $Id: rfc1035.c,v 1.52 2007/12/19 02:36:27 amosjeffries Exp $ + * $Id: rfc1035.c,v 1.53 2008/01/11 03:49:21 amosjeffries Exp $ * * Low level DNS protocol routines * AUTHOR: Duane Wessels @@ -471,12 +471,13 @@ rfc1035SetErrno(int n) } } -static void +void rfc1035RRDestroy(rfc1035_rr ** rr, int n) { - if (*rr == NULL) + if (*rr == NULL || n < 1) { return; - assert(n > 0); + } + while (n--) { if ((*rr)[n].rdata) xfree((*rr)[n].rdata); diff --git a/src/dns_internal.cc b/src/dns_internal.cc index fc90f7eebd..7fa16a8d6b 100644 --- a/src/dns_internal.cc +++ b/src/dns_internal.cc @@ -1,6 +1,6 @@ /* - * $Id: dns_internal.cc,v 1.103 2007/12/29 17:56:25 hno Exp $ + * $Id: dns_internal.cc,v 1.104 2008/01/11 03:49:22 amosjeffries Exp $ * * DEBUG: section 78 DNS lookups; interacts with lib/rfc1035.c * AUTHOR: Duane Wessels @@ -117,6 +117,10 @@ struct _idns_query unsigned short domain; unsigned short do_searchpath; bool need_A; + struct { + int count; + rfc1035_rr *answers; + } initial_AAAA; }; struct _nsvc @@ -925,6 +929,7 @@ idnsGrokReply(const char *buf, size_t sz) } if (message->tc) { + debugs(78, 3, HERE << "Resolver requested TC (" << q->query.name << ")"); dlinkDelete(&q->lru, &lru_list); rfc1035MessageDestroy(&message); @@ -1003,7 +1008,7 @@ idnsGrokReply(const char *buf, size_t sz) if(q->need_A && (Config.onoff.dns_require_A == 1 || n <= 0 ) ) { /* ERROR or NO AAAA exist. Failover to A records. */ - /* AYJ: Apparently its also a good idea to lookup and store the A records + /* Apparently its also a good idea to lookup and store the A records * just in case the AAAA are not available when we need them. * This could occur due to number of network failings beyond our control * thus the || above allowing the user to request always both. @@ -1016,6 +1021,14 @@ idnsGrokReply(const char *buf, size_t sz) else // admin requested this. debugs(78, 3, "idnsGrokReply: " << q->name << " AAAA query done. Configured to retrieve A now also."); + // move the initial message results into the failover query for merging later. + if(n > 0) { + q->initial_AAAA.count = message->ancount; + q->initial_AAAA.answers = message->answer; + message->answer = NULL; + } + + // remove the hashed query info idnsDropMessage(message, q); q->start_t = current_time; @@ -1029,9 +1042,39 @@ idnsGrokReply(const char *buf, size_t sz) } #endif + /** If there are two result sets from preceeding AAAA and A lookups merge them with a preference for AAAA */ + if(q->initial_AAAA.count > 0 && n > 0) { + /* two sets of RR need merging */ + rfc1035_rr *result = (rfc1035_rr*) xmalloc( sizeof(rfc1035_rr)*(n + q->initial_AAAA.count) ); + rfc1035_rr *tmp = result; + + debugs(78, 6, HERE << "Merging DNS results " << q->name << " AAAA has " << q->initial_AAAA.count << " RR, A has " << n << " RR"); + + memcpy(tmp, q->initial_AAAA.answers, (sizeof(rfc1035_rr)*(q->initial_AAAA.count)) ); + tmp += q->initial_AAAA.count; + /* free the RR object without freeing its child strings (they are now taken by the copy above) */ + safe_free(q->initial_AAAA.answers); + + memcpy( tmp, message->answer, (sizeof(rfc1035_rr)*n) ); + /* free the RR object without freeing its child strings (they are now taken by the copy above) */ + safe_free(message->answer); + + message->answer = result; + n += q->initial_AAAA.count; + q->initial_AAAA.count=0; + } + else if(q->initial_AAAA.count > 0 && n <= 0) { + /* initial of dual queries was the only result set. */ + debugs(78, 6, HERE << "Merging DNS results " << q->name << " AAAA has " << q->initial_AAAA.count << " RR, A has " << n << " RR"); + rfc1035RRDestroy(&(message->answer), n); + message->answer = q->initial_AAAA.answers; + n = q->initial_AAAA.count; + } + /* else initial results were empty. just use the final set as authoritative */ + + debugs(78, 6, HERE << "Sending " << n << " DNS results to caller."); idnsCallback(q, message->answer, n, q->error); rfc1035MessageDestroy(&message); - cbdataFree(q); } diff --git a/src/ipcache.cc b/src/ipcache.cc index 7cfc5bb63a..c4a4a807dd 100644 --- a/src/ipcache.cc +++ b/src/ipcache.cc @@ -1,6 +1,6 @@ /* - * $Id: ipcache.cc,v 1.266 2008/01/10 08:13:43 amosjeffries Exp $ + * $Id: ipcache.cc,v 1.267 2008/01/11 03:49:22 amosjeffries Exp $ * * DEBUG: section 14 IP Cache * AUTHOR: Harvest Derived @@ -57,7 +57,9 @@ struct _ipcache_entry struct timeval request_time; dlink_node lru; unsigned short locks; +#if DNS_CNAME unsigned short cname_wait; +#endif struct { @@ -80,6 +82,10 @@ static struct int misses; int negative_hits; int numeric_hits; + int rr_a; + int rr_aaaa; + int rr_cname; + int cname_only; int invalid; } IpcacheStats; @@ -251,18 +257,22 @@ ipcacheAddEntry(ipcache_entry * i) { hash_link *e = (hash_link *)hash_lookup(ip_table, i->hash.key); +#if DNS_CNAME /* INET6 : should NOT be adding this entry until all CNAME have been received. */ assert(i->cname_wait == 0); +#endif if (NULL != e) { /* avoid colission */ ipcache_entry *q = (ipcache_entry *) e; +#if DNS_CNAME if(q == i) { /* can occur with Multiple-depth CNAME Recursion if parent returned early with additional */ /* just need to drop from the hash without releasing actual memory */ ipcacheRelease(q, false); } else +#endif ipcacheRelease(q); } @@ -408,6 +418,8 @@ ipcacheParse(ipcache_entry *i, rfc1035_rr * answers, int nr, const char *error_m int na = 0; int ttl = 0; const char *name = (const char *)i->hash.key; + int cname_found = 0; + i->expires = squid_curtime + Config.negativeDnsTtl; i->flags.negcached = 1; safe_free(i->addrs.in_addrs); @@ -441,6 +453,7 @@ ipcacheParse(ipcache_entry *i, rfc1035_rr * answers, int nr, const char *error_m continue; } na++; + IpcacheStats.rr_aaaa++; continue; } #endif @@ -451,11 +464,16 @@ ipcacheParse(ipcache_entry *i, rfc1035_rr * answers, int nr, const char *error_m continue; } na++; + IpcacheStats.rr_a++; continue; } /* With A and AAAA, the CNAME does not necessarily come with additional records to use. */ if (answers[k].type == RFC1035_TYPE_CNAME) { + cname_found=1; + IpcacheStats.rr_cname++; + +#if DNS_CNAME debugs(14, 5, "ipcacheParse: " << name << " CNAME " << answers[k].rdata << " (checking destination: " << i << ")."); const ipcache_addrs *res = ipcache_gethostbyname(answers[k].rdata, 0); if(res) { @@ -468,18 +486,28 @@ ipcacheParse(ipcache_entry *i, rfc1035_rr * answers, int nr, const char *error_m ipcache_nbgethostbyname(answers[k].rdata, ipcacheHandleCnameRecurse, new generic_cbdata(i) ); i->cname_wait++; } +#endif /* DNS_CNAME */ + continue; } + + // otherwise its an unknown RR. debug at level 9 since we usually want to ignore these and they are common. + debugs(14, 9, HERE << "Unknown RR type received: type=" << answers[k].type << " starting at " << &(answers[k]) ); } +#if DNS_CNAME if(na == 0 && i->cname_wait >0 ) { /* don't set any error message (yet). Allow recursion to do its work first. */ + IpcacheStats.cname_only++; return 0; } +#endif /* DNS_CNAME */ if (na == 0) { debugs(14, 1, "ipcacheParse: No Address records in response to '" << name << "'"); i->error_message = xstrdup("No Address records"); + if(cname_found) + IpcacheStats.cname_only++; return 0; } @@ -513,7 +541,9 @@ ipcacheParse(ipcache_entry *i, rfc1035_rr * answers, int nr, const char *error_m debugs(14, 3, "ipcacheParse: " << name << " #" << j << " " << i->addrs.in_addrs[j] ); j++; #endif - } else if (answers[k].type == RFC1035_TYPE_CNAME) { + } +#if DNS_CNAME + else if (answers[k].type == RFC1035_TYPE_CNAME) { debugs(14, 3, "ipcacheParse: " << name << " #x CNAME " << answers[k].rdata); const ipcache_addrs *res = ipcache_gethostbyname(answers[k].rdata, 0); if(res) { @@ -528,6 +558,7 @@ ipcacheParse(ipcache_entry *i, rfc1035_rr * answers, int nr, const char *error_m debugs(14, 9, "ipcacheParse: " << answers[k].rdata << " (CNAME) waiting on A/AAAA records."); } } +#endif /* DNS_CNAME */ if (ttl == 0 || (int) answers[k].ttl < ttl) ttl = answers[k].ttl; @@ -550,12 +581,14 @@ ipcacheParse(ipcache_entry *i, rfc1035_rr * answers, int nr, const char *error_m i->flags.negcached = 0; +#if DNS_CNAME /* SPECIAL CASE: may get here IFF CNAME received with Additional records */ /* reurn 0/'wait for further details' value. */ /* NP: 'No DNS Results' is a return -1 +msg */ if(i->cname_wait) return 0; else +#endif /* DNS_CNAME */ return i->addrs.count; } @@ -809,6 +842,14 @@ stat_ipcache_get(StoreEntry * sentry) IpcacheStats.numeric_hits); storeAppendPrintf(sentry, "IPcache Misses: %d\n", IpcacheStats.misses); + storeAppendPrintf(sentry, "IPcache Retrieved A: %d\n", + IpcacheStats.rr_a); + storeAppendPrintf(sentry, "IPcache Retrieved AAAA: %d\n", + IpcacheStats.rr_aaaa); + storeAppendPrintf(sentry, "IPcache Retrieved CNAME: %d\n", + IpcacheStats.rr_cname); + storeAppendPrintf(sentry, "IPcache CNAME-Only Response: %d\n", + IpcacheStats.cname_only); storeAppendPrintf(sentry, "IPcache Invalid Request: %d\n", IpcacheStats.invalid); storeAppendPrintf(sentry, "\n\n"); @@ -826,6 +867,7 @@ stat_ipcache_get(StoreEntry * sentry) } } +#if DNS_CNAME /** * Takes two IPAddress arrays and merges them into a single array * which is allocated dynamically to fit the number of unique addresses @@ -937,10 +979,12 @@ debugs(14,8, HERE << "A[" << t << "]=IPv6 " << aaddrs[t]); assert(outlen == fc); // otherwise something broke badly! } +#endif /* DNS_CNAME */ static void ipcacheHandleCnameRecurse(const ipcache_addrs *addrs, void *cbdata) { +#if DNS_CNAME ipcache_entry *i = NULL; char *pname = NULL; IPAddress *tmpbuf = NULL; @@ -1036,6 +1080,7 @@ ipcacheHandleCnameRecurse(const ipcache_addrs *addrs, void *cbdata) ipcacheCallback(i); } // else still more CNAME to be found. +#endif /* DNS_CNAME */ } void