# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: henrik@henriknordstrom.net-20120106204121-\
#   zvhpl72emejmxec3
# target_branch: http://www.squid-cache.org/bzr/squid3/trunk/
# testament_sha1: 632f737bae5da0d5043420fa85eaa9e795102325
# timestamp: 2012-01-11 02:19:56 +0100
# base_revision_id: squid3@treenet.co.nz-20120105141204-\
#   wm58j1qdf5zuz6zz
# 
# Begin patch
=== modified file 'src/cf.data.pre'
--- src/cf.data.pre	2012-01-03 02:19:30 +0000
+++ src/cf.data.pre	2012-01-06 20:41:21 +0000
@@ -7238,27 +7238,6 @@
 	nameservers by setting this option to 'off'.
 DOC_END
 
-NAME: dns_v4_fallback
-TYPE: onoff
-DEFAULT: on
-LOC: Config.onoff.dns_require_A
-IFDEF: !USE_DNSHELPER
-DOC_START
-	Standard practice with DNS is to lookup either A or AAAA records
-	and use the results if it succeeds. Only looking up the other if
-	the first attempt fails or otherwise produces no results.
-
-	That policy however will cause squid to produce error pages for some
-	servers that advertise AAAA but are unreachable over IPv6.
-
-	If this is ON  squid will always lookup both AAAA and A, using both.
-	If this is OFF squid will lookup AAAA and only try A if none found.
-
-	WARNING: There are some possibly unwanted side-effects with this on:
-		*) Doubles the load placed by squid on the DNS network.
-		*) May negatively impact connection delay times.
-DOC_END
-
 NAME: dns_v4_first
 TYPE: onoff
 DEFAULT: off

=== modified file 'src/dns_internal.cc'
--- src/dns_internal.cc	2012-01-03 02:19:30 +0000
+++ src/dns_internal.cc	2012-01-06 20:30:35 +0000
@@ -127,11 +127,12 @@
     char name[NS_MAXDNAME + 1];
     char orig[NS_MAXDNAME + 1];
     ssize_t sz;
-    unsigned short msg_id; /// random query ID sent to server; changes with every query sent
+    unsigned short query_id; /// random query ID sent to server; changes with every query sent
     InstanceId<idns_query> xact_id; /// identifies our "transaction", stays constant when query is retried
 
     int nsends;
     int need_vc;
+    int pending;
 
     struct timeval start_t;
     struct timeval sent_t;
@@ -142,13 +143,12 @@
     int attempt;
     int rcode;
     idns_query *queue;
+    idns_query *slave;  // AAAA
+    idns_query *master; // A
     unsigned short domain;
     unsigned short do_searchpath;
-    bool need_A;
-    struct {
-        int count;
-        rfc1035_rr *answers;
-    } initial_AAAA;
+    rfc1035_message *message;
+    int ancount;
 };
 InstanceIdDefinitions(idns_query,  "dns");
 
@@ -249,6 +249,7 @@
 static void idnsRcodeCount(int, int);
 static CLCB idnsVCClosed;
 static unsigned short idnsQueryID(void);
+static void idnsSendSlaveAAAAQuery(idns_query *q);
 
 static void
 idnsAddNameserver(const char *buf)
@@ -670,7 +671,7 @@
     for (n = lru_list.head; n; n = n->next) {
         q = (idns_query *)n->data;
         storeAppendPrintf(sentry, "%#06x %4d %5d %10.3f %9.3f\n",
-                          (int) q->msg_id, (int) q->sz, q->nsends,
+                          (int) q->query_id, (int) q->sz, q->nsends,
                           tvSubDsec(q->start_t, current_time),
                           tvSubDsec(q->sent_t, current_time));
     }
@@ -906,8 +907,6 @@
     int ns;
 
     q->start_t = current_time;
-    q->msg_id = idnsQueryID();
-    rfc1035SetQueryID(q->buf, q->msg_id);
 
     do {
         ns = q->nsends % nns;
@@ -918,7 +917,7 @@
         } else {
             if (DnsSocketB >= 0 && nameservers[ns].S.IsIPv6())
                 y = comm_udp_sendto(DnsSocketB, nameservers[ns].S, q->buf, q->sz);
-            else if (DnsSocketA)
+            else if (DnsSocketA >= 0)
                 x = comm_udp_sendto(DnsSocketA, nameservers[ns].S, q->buf, q->sz);
         }
 
@@ -943,6 +942,7 @@
     nameservers[ns].nqueries++;
     q->queue_t = current_time;
     dlinkAdd(q, &q->lru, &lru_list);
+    q->pending = 1;
     idnsTickleQueue();
 }
 
@@ -973,7 +973,7 @@
     for (n = lru_list.tail; n; n = n->prev) {
         q = (idns_query*)n->data;
 
-        if (q->msg_id == id)
+        if (q->query_id == id)
             return q;
     }
 
@@ -1028,16 +1028,6 @@
     }
 }
 
-void
-idnsDropMessage(rfc1035_message *message, idns_query *q)
-{
-    rfc1035MessageDestroy(&message);
-    if (q->hash.key) {
-        hash_remove_link(idns_lookup_hash, &q->hash);
-        q->hash.key = NULL;
-    }
-}
-
 static void
 idnsGrokReply(const char *buf, size_t sz, int from_ns)
 {
@@ -1092,9 +1082,11 @@
     }
 #endif
 
+    dlinkDelete(&q->lru, &lru_list);
+    q->pending = 0;
+
     if (message->tc) {
         debugs(78, 3, HERE << "Resolver requested TC (" << q->query.name << ")");
-        dlinkDelete(&q->lru, &lru_list);
         rfc1035MessageDestroy(&message);
 
         if (!q->need_vc) {
@@ -1112,7 +1104,6 @@
         return;
     }
 
-    dlinkDelete(&q->lru, &lru_list);
     idnsRcodeCount(n, q->attempt);
 
     if (n < 0) {
@@ -1131,7 +1122,7 @@
             return;
         }
 
-        if (q->rcode == 3 && q->do_searchpath && q->attempt < MAX_ATTEMPT) {
+        if (q->rcode == 3 && !q->master && q->do_searchpath && q->attempt < MAX_ATTEMPT) {
             assert(NULL == message->answer);
             strcpy(q->name, q->orig);
 
@@ -1146,17 +1137,21 @@
                 q->attempt++;
             }
 
-            idnsDropMessage(message, q);
+            rfc1035MessageDestroy(&message);
 
-            if (Ip::EnableIpv6 && q->query.qtype == RFC1035_TYPE_AAAA) {
-                debugs(78, 3, "idnsGrokReply: Trying AAAA Query for " << q->name);
-                q->sz = rfc3596BuildAAAAQuery(q->name, q->buf, sizeof(q->buf), 0, &q->query, Config.dns.packet_max);
-            } else {
-                debugs(78, 3, "idnsGrokReply: Trying A Query for " << q->name);
-                // see EDNS notes at top of file why this sends 0
-                q->sz = rfc3596BuildAQuery(q->name, q->buf, sizeof(q->buf), 0, &q->query, 0);
+            // cleanup stale AAAA query
+            while (idns_query *slave = q->slave) {
+                dlinkDelete(&slave->lru, &lru_list);
+                q->slave = slave->slave;
+                rfc1035MessageDestroy(&slave->message);
+                cbdataFree(slave);
             }
-
+            
+            // Build new query
+            q->query_id = idnsQueryID();
+            debugs(78, 3, "idnsGrokReply: Trying A Query for " << q->name);
+            // see EDNS notes at top of file why this sends 0
+            q->sz = rfc3596BuildAQuery(q->name, q->buf, sizeof(q->buf), q->query_id, &q->query, 0);
             if (q->sz < 0) {
                 /* problem with query data -- query not sent */
                 idnsCallback(static_cast<idns_query *>(q->callback_data), NULL, 0, "Internal error");
@@ -1164,94 +1159,62 @@
                 return;
             }
 
-            idnsCacheQuery(q);
             idnsSendQuery(q);
-            return;
-        }
-    }
-
-    if (q->need_A && (Config.onoff.dns_require_A == 1 || n <= 0 ) ) {
-        /* ERROR or NO AAAA exist. Failover to 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.
-         */
-
-        if (n == 0)
-            debugs(78, 3, "idnsGrokReply: " << q->name << " has no AAAA records. Looking up A record instead.");
-        else if (q->need_A && n <= 0)
-            debugs(78, 3, "idnsGrokReply: " << q->name << " AAAA query failed. Trying A now instead.");
-        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);
-
-        // reset the query as an A query
-        q->nsends = 0;
-        // see EDNS notes at top of file why this sends 0
-        q->sz = rfc3596BuildAQuery(q->name, q->buf, sizeof(q->buf), 0, &q->query, 0);
-        q->need_A = false;
-
-        if (q->sz < 0) {
-            /* problem with query data -- query not sent */
-            idnsCallback(static_cast<idns_query *>(q->callback_data), NULL, 0, "Internal error");
-            cbdataFree(q);
-            return;
-        }
-
-        idnsCacheQuery(q);
-        idnsSendQuery(q);
-        return;
-    }
-
-    /** 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");
-
-        if (Config.dns.v4_first) {
-            memcpy( tmp, message->answer, (sizeof(rfc1035_rr)*n) );
-            tmp += n;
-            /* free the RR object without freeing its child strings (they are now taken by the copy above) */
-            safe_free(message->answer);
-        }
-
-        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);
-
-        if (!Config.dns.v4_first) {
-            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);
-        }
-
-        n += q->initial_AAAA.count;
-        q->initial_AAAA.count = 0;
-        message->answer = result;
-        message->ancount = n;
-    } 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;
-        message->ancount = n;
-    }
-    /* else initial results were empty. just use the final set as authoritative */
+            if (Ip::EnableIpv6)
+                idnsSendSlaveAAAAQuery(q);
+            return;
+        }
+    }
+
+    q->message = message;
+    q->ancount = n;
+
+    if (q->master)
+        q = q->master;
+
+    idns_query *q2;
+    // If any of our subqueries are still pending then wait for them to complete before continuing
+    for ( q2 = q; q2; q2 = q2->slave) {
+        if (q2->pending) {
+            return;
+        }
+    }
+
+    /* Merge results */
+    message = q->message;
+    n = q->ancount;
+    
+    while ( (q2 = q->slave) ) {
+        debugs(78, 6, HERE << "Merging DNS results " << q->name << " A has " << n << " RR, AAAA has " << q2->ancount << " RR");
+        q->slave = q2->slave;
+        if ( q2->ancount >= 0 ) {
+            if (n > 0 ) {
+                // two sets of RR need merging
+                rfc1035_rr *result = (rfc1035_rr*) xmalloc( sizeof(rfc1035_rr)*(n + q2->ancount) );
+                if (Config.dns.v4_first) {
+                    memcpy(result, message->answer, (sizeof(rfc1035_rr)*n) );
+                    memcpy(result+n, q2->message->answer, (sizeof(rfc1035_rr)*q2->ancount) );
+                } else {
+                    memcpy(result, q2->message->answer, (sizeof(rfc1035_rr)*q2->ancount) );
+                    memcpy(result+q2->ancount, message->answer, (sizeof(rfc1035_rr)*n) );
+                }
+                n += q2->ancount;
+                safe_free(message->answer);
+                message->answer = result;
+                message->ancount += q2->message->ancount;
+                safe_free(q2->message->answer);
+                q2->message->answer = NULL;
+            } else if (n < 0 || q2->ancount > 0) {
+                // first set empty / failed
+                rfc1035MessageDestroy(&message);
+                message = q->message = q2->message;
+                q2->message = NULL;
+                n = q2->ancount;
+            }
+        }
+        rfc1035MessageDestroy(&q2->message);
+        cbdataFree(q2);
+    }
 
     debugs(78, 6, HERE << "Sending " << n << " DNS results to caller.");
     idnsCallback(q, message->answer, n, rfc1035ErrorMessage(n));
@@ -1375,7 +1338,7 @@
 
         debugs(78, 3, "idnsCheckQueue: ID " << q->xact_id <<
                " QID 0x"  << std::hex << std::setfill('0')  <<
-               std::setw(4) << q->msg_id << ": timeout" );
+               std::setw(4) << q->query_id << ": timeout" );
 
         dlinkDelete(&q->lru, &lru_list);
 
@@ -1383,7 +1346,7 @@
             idnsSendQuery(q);
         } else {
             debugs(78, 2, "idnsCheckQueue: ID " << q->xact_id <<
-                   " QID 0x" << std::hex << q->msg_id <<
+                   " QID 0x" << std::hex << q->query_id <<
                    " : giving up after " << std::dec << q->nsends << " tries and " <<
                    std::setw(5)<< std::setprecision(2) << tvSubDsec(q->start_t, current_time) << " seconds");
 
@@ -1500,30 +1463,30 @@
     CBDATA_INIT_TYPE(idns_query);
 
     if (DnsSocketA < 0 && DnsSocketB < 0) {
-        Ip::Address addrA; // since we don't want to alter Config.Addrs.udp_* and dont have one of our own.
+        Ip::Address addrV6; // since we don't want to alter Config.Addrs.udp_* and dont have one of our own.
 
         if (!Config.Addrs.udp_outgoing.IsNoAddr())
-            addrA = Config.Addrs.udp_outgoing;
+            addrV6 = Config.Addrs.udp_outgoing;
         else
-            addrA = Config.Addrs.udp_incoming;
-
-        Ip::Address addrB = addrA;
-        addrA.SetIPv4();
-
-        if (Ip::EnableIpv6 && addrB.IsIPv6()) {
-            debugs(78, 2, "idnsInit: attempt open DNS socket to: " << addrB);
+            addrV6 = Config.Addrs.udp_incoming;
+
+        Ip::Address addrV4 = addrV6;
+        addrV4.SetIPv4();
+
+        if (Ip::EnableIpv6 && addrV6.IsIPv6()) {
+            debugs(78, 2, "idnsInit: attempt open DNS socket to: " << addrV6);
             DnsSocketB = comm_open_listener(SOCK_DGRAM,
                                             IPPROTO_UDP,
-                                            addrB,
+                                            addrV6,
                                             COMM_NONBLOCKING,
                                             "DNS Socket IPv6");
         }
 
-        if (addrA.IsIPv4()) {
-            debugs(78, 2, "idnsInit: attempt open DNS socket to: " << addrA);
+        if (addrV4.IsIPv4()) {
+            debugs(78, 2, "idnsInit: attempt open DNS socket to: " << addrV4);
             DnsSocketA = comm_open_listener(SOCK_DGRAM,
                                             IPPROTO_UDP,
-                                            addrA,
+                                            addrV4,
                                             COMM_NONBLOCKING,
                                             "DNS Socket IPv4");
         }
@@ -1536,12 +1499,12 @@
          */
         if (DnsSocketB >= 0) {
             comm_local_port(DnsSocketB);
-            debugs(78, 1, "DNS Socket created at " << addrB << ", FD " << DnsSocketB);
+            debugs(78, 1, "DNS Socket created at " << addrV6 << ", FD " << DnsSocketB);
             Comm::SetSelect(DnsSocketB, COMM_SELECT_READ, idnsRead, NULL, 0);
         }
         if (DnsSocketA >= 0) {
             comm_local_port(DnsSocketA);
-            debugs(78, 1, "DNS Socket created at " << addrA << ", FD " << DnsSocketA);
+            debugs(78, 1, "DNS Socket created at " << addrV4 << ", FD " << DnsSocketA);
             Comm::SetSelect(DnsSocketA, COMM_SELECT_READ, idnsRead, NULL, 0);
         }
     }
@@ -1629,6 +1592,7 @@
     q = cbdataAlloc(idns_query);
     // idns_query is POD so no constructors are called after allocation
     q->xact_id.change();
+    // no query_id on this instance.
 
     q->callback = callback;
 
@@ -1644,10 +1608,31 @@
 static void
 idnsCacheQuery(idns_query *q)
 {
-    q->hash.key = q->query.name;
+    q->hash.key = q->orig;
     hash_join(idns_lookup_hash, &q->hash);
 }
 
+static void
+idnsSendSlaveAAAAQuery(idns_query *master)
+{
+    idns_query *q = cbdataAlloc(idns_query);
+    memcpy(q->name, master->name, sizeof(q->name));
+    memcpy(q->orig, master->orig, sizeof(q->orig));
+    q->master = master;
+    q->query_id = idnsQueryID();
+    q->sz = rfc3596BuildAAAAQuery(q->name, q->buf, sizeof(q->buf), q->query_id, &q->query, Config.dns.packet_max);
+    q->slave = master->slave;
+    
+    debugs(78, 3, "idnsALookup: buf is " << q->sz << " bytes for " << q->name <<
+           ", id = 0x" << std::hex << q->query_id);
+    if (!q->sz) {
+        cbdataFree(q);
+        return;
+    }
+    master->slave = q;
+    idnsSendQuery(q);
+}
+
 void
 idnsALookup(const char *name, IDNSCB * callback, void *data)
 {
@@ -1661,6 +1646,7 @@
     q = cbdataAlloc(idns_query);
     // idns_query is POD so no constructors are called after allocation
     q->xact_id.change();
+    q->query_id = idnsQueryID();
 
     for (i = 0; i < strlen(name); i++)
         if (name[i] == '.')
@@ -1682,14 +1668,8 @@
         debugs(78, 3, "idnsALookup: searchpath used for " << q->name);
     }
 
-    if (Ip::EnableIpv6) {
-        q->sz = rfc3596BuildAAAAQuery(q->name, q->buf, sizeof(q->buf), 0, &q->query, Config.dns.packet_max);
-        q->need_A = true;
-    } else {
-        // see EDNS notes at top of file why this sends 0
-        q->sz = rfc3596BuildAQuery(q->name, q->buf, sizeof(q->buf), 0, &q->query, 0);
-        q->need_A = false;
-    }
+    // see EDNS notes at top of file why this sends 0
+    q->sz = rfc3596BuildAQuery(q->name, q->buf, sizeof(q->buf), q->query_id, &q->query, 0);
 
     if (q->sz < 0) {
         /* problem with query data -- query not sent */
@@ -1699,13 +1679,17 @@
     }
 
     debugs(78, 3, "idnsALookup: buf is " << q->sz << " bytes for " << q->name <<
-           ", id = 0x" << std::hex << q->msg_id);
+           ", id = 0x" << std::hex << q->query_id);
 
     q->callback = callback;
     q->callback_data = cbdataReference(data);
 
     idnsCacheQuery(q);
     idnsSendQuery(q);
+
+    if (Ip::EnableIpv6)
+        idnsSendSlaveAAAAQuery(q);
+
 }
 
 void
@@ -1721,6 +1705,7 @@
 
     // idns_query is POD so no constructors are called after allocation
     q->xact_id.change();
+    q->query_id = idnsQueryID();
 
     if (addr.IsIPv6()) {
         struct in6_addr addr6;
@@ -1733,9 +1718,6 @@
         q->sz = rfc3596BuildPTRQuery4(addr4, q->buf, sizeof(q->buf), 0, &q->query, 0);
     }
 
-    /* PTR does not do inbound A/AAAA */
-    q->need_A = false;
-
     if (q->sz < 0) {
         /* problem with query data -- query not sent */
         callback(data, NULL, 0, "Internal error");
@@ -1749,7 +1731,7 @@
     }
 
     debugs(78, 3, "idnsPTRLookup: buf is " << q->sz << " bytes for " << ip <<
-           ", id = 0x" << std::hex << q->msg_id);
+           ", id = 0x" << std::hex << q->query_id);
 
     q->callback = callback;
     q->callback_data = cbdataReference(data);

=== modified file 'src/structs.h'
--- src/structs.h	2012-01-03 02:19:30 +0000
+++ src/structs.h	2012-01-06 20:41:21 +0000
@@ -445,7 +445,6 @@
         int emailErrData;
         int httpd_suppress_version_string;
         int global_internal_static;
-        int dns_require_A;
 
 #if FOLLOW_X_FORWARDED_FOR
         int acl_uses_indirect_client;

# Begin bundle
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

