The last outstanding reason to retain dnsserver component in Squid seems
to be lack of mDNS support in our client resolver. This patch seeks to
close that hole and add mDNS support to the Squid internal DNS resolver.
* adds the mDNS multicast group IPs as always-present entries in the
nameservers list.
* filters each request. ".local" lookups are permitted to both the mDNS
resolvers and the recursive resolvers, other requests are only permitted
to the regular recursive resolvers.
I have not done much testing of this yet. However the DNS protocol
operations are completely unchanged, and the only questions are whether
the nameservers responses are accepted back into Squid or prevented by
the ignore_unknown_nameservers option (or not) - that depends on the
mDNS responses. And whether the mDNS produces NXDOMAIN in a useful way
for Squid.
Amos
=== modified file 'src/dns_internal.cc'
--- src/dns_internal.cc 2013-03-03 07:10:22 +0000
+++ src/dns_internal.cc 2013-05-24 16:42:52 +0000
@@ -141,6 +141,7 @@
int nsends;
int need_vc;
+ bool permit_mdns;
int pending;
struct timeval start_t;
@@ -179,6 +180,7 @@
#if WHEN_EDNS_RESPONSES_ARE_PARSED
int last_seen_edns;
#endif
+ bool mDNSResolver;
nsvc *vc;
};
@@ -231,15 +233,16 @@
static OBJH idnsStats;
static void idnsAddNameserver(const char *buf);
+static void idnsAddMDNSNameservers();
static void idnsAddPathComponent(const char *buf);
static void idnsFreeNameservers(void);
static void idnsFreeSearchpath(void);
-static void idnsParseNameservers(void);
-#if !_SQUID_WINDOWS_
-static void idnsParseResolvConf(void);
+static bool idnsParseNameservers(void);
+#if _SQUID_WINDOWS_
+static bool idnsParseResolvConf(void);
#endif
#if _SQUID_WINDOWS_
-static void idnsParseWIN32Registry(void);
+static bool idnsParseWIN32Registry(void);
static void idnsParseWIN32SearchList(const char *);
#endif
static void idnsStartQuery(idns_query * q, IDNSCB * callback, void *data);
@@ -262,6 +265,30 @@
static void idnsSendSlaveAAAAQuery(idns_query *q);
static void
+idnsCheckMDNS(idns_query *q)
+{
+ size_t slen = strlen(q->name);
+ if (slen > 6 && memcmp(q->name +(slen-6),".local", 6) == 0) {
+ q->permit_mdns = true;
+ }
+}
+
+static void
+idnsAddMDNSNameservers()
+{
+#define MDNS_RESOLVER_COUNT 2
+
+ // mDNS resolver addresses are explicit multicast group IPs
+ idnsAddNameserver("FF02::FB");
+ nameservers[nns-1].S.SetPort(5353);
+ nameservers[nns-1].mDNSResolver = true;
+
+ idnsAddNameserver("224.0.0.251");
+ nameservers[nns-1].S.SetPort(5353);
+ nameservers[nns-1].mDNSResolver = true;
+}
+
+static void
idnsAddNameserver(const char *buf)
{
Ip::Address A;
@@ -354,29 +381,31 @@
npc = npc_alloc = 0;
}
-static void
+static bool
idnsParseNameservers(void)
{
- wordlist *w;
-
- for (w = Config.dns_nameservers; w; w = w->next) {
+ bool result = false;
+ for (wordlist *w = Config.dns_nameservers; w; w = w->next) {
debugs(78, DBG_IMPORTANT, "Adding nameserver " << w->key << " from
squid.conf");
idnsAddNameserver(w->key);
+ result = true;
}
+ return result;
}
#if !_SQUID_WINDOWS_
-static void
+static bool
idnsParseResolvConf(void)
{
FILE *fp;
char buf[RESOLV_BUFSZ];
const char *t;
+ bool result = false;
fp = fopen(_PATH_RESCONF, "r");
if (fp == NULL) {
debugs(78, DBG_IMPORTANT, "" << _PATH_RESCONF << ": " << xstrerror());
- return;
+ return false;
}
#if _SQUID_CYGWIN_
@@ -397,6 +426,7 @@
debugs(78, DBG_IMPORTANT, "Adding nameserver " << t << " from " <<
_PATH_RESCONF);
idnsAddNameserver(t);
+ result = true;
} else if (strcmp(t, "domain") == 0) {
idnsFreeSearchpath();
t = strtok(NULL, w_space);
@@ -444,6 +474,7 @@
}
fclose(fp);
+ return result;
}
#endif
@@ -493,12 +524,13 @@
}
}
-static void
+static bool
idnsParseWIN32Registry(void)
{
char *t;
char *token;
HKEY hndKey, hndKey2;
+ bool result = false;
switch (WIN32_OS_version) {
@@ -518,6 +550,7 @@
while (token) {
idnsAddNameserver(token);
+ result = true;
debugs(78, DBG_IMPORTANT, "Adding DHCP nameserver " <<
token << " from Registry");
token = strtok(NULL, ",");
}
@@ -534,6 +567,7 @@
while (token) {
debugs(78, DBG_IMPORTANT, "Adding nameserver " << token <<
" from Registry");
idnsAddNameserver(token);
+ result = true;
token = strtok(NULL, ", ");
}
xfree(t);
@@ -587,6 +621,7 @@
while (token) {
debugs(78, DBG_IMPORTANT, "Adding DHCP
nameserver " << token << " from Registry");
idnsAddNameserver(token);
+ result = true;
token = strtok(NULL, ", ");
}
xfree(t);
@@ -600,6 +635,7 @@
while (token) {
debugs(78, DBG_IMPORTANT, "Adding
nameserver " << token << " from Registry");
idnsAddNameserver(token);
+ result = true;
token = strtok(NULL, ", ");
}
@@ -644,6 +680,7 @@
while (token) {
debugs(78, DBG_IMPORTANT, "Adding nameserver " << token <<
" from Registry");
idnsAddNameserver(token);
+ result = true;
token = strtok(NULL, ", ");
}
xfree(t);
@@ -656,8 +693,9 @@
default:
debugs(78, DBG_IMPORTANT, "Failed to read nameserver from Registry:
Unknown System Type.");
- return;
}
+
+ return result;
}
#endif
@@ -690,14 +728,15 @@
storeAppendPrintf(sentry, "DNS jumbo-grams: not working\n");
storeAppendPrintf(sentry, "\nNameservers:\n");
- storeAppendPrintf(sentry, "IP ADDRESS
# QUERIES # REPLIES\n");
- storeAppendPrintf(sentry, "----------------------------------------------
--------- ---------\n");
+ storeAppendPrintf(sentry, "IP ADDRESS
# QUERIES # REPLIES Type\n");
+ storeAppendPrintf(sentry, "----------------------------------------------
--------- --------- --------\n");
for (i = 0; i < nns; ++i) {
- storeAppendPrintf(sentry, "%-45s %9d %9d\n", /* Let's take the
maximum: (15 IPv4/45 IPv6) */
+ storeAppendPrintf(sentry, "%-45s %9d %9d %s\n", /* Let's take the
maximum: (15 IPv4/45 IPv6) */
nameservers[i].S.NtoA(buf,MAX_IPSTRLEN),
nameservers[i].nqueries,
- nameservers[i].nreplies);
+ nameservers[i].nreplies,
+ nameservers[i].mDNSResolver?"multicast":"recurse");
}
storeAppendPrintf(sentry, "\nRcode Matrix:\n");
@@ -915,7 +954,11 @@
int nsn;
do {
- nsn = q->nsends % nns;
+ // only use mDNS resolvers for mDNS compatible queries
+ if (!q->permit_mdns)
+ nsn = MDNS_RESOLVER_COUNT + q->nsends % (nns-MDNS_RESOLVER_COUNT);
+ else
+ nsn = q->nsends % nns;
if (q->need_vc) {
idnsSendQueryVC(q, nsn);
@@ -1227,6 +1270,7 @@
q->nsends = 0;
+ idnsCheckMDNS(q);
idnsSendQuery(q);
if (Ip::EnableIpv6)
idnsSendSlaveAAAAQuery(q);
@@ -1531,19 +1575,20 @@
}
assert(0 == nns);
- idnsParseNameservers();
+ idnsAddMDNSNameservers();
+ bool nsFound = idnsParseNameservers();
#if !_SQUID_WINDOWS_
- if (0 == nns)
- idnsParseResolvConf();
+ if (!nsFound)
+ nsFound = idnsParseResolvConf();
#endif
#if _SQUID_WINDOWS_
- if (0 == nns)
- idnsParseWIN32Registry();
+ if (!nsFound)
+ nsFound = idnsParseWIN32Registry();
#endif
- if (0 == nns) {
+ if (!nsFound) {
debugs(78, DBG_IMPORTANT, "Warning: Could not find any nameservers.
Trying to use localhost");
#if _SQUID_WINDOWS_
debugs(78, DBG_IMPORTANT, "Please check your TCP-IP settings or
/etc/resolv.conf file");
@@ -1657,6 +1702,7 @@
cbdataFree(q);
return;
}
+ idnsCheckMDNS(q);
master->slave = q;
idnsSendQuery(q);
}
@@ -1709,6 +1755,7 @@
debugs(78, 3, "idnsALookup: buf is " << q->sz << " bytes for " << q->name
<<
", id = 0x" << std::hex << q->query_id);
+ idnsCheckMDNS(q);
idnsStartQuery(q, callback, data);
if (Ip::EnableIpv6)
@@ -1757,6 +1804,7 @@
debugs(78, 3, "idnsPTRLookup: buf is " << q->sz << " bytes for " << ip <<
", id = 0x" << std::hex << q->query_id);
+ q->permit_mdns = true;
idnsStartQuery(q, callback, data);
}