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


