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);
 }
 

Reply via email to