Revision: 14849
Author: adrian.chadd
Date: Tue Jan 18 17:13:51 2011
Log: Convert internal dns over to being IPv6 aware.
This is inspired from Squid-3, but I've rewritten it a bit and made sure
I tidy up aborted DNS requests/replies.
A requests are turned into AAAA requests first. After an AAAA request is
done, an A request is then done and the results are merged together.
AAAA records are preferred over A records. "Down" IPv6 hosts are
quickly marked "bad".
There's some EDNS stuff that isn't yet ported over; I'll worry about that
later.
This now populates the ipcache with v6 and v4 records and these
are handled by commConnect*() routines in src/comm.c . Unfortunately
those routines don't quite work for other reasons, but at least the
IPv6 DNS records are now making it there.
http://code.google.com/p/lusca-cache/source/detail?r=14849
Modified:
/playpen/LUSCA_HEAD_ipv6/libsqdns/dns_internal.c
/playpen/LUSCA_HEAD_ipv6/libsqdns/dns_internal.h
=======================================
--- /playpen/LUSCA_HEAD_ipv6/libsqdns/dns_internal.c Sun Jul 4 06:56:53
2010
+++ /playpen/LUSCA_HEAD_ipv6/libsqdns/dns_internal.c Tue Jan 18 17:13:51
2011
@@ -390,6 +390,7 @@
cbdataUnlock(q2->callback_data);
if (valid)
q2->callback(q2->callback_data, answers, n, error);
+ safe_free(q2->initial_AAAA.answers);
cbdataFree(q2);
}
if (q->hash.key) {
@@ -504,6 +505,16 @@
dlinkAdd(q, &q->lru, &idns_lru_list);
comm_connect_begin(q->tcp_socket, &nameservers[ns].S,
idnsSendTcpQuery, q);
}
+
+static 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)
@@ -577,18 +588,91 @@
q->start_t = current_time;
q->id = idnsQueryID();
rfc1035SetQueryID(q->buf, q->id);
- q->sz = rfc1035BuildAQuery(q->name, q->buf, sizeof(q->buf), q->id,
- &q->query);
+ /* XXX Should only do this if ipv6 is enabled? like in squid-3?
-adrian */
+ if (q->query.qtype == RFC1035_TYPE_AAAA) {
+ q->sz = rfc1035BuildAAAAQuery(q->name, q->buf, sizeof(q->buf),
q->id, &q->query);
+ q->need_A = 1;
+ } else {
+ q->sz = rfc1035BuildAQuery(q->name, q->buf, sizeof(q->buf),
q->id, &q->query);
+ q->need_A = 0;
+ }
idnsCacheQuery(q);
idnsSendQuery(q);
return;
}
}
+
+ /* Do we need to do a followup IPv4 lookup before we return the
results? */
+ if (q->need_A == 1) {
+ debug(1, 1) ("%s: need_A == 1; re-submit an A query\n", __func__);
+
+ /* Squirrel away the message answers so we can combine them later */
+ if (n > 0) {
+ q->initial_AAAA.count = message->ancount;
+ q->initial_AAAA.answers = message->answer;
+ message->answer = NULL;
+ message->ancount = 0;
+ }
+
+ /* Drop the current message; which now has no answer in it to free */
+ idnsDropMessage(message, q);
+
+ /* Reset the query */
+ q->nsends = 0;
+
+ /* No need to send an A if this fails */
+ q->need_A = 0;
+
+ /* Submit an A query */
+ /* XXX squid-3 says 'see EDNS notes at top of file why this sends 0';
merge! */
+ q->sz = rfc1035BuildAQuery(q->name, q->buf, sizeof(q->buf), q->id,
&q->query);
+ idnsCacheQuery(q);
+ idnsSendQuery(q);
+ return;
+ }
+
+ if (q->initial_AAAA.count != 0 && n <= 0) {
+ debug(14, 1) ("%s: lookup failed but a previous AAAA lookup succeeded;
using those records\n", __func__);
+ /* There is a set of previous results from an AAAA lookup w/ no A
answers; Just use those */
+ rfc1035RRDestroy(message->answer, 0);
+ /* "hand over" the original answer */
+ message->answer = q->initial_AAAA.answers;
+ message->ancount = q->initial_AAAA.count;
+ n = message->ancount;
+ q->initial_AAAA.answers = NULL;
+ q->initial_AAAA.count = 0;
+ } else if (q->initial_AAAA.count != 0 && n > 0) {
+ debug(14, 1) ("%s: merging AAAA and A records\n", __func__);
+ /* There's both a set of previous results and current results; merge them
*/
+
+ rfc1035_rr *rr;
+
+ /* Allocate new rr, as a union of both */
+ rr = xcalloc(message->ancount + q->initial_AAAA.count,
sizeof(rfc1035_rr));
+
+ /* Copy the contents - this copies the pointers to the rdata of each rr
entry */
+ memcpy(&rr[0], q->initial_AAAA.answers, q->initial_AAAA.count *
sizeof(rfc1035_rr));
+ memcpy(&rr[q->initial_AAAA.count], message->answer, message->ancount *
sizeof(rfc1035_rr));
+
+ /* Free the originals here, leaving the rdata's untouched - they're now
owned by the above */
+ safe_free(q->initial_AAAA.answers);
+ safe_free(message->answer);
+
+ /* shove our newly appended answer into the message */
+ message->answer = rr;
+ n = message->ancount += q->initial_AAAA.count;
+
+ /* Delete any reference to the initial AAAA lookup */
+ q->initial_AAAA.answers = NULL;
+ q->initial_AAAA.count = 0;
+ }
+
idnsCallback(q, message->answer, n, q->error);
rfc1035MessageDestroy(message);
idnsTcpCleanup(q);
+ safe_free(q->initial_AAAA.answers);
cbdataFree(q);
}
@@ -695,6 +779,7 @@
else
idnsCallback(q, NULL, -16, "Timeout");
idnsTcpCleanup(q);
+ safe_free(q->initial_AAAA.answers);
cbdataFree(q);
}
}
@@ -855,12 +940,16 @@
debug(78, 3) ("idnsALookup: searchpath used for %s\n",
q->name);
}
- q->sz = rfc1035BuildAQuery(q->name, q->buf, sizeof(q->buf), q->id,
+ /* XXXX only do this if there's IPv6 enabled */
+ /* XXXX limit the number of queries to be made for AAAA + EDNS; see
Squid-3 */
+ q->sz = rfc1035BuildAAAAQuery(q->name, q->buf, sizeof(q->buf), q->id,
&q->query);
+ q->need_A = 1;
if (q->sz < 0) {
/* problem with query data -- query not sent */
callback(data, NULL, 0, "Internal error");
+ safe_free(q->initial_AAAA.answers);
cbdataFree(q);
return;
}
@@ -883,15 +972,21 @@
q->tcp_socket = -1;
q->id = idnsQueryID();
q->sz = rfc1035BuildPTRQuery(addr, q->buf, sizeof(q->buf), q->id,
&q->query);
+
+ /* PTR does not do inbound A/AAAA */
+ q->need_A = 0;
+
debug(78, 3) ("idnsPTRLookup: buf is %d bytes for %s, id = %#hx\n",
(int) q->sz, ip, q->id);
if (q->sz < 0) {
/* problem with query data -- query not sent */
callback(data, NULL, 0, "Internal error");
+ safe_free(q->initial_AAAA.answers);
cbdataFree(q);
return;
}
if (idnsCachedLookup(q->query.name, callback, data)) {
+ safe_free(q->initial_AAAA.answers);
cbdataFree(q);
return;
}
=======================================
--- /playpen/LUSCA_HEAD_ipv6/libsqdns/dns_internal.h Fri Sep 5 01:21:13
2008
+++ /playpen/LUSCA_HEAD_ipv6/libsqdns/dns_internal.h Tue Jan 18 17:13:51
2011
@@ -59,6 +59,11 @@
char *tcp_buffer;
size_t tcp_buffer_size;
size_t tcp_buffer_offset;
+ int need_A;
+ struct {
+ int count;
+ rfc1035_rr *answers;
+ } initial_AAAA;
};
struct _ns {
--
You received this message because you are subscribed to the Google Groups
"lusca-commit" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/lusca-commit?hl=en.