]> git.saurik.com Git - apple/mdnsresponder.git/commitdiff
mDNSResponder-170.tar.gz mac-os-x-1052 v170
authorApple <opensource@apple.com>
Sat, 5 Jan 2008 00:13:11 +0000 (00:13 +0000)
committerApple <opensource@apple.com>
Sat, 5 Jan 2008 00:13:11 +0000 (00:13 +0000)
34 files changed:
Clients/dns-sd.c
Makefile
mDNSCore/DNSCommon.c
mDNSCore/DNSCommon.h
mDNSCore/DNSDigest.c
mDNSCore/mDNS.c
mDNSCore/mDNSDebug.h
mDNSCore/mDNSEmbeddedAPI.h
mDNSCore/uDNS.c
mDNSCore/uDNS.h
mDNSMacOSX/LegacyNATTraversal.c
mDNSMacOSX/PreferencePane/DNSServiceDiscoveryPref.m
mDNSMacOSX/PreferencePane/PrivilegedOperations.c
mDNSMacOSX/PreferencePane/ddnswriteconfig.m
mDNSMacOSX/SamplemDNSClient.c
mDNSMacOSX/daemon.c
mDNSMacOSX/helper-error.h
mDNSMacOSX/helper-stubs.c
mDNSMacOSX/helper.c
mDNSMacOSX/mDNSMacOSX.c
mDNSMacOSX/mDNSMacOSX.h
mDNSMacOSX/mDNSResponder.xcodeproj/project.pbxproj
mDNSMacOSX/pfkey.c
mDNSPosix/mDNSUNP.c
mDNSShared/Java/JNISupport.c
mDNSShared/PlatformCommon.c
mDNSShared/dns_sd.h
mDNSShared/dnsextd.c
mDNSShared/dnssd_clientlib.c
mDNSShared/dnssd_clientshim.c
mDNSShared/dnssd_clientstub.c
mDNSShared/mDNSDebug.c
mDNSShared/uds_daemon.c
mDNSWindows/mDNSWin32.c

index 718547cdcceb32b76402b3c6ce17bcddd50bf692..e80ee39af09becf357e80b84f6a736dece4e2efe 100644 (file)
@@ -433,6 +433,7 @@ static void myTimerCallBack(void)
                        else                      updatetest[1] = 'A';
                        updatetest[0] = 3 - updatetest[0];
                        updatetest[2] = updatetest[1];
                        else                      updatetest[1] = 'A';
                        updatetest[0] = 3 - updatetest[0];
                        updatetest[2] = updatetest[1];
+                       printtimestamp();
                        printf("Updating Test TXT record to %c\n", updatetest[1]);
                        err = DNSServiceUpdateRecord(client, NULL, 0, 1+updatetest[0], &updatetest[0], 0);
                        }
                        printf("Updating Test TXT record to %c\n", updatetest[1]);
                        err = DNSServiceUpdateRecord(client, NULL, 0, 1+updatetest[0], &updatetest[0], 0);
                        }
@@ -689,19 +690,19 @@ static int getfirstoption(int argc, char **argv, const char *optstr, int *pOptIn
        }
 #else
        {
        }
 #else
        {
-       int operation = getopt(argc, (char *const *)argv, optstr);
+       int o = getopt(argc, (char *const *)argv, optstr);
        *pOptInd = optind;
        *pOptInd = optind;
-       return operation;
+       return o;
        }
 #endif
 
        }
 #endif
 
-static void DNSSD_API MyRegisterRecordCallback(DNSServiceRef service, DNSRecordRef record, const DNSServiceFlags flags,
+static void DNSSD_API MyRegisterRecordCallback(DNSServiceRef service, DNSRecordRef rec, const DNSServiceFlags flags,
     DNSServiceErrorType errorCode, void *context)
        {
        char *name = (char *)context;
        
        (void)service;  // Unused
     DNSServiceErrorType errorCode, void *context)
        {
        char *name = (char *)context;
        
        (void)service;  // Unused
-       (void)record;   // Unused
+       (void)rec;      // Unused
        (void)flags;    // Unused
        
        printtimestamp();
        (void)flags;    // Unused
        
        printtimestamp();
@@ -714,7 +715,7 @@ static void DNSSD_API MyRegisterRecordCallback(DNSServiceRef service, DNSRecordR
                default:                          printf("Error %d\n", errorCode); break;
                }
        if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
                default:                          printf("Error %d\n", errorCode); break;
                }
        if (!(flags & kDNSServiceFlagsMoreComing)) fflush(stdout);
-       // DNSServiceRemoveRecord(service, record, 0); to test record removal
+       // DNSServiceRemoveRecord(service, rec, 0); to test record removal
        }
 
 static unsigned long getip(const char *const name)
        }
 
 static unsigned long getip(const char *const name)
@@ -811,7 +812,7 @@ int main(int argc, char **argv)
        {
        DNSServiceErrorType err;
        char buffer[TypeBufferSize], *typ, *dom;
        {
        DNSServiceErrorType err;
        char buffer[TypeBufferSize], *typ, *dom;
-       int optind;
+       int opi;
 
        // Extract the program name from argv[0], which by convention contains the path to this executable.
        // Note that this is just a voluntary convention, not enforced by the kernel --
 
        // Extract the program name from argv[0], which by convention contains the path to this executable.
        // Note that this is just a voluntary convention, not enforced by the kernel --
@@ -852,7 +853,7 @@ int main(int argc, char **argv)
                                                                #if HAS_ADDRINFO_API
                                                                        "G"
                                                                #endif
                                                                #if HAS_ADDRINFO_API
                                                                        "G"
                                                                #endif
-                                                               , &optind);
+                                                               , &opi);
        if (operation == -1) goto Fail;
 
        if (opinterface) printf("Using interface %d\n", opinterface);
        if (operation == -1) goto Fail;
 
        if (opinterface) printf("Using interface %d\n", opinterface);
@@ -871,38 +872,38 @@ int main(int argc, char **argv)
                                        //enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "dns-sd.ibm.com.", NULL);
                                        break;
 
                                        //enum_reply(client, kDNSServiceFlagsAdd, 0, 0, "dns-sd.ibm.com.", NULL);
                                        break;
 
-               case 'B':       typ = (argc < optind+1) ? "" : argv[optind+0];
-                                       dom = (argc < optind+2) ? "" : argv[optind+1];  // Missing domain argument is the same as empty string i.e. use system default(s)
+               case 'B':       typ = (argc < opi+1) ? "" : argv[opi+0];
+                                       dom = (argc < opi+2) ? "" : argv[opi+1];  // Missing domain argument is the same as empty string i.e. use system default(s)
                                        typ = gettype(buffer, typ);
                                        if (dom[0] == '.' && dom[1] == 0) dom[0] = 0;   // We allow '.' on the command line as a synonym for empty string
                                        printf("Browsing for %s%s%s\n", typ, dom[0] ? "." : "", dom);
                                        err = DNSServiceBrowse(&client, 0, opinterface, typ, dom, browse_reply, NULL);
                                        break;
 
                                        typ = gettype(buffer, typ);
                                        if (dom[0] == '.' && dom[1] == 0) dom[0] = 0;   // We allow '.' on the command line as a synonym for empty string
                                        printf("Browsing for %s%s%s\n", typ, dom[0] ? "." : "", dom);
                                        err = DNSServiceBrowse(&client, 0, opinterface, typ, dom, browse_reply, NULL);
                                        break;
 
-               case 'L':       if (argc < optind+2) goto Fail;
-                                       typ = (argc < optind+2) ? ""      : argv[optind+1];
-                                       dom = (argc < optind+3) ? "local" : argv[optind+2];
+               case 'L':       if (argc < opi+2) goto Fail;
+                                       typ = (argc < opi+2) ? ""      : argv[opi+1];
+                                       dom = (argc < opi+3) ? "local" : argv[opi+2];
                                        typ = gettype(buffer, typ);
                                        if (dom[0] == '.' && dom[1] == 0) dom = "local";   // We allow '.' on the command line as a synonym for "local"
                                        typ = gettype(buffer, typ);
                                        if (dom[0] == '.' && dom[1] == 0) dom = "local";   // We allow '.' on the command line as a synonym for "local"
-                                       printf("Lookup %s.%s.%s\n", argv[optind+0], typ, dom);
-                                       err = DNSServiceResolve(&client, 0, opinterface, argv[optind+0], typ, dom, (DNSServiceResolveReply)resolve_reply, NULL);
+                                       printf("Lookup %s.%s.%s\n", argv[opi+0], typ, dom);
+                                       err = DNSServiceResolve(&client, 0, opinterface, argv[opi+0], typ, dom, (DNSServiceResolveReply)resolve_reply, NULL);
                                        break;
 
                                        break;
 
-               case 'R':       if (argc < optind+4) goto Fail;
-                                       typ = (argc < optind+2) ? "" : argv[optind+1];
-                                       dom = (argc < optind+3) ? "" : argv[optind+2];
+               case 'R':       if (argc < opi+4) goto Fail;
+                                       typ = (argc < opi+2) ? "" : argv[opi+1];
+                                       dom = (argc < opi+3) ? "" : argv[opi+2];
                                        typ = gettype(buffer, typ);
                                        if (dom[0] == '.' && dom[1] == 0) dom[0] = 0;   // We allow '.' on the command line as a synonym for empty string
                                        typ = gettype(buffer, typ);
                                        if (dom[0] == '.' && dom[1] == 0) dom[0] = 0;   // We allow '.' on the command line as a synonym for empty string
-                                       err = RegisterService(&client, argv[optind+0], typ, dom, NULL, argv[optind+3], argc-(optind+4), argv+(optind+4));
+                                       err = RegisterService(&client, argv[opi+0], typ, dom, NULL, argv[opi+3], argc-(opi+4), argv+(opi+4));
                                        break;
 
                                        break;
 
-               case 'P':       if (argc < optind+6) goto Fail;
+               case 'P':       if (argc < opi+6) goto Fail;
                                        err = DNSServiceCreateConnection(&client_pa);
                                        if (err) { fprintf(stderr, "DNSServiceCreateConnection returned %d\n", err); return(err); }
                                        err = DNSServiceCreateConnection(&client_pa);
                                        if (err) { fprintf(stderr, "DNSServiceCreateConnection returned %d\n", err); return(err); }
-                                       err = RegisterProxyAddressRecord(client_pa, argv[optind+4], argv[optind+5]);
-                                       //err = RegisterProxyAddressRecord(client_pa, "two", argv[optind+5]);
+                                       err = RegisterProxyAddressRecord(client_pa, argv[opi+4], argv[opi+5]);
+                                       //err = RegisterProxyAddressRecord(client_pa, "two", argv[opi+5]);
                                        if (err) break;
                                        if (err) break;
-                                       err = RegisterService(&client, argv[optind+0], argv[optind+1], argv[optind+2], argv[optind+4], argv[optind+3], argc-(optind+6), argv+(optind+6));
+                                       err = RegisterService(&client, argv[opi+0], argv[opi+1], argv[opi+2], argv[opi+4], argv[opi+3], argc-(opi+6), argv+(opi+6));
                                        //DNSServiceRemoveRecord(client_pa, record, 0);
                                        //DNSServiceRemoveRecord(client_pa, record, 0);
                                        break;
                                        //DNSServiceRemoveRecord(client_pa, record, 0);
                                        //DNSServiceRemoveRecord(client_pa, record, 0);
                                        break;
@@ -911,11 +912,11 @@ int main(int argc, char **argv)
                case 'C':       {
                                        uint16_t rrtype, rrclass;
                                        DNSServiceFlags flags = kDNSServiceFlagsReturnIntermediates;
                case 'C':       {
                                        uint16_t rrtype, rrclass;
                                        DNSServiceFlags flags = kDNSServiceFlagsReturnIntermediates;
-                                       if (argc < optind+1) goto Fail;
-                                       rrtype = (argc <= optind+1) ? kDNSServiceType_A  : GetRRType(argv[optind+1]);
-                                       rrclass = (argc <= optind+2) ? kDNSServiceClass_IN : atoi(argv[optind+2]);
+                                       if (argc < opi+1) goto Fail;
+                                       rrtype = (argc <= opi+1) ? kDNSServiceType_A  : GetRRType(argv[opi+1]);
+                                       rrclass = (argc <= opi+2) ? kDNSServiceClass_IN : atoi(argv[opi+2]);
                                        if (rrtype == kDNSServiceType_TXT || rrtype == kDNSServiceType_PTR) flags |= kDNSServiceFlagsLongLivedQuery;
                                        if (rrtype == kDNSServiceType_TXT || rrtype == kDNSServiceType_PTR) flags |= kDNSServiceFlagsLongLivedQuery;
-                                       err = DNSServiceQueryRecord(&client, flags, opinterface, argv[optind+0], rrtype, rrclass, qr_reply, NULL);
+                                       err = DNSServiceQueryRecord(&client, flags, opinterface, argv[opi+0], rrtype, rrclass, qr_reply, NULL);
                                        break;
                                        }
 
                                        break;
                                        }
 
@@ -963,14 +964,14 @@ int main(int argc, char **argv)
 
 #if HAS_NAT_PMP_API
                case 'X':   {
 
 #if HAS_NAT_PMP_API
                case 'X':   {
-                                       if (argc == optind)     // If no arguments, just fetch IP address
+                                       if (argc == opi)        // If no arguments, just fetch IP address
                                                err = DNSServiceNATPortMappingCreate(&client, 0, 0, 0, 0, 0, 0, port_mapping_create_reply, NULL);
                                                err = DNSServiceNATPortMappingCreate(&client, 0, 0, 0, 0, 0, 0, port_mapping_create_reply, NULL);
-                                       else if (argc >= optind+2 && atoi(argv[optind+0]) == 0)
+                                       else if (argc >= opi+2 && atoi(argv[opi+0]) == 0)
                                                {
                                                {
-                                               DNSServiceProtocol prot  = GetProtocol(argv[optind+0]);                                         // Must specify TCP or UDP
-                                               uint16_t IntPortAsNumber = atoi(argv[optind+1]);                                                        // Must specify internal port
-                                               uint16_t ExtPortAsNumber = (argc < optind+3) ? 0 : atoi(argv[optind+2]);        // Optional desired external port
-                                               uint32_t ttl             = (argc < optind+4) ? 0 : atoi(argv[optind+3]);        // Optional desired lease lifetime
+                                               DNSServiceProtocol prot  = GetProtocol(argv[opi+0]);                                            // Must specify TCP or UDP
+                                               uint16_t IntPortAsNumber = atoi(argv[opi+1]);                                                   // Must specify internal port
+                                               uint16_t ExtPortAsNumber = (argc < opi+3) ? 0 : atoi(argv[opi+2]);      // Optional desired external port
+                                               uint32_t ttl             = (argc < opi+4) ? 0 : atoi(argv[opi+3]);      // Optional desired lease lifetime
                                                Opaque16 intp = { { IntPortAsNumber >> 8, IntPortAsNumber & 0xFF } };
                                                Opaque16 extp = { { ExtPortAsNumber >> 8, ExtPortAsNumber & 0xFF } };
                                                err = DNSServiceNATPortMappingCreate(&client, 0, 0, prot, intp.NotAnInteger, extp.NotAnInteger, ttl, port_mapping_create_reply, NULL);
                                                Opaque16 intp = { { IntPortAsNumber >> 8, IntPortAsNumber & 0xFF } };
                                                Opaque16 extp = { { ExtPortAsNumber >> 8, ExtPortAsNumber & 0xFF } };
                                                err = DNSServiceNATPortMappingCreate(&client, 0, 0, prot, intp.NotAnInteger, extp.NotAnInteger, ttl, port_mapping_create_reply, NULL);
@@ -982,8 +983,8 @@ int main(int argc, char **argv)
 
 #if HAS_ADDRINFO_API
                case 'G':   {
 
 #if HAS_ADDRINFO_API
                case 'G':   {
-                                       if (argc != optind+2) goto Fail;
-                                       else err = DNSServiceGetAddrInfo(&client, kDNSServiceFlagsReturnIntermediates, opinterface, GetProtocol(argv[optind+0]), argv[optind+1], addrinfo_reply, NULL);
+                                       if (argc != opi+2) goto Fail;
+                                       else err = DNSServiceGetAddrInfo(&client, kDNSServiceFlagsReturnIntermediates, opinterface, GetProtocol(argv[opi+0]), argv[opi+1], addrinfo_reply, NULL);
                                        break;
                            }
 #endif
                                        break;
                            }
 #endif
index d774618acc6554df31812f67defd29210d1d8e06..c6aca02a526ce843f0808bcf97e6a6b384cc2bf7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@
 
 include /Developer/Makefiles/pb_makefiles/platform.make
 
 
 include /Developer/Makefiles/pb_makefiles/platform.make
 
-MVERS = "mDNSResponder-164"
+MVERS = "mDNSResponder-170"
 
 DDNSWRITECONFIG = "$(DSTROOT)/Library/Application Support/Bonjour/ddnswriteconfig"
 
 
 DDNSWRITECONFIG = "$(DSTROOT)/Library/Application Support/Bonjour/ddnswriteconfig"
 
index 01e063ad08b061bb9b80dd5254b354ab25012d6b..7c17df69ee424ec16ae322704b4c4e270db58e0a 100644 (file)
     Change History (most recent first):
 
 $Log: DNSCommon.c,v $
     Change History (most recent first):
 
 $Log: DNSCommon.c,v $
+Revision 1.193  2007/12/17 23:42:36  cheshire
+Added comments about DNSDigest_SignMessage()
+
+Revision 1.192  2007/12/17 21:24:09  cheshire
+<rdar://problem/5526800> BTMM: Need to deregister records and services on shutdown/sleep
+We suspend sending of mDNS queries responses when going to sleep, so calculate GetNextScheduledEvent() time accordingly
+
+Revision 1.191  2007/12/14 00:59:36  cheshire
+<rdar://problem/5526800> BTMM: Need to deregister records and services on shutdown/sleep
+While going to sleep, don't block event scheduling
+
+Revision 1.190  2007/12/13 20:20:17  cheshire
+Minor efficiency tweaks -- converted IdenticalResourceRecord, IdenticalSameNameRecord, and
+SameRData from functions to macros, which allows the code to be inlined (the compiler can't
+inline a function defined in a different compilation unit) and therefore optimized better.
+
+Revision 1.189  2007/12/13 00:17:32  cheshire
+RDataHashValue was not calculating hash value reliably for RDATA types that have 'holes' in the
+in-memory representation (particularly SOA was affected by this, resulting in multiple duplicate
+cache entities for the same SOA record, because they had erroneously different rdatahash values).
+
+Revision 1.188  2007/12/13 00:13:03  cheshire
+Simplified RDataHashValue to take a single ResourceRecord pointer, instead of separate rdlength and RDataBody
+
+Revision 1.187  2007/12/08 00:35:20  cheshire
+<rdar://problem/5636422> Updating TXT records is too slow
+m->SuppressSending should not suppress all activity, just mDNS Query/Probe/Response
+
+Revision 1.186  2007/11/15 22:52:29  cheshire
+<rdar://problem/5589039> ERROR: mDNSPlatformWriteTCP - send Broken pipe
+
 Revision 1.185  2007/10/10 20:22:03  cheshire
 Added sanity checks in mDNSSendDNSMessage -- we've seen crashes in DNSDigest_SignMessage
 apparently caused by trying to sign zero-length messages
 Revision 1.185  2007/10/10 20:22:03  cheshire
 Added sanity checks in mDNSSendDNSMessage -- we've seen crashes in DNSDigest_SignMessage
 apparently caused by trying to sign zero-length messages
@@ -1273,20 +1304,52 @@ mDNSexport void mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mD
        rr->namestorage.c[0]  = 0;              // MUST be set by client before calling mDNS_Register()
        }
 
        rr->namestorage.c[0]  = 0;              // MUST be set by client before calling mDNS_Register()
        }
 
-mDNSexport mDNSu32 RDataHashValue(mDNSu16 const rdlength, const RDataBody *const rdb)
+mDNSexport mDNSu32 RDataHashValue(const ResourceRecord *const rr)
        {
        {
-       mDNSu32 sum = 0;
-       int i;
-       for (i=0; i+1 < rdlength; i+=2)
-               {
-               sum += (((mDNSu32)(rdb->data[i])) << 8) | rdb->data[i+1];
-               sum = (sum<<3) | (sum>>29);
-               }
-       if (i < rdlength)
+       switch(rr->rrtype)
                {
                {
-               sum += ((mDNSu32)(rdb->data[i])) << 8;
+               case kDNSType_NS:
+               case kDNSType_CNAME:
+               case kDNSType_PTR:
+               case kDNSType_DNAME: return DomainNameHashValue(&rr->rdata->u.name);
+
+               case kDNSType_SOA:   return rr->rdata->u.soa.serial  +
+                                                                       rr->rdata->u.soa.refresh +
+                                                                       rr->rdata->u.soa.retry   +
+                                                                       rr->rdata->u.soa.expire  +
+                                                                       rr->rdata->u.soa.min     +
+                                                                       DomainNameHashValue(&rr->rdata->u.soa.mname) +
+                                                                       DomainNameHashValue(&rr->rdata->u.soa.rname);
+
+               case kDNSType_MX:
+               case kDNSType_AFSDB:
+               case kDNSType_RT:
+               case kDNSType_KX:        return DomainNameHashValue(&rr->rdata->u.mx.exchange);
+
+               case kDNSType_RP:        return DomainNameHashValue(&rr->rdata->u.rp.mbox)   + DomainNameHashValue(&rr->rdata->u.rp.txt);
+
+               case kDNSType_PX:        return DomainNameHashValue(&rr->rdata->u.px.map822) + DomainNameHashValue(&rr->rdata->u.px.mapx400);
+
+               case kDNSType_SRV:       return DomainNameHashValue(&rr->rdata->u.srv.target);
+
+               case kDNSType_OPT:      // Okay to use blind memory sum because there are no 'holes' in the in-memory representation
+
+               default:
+                       {
+                       mDNSu32 sum = 0;
+                       int i;
+                       for (i=0; i+1 < rr->rdlength; i+=2)
+                               {
+                               sum += (((mDNSu32)(rr->rdata->u.data[i])) << 8) | rr->rdata->u.data[i+1];
+                               sum = (sum<<3) | (sum>>29);
+                               }
+                       if (i < rr->rdlength)
+                               {
+                               sum += ((mDNSu32)(rr->rdata->u.data[i])) << 8;
+                               }
+                       return(sum);
+                       }
                }
                }
-       return(sum);
        }
 
 // r1 has to be a full ResourceRecord including rrtype and rdlength
        }
 
 // r1 has to be a full ResourceRecord including rrtype and rdlength
@@ -1326,28 +1389,12 @@ mDNSexport mDNSBool SameRDataBody(const ResourceRecord *const r1, const RDataBod
                                                                                                mDNSSameIPPort(r1->rdata->u.srv.port, r2->srv.port) &&
                                                                                                SameDomainName(&r1->rdata->u.srv.target, &r2->srv.target));
 
                                                                                                mDNSSameIPPort(r1->rdata->u.srv.port, r2->srv.port) &&
                                                                                                SameDomainName(&r1->rdata->u.srv.target, &r2->srv.target));
 
-               case kDNSType_OPT:      // Okay to use memory compare because there are no 'holes' in the in-memory representation
+               case kDNSType_OPT:      // Okay to use blind memory compare because there are no 'holes' in the in-memory representation
 
                default:                        return(mDNSPlatformMemSame(r1->rdata->u.data, r2->data, r1->rdlength));
                }
        }
 
 
                default:                        return(mDNSPlatformMemSame(r1->rdata->u.data, r2->data, r1->rdlength));
                }
        }
 
-mDNSexport mDNSBool SameRData(const ResourceRecord *const r1, const ResourceRecord *const r2)
-       {
-       if (r1->rrtype     != r2->rrtype)     return(mDNSfalse);
-       if (r1->rdlength   != r2->rdlength)   return(mDNSfalse);
-       if (r1->rdatahash  != r2->rdatahash)  return(mDNSfalse);
-       return(SameRDataBody(r1, &r2->rdata->u));
-       }
-
-mDNSexport mDNSBool SameResourceRecord(ResourceRecord *r1, ResourceRecord *r2)
-       {
-       return (r1->namehash == r2->namehash &&
-                       r1->rrtype == r2->rrtype &&
-                       SameDomainName(r1->name, r2->name) &&
-                       SameRData(r1, r2));
-       }
-
 // ResourceRecordAnswersQuestion returns mDNStrue if the given resource record is a valid answer to the given question.
 // SameNameRecordAnswersQuestion is the same, except it skips the expensive SameDomainName() call.
 // SameDomainName() is generally cheap when the names don't match, but expensive when they do match,
 // ResourceRecordAnswersQuestion returns mDNStrue if the given resource record is a valid answer to the given question.
 // SameNameRecordAnswersQuestion is the same, except it skips the expensive SameDomainName() call.
 // SameDomainName() is generally cheap when the names don't match, but expensive when they do match,
@@ -1368,14 +1415,6 @@ mDNSexport mDNSBool SameNameRecordAnswersQuestion(const ResourceRecord *const rr
        if (rr->rrtype != kDNSType_CNAME && rr->rrtype  != q->qtype  && q->qtype  != kDNSQType_ANY ) return(mDNSfalse);
        if (                                rr->rrclass != q->qclass && q->qclass != kDNSQClass_ANY) return(mDNSfalse);
 
        if (rr->rrtype != kDNSType_CNAME && rr->rrtype  != q->qtype  && q->qtype  != kDNSQType_ANY ) return(mDNSfalse);
        if (                                rr->rrclass != q->qclass && q->qclass != kDNSQClass_ANY) return(mDNSfalse);
 
-#if VerifySameNameAssumptions
-       if (rr->namehash != q->qnamehash || !SameDomainName(rr->name, &q->qname))
-               {
-               LogMsg("Bogus SameNameRecordAnswersQuestion call: RR %##s does not match Q %##s", rr->name->c, q->qname.c);
-               return(mDNSfalse);
-               }
-#endif
-
        return(mDNStrue);
        }
 
        return(mDNStrue);
        }
 
@@ -2007,7 +2046,7 @@ mDNSexport void SetNewRData(ResourceRecord *const rr, RData *NewRData, mDNSu16 r
        target = GetRRDomainNameTarget(rr);
        rr->rdlength   = GetRDLength(rr, mDNSfalse);
        rr->rdestimate = GetRDLength(rr, mDNStrue);
        target = GetRRDomainNameTarget(rr);
        rr->rdlength   = GetRDLength(rr, mDNSfalse);
        rr->rdestimate = GetRDLength(rr, mDNStrue);
-       rr->rdatahash  = target ? DomainNameHashValue(target) : RDataHashValue(rr->rdlength, &rr->rdata->u);
+       rr->rdatahash  = target ? DomainNameHashValue(target) : RDataHashValue(rr);
        }
 
 mDNSexport const mDNSu8 *skipDomainName(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end)
        }
 
 mDNSexport const mDNSu8 *skipDomainName(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end)
@@ -2159,9 +2198,9 @@ mDNSexport const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage
 
        if (!RecordType) LogMsg("GetLargeResourceRecord: No RecordType for %##s", rr->resrec.name->c);
 
 
        if (!RecordType) LogMsg("GetLargeResourceRecord: No RecordType for %##s", rr->resrec.name->c);
 
-       // IMPORTANT: Any record type we understand and unpack into a structure containing domainnames needs to have
-       // a corresponding case in SameRDataBody() to do a semantic comparison of the structure instead of a blind
-       // bitwise memory compare. This is because a domainname is a fixed size structure holding variable-length data.
+       // IMPORTANT: Any record type we understand and unpack into a structure containing domainnames needs to have corresponding
+       // cases in SameRDataBody() and RDataHashValue() to do a semantic comparison (or checksum) of the structure instead of a blind
+       // bitwise memory compare (or sum). This is because a domainname is a fixed size structure holding variable-length data.
        // Any bytes past the logical end of the name are undefined, and a blind bitwise memory compare may indicate that
        // two domainnames are different when semantically they are the same name and it's only the unused bytes that differ.
        if (rr->resrec.rrclass == kDNSQClass_ANY && pktrdlength == 0)   // Used in update packets to mean "Delete An RRset" (RFC 2136)
        // Any bytes past the logical end of the name are undefined, and a blind bitwise memory compare may indicate that
        // two domainnames are different when semantically they are the same name and it's only the unused bytes that differ.
        if (rr->resrec.rrclass == kDNSQClass_ANY && pktrdlength == 0)   // Used in update packets to mean "Delete An RRset" (RFC 2136)
@@ -2486,13 +2525,12 @@ mDNSexport void DumpPacket(mDNS *const m, mDNSBool sent, char *transport, const
 // Stub definition of TCPSocket_struct so we can access flags field. (Rest of TCPSocket_struct is platform-dependent.)
 struct TCPSocket_struct { TCPSocketFlags flags; /* ... */ };
 
 // Stub definition of TCPSocket_struct so we can access flags field. (Rest of TCPSocket_struct is platform-dependent.)
 struct TCPSocket_struct { TCPSocketFlags flags; /* ... */ };
 
+// Note: When we sign a DNS message using DNSDigest_SignMessage(), the current real-time clock value is used, which
+// is why we generally defer signing until we send the message, to ensure the signature is as fresh as possible.
 mDNSexport mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNSu8 *end,
     mDNSInterfaceID InterfaceID, const mDNSAddr *dst, mDNSIPPort dstport, TCPSocket *sock, DomainAuthInfo *authInfo)
        {
 mDNSexport mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNSu8 *end,
     mDNSInterfaceID InterfaceID, const mDNSAddr *dst, mDNSIPPort dstport, TCPSocket *sock, DomainAuthInfo *authInfo)
        {
-       mStatus status;
-       long nsent;
-       unsigned long msglen;
-       mDNSu8 lenbuf[2];
+       mStatus status = mStatus_NoError;
        mDNSu16 numQuestions   = msg->h.numQuestions;
        mDNSu16 numAnswers     = msg->h.numAnswers;
        mDNSu16 numAuthorities = msg->h.numAuthorities;
        mDNSu16 numQuestions   = msg->h.numQuestions;
        mDNSu16 numAnswers     = msg->h.numAnswers;
        mDNSu16 numAuthorities = msg->h.numAuthorities;
@@ -2515,30 +2553,25 @@ mDNSexport mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNS
        *ptr++ = (mDNSu8)(numAdditionals >> 8);
        *ptr++ = (mDNSu8)(numAdditionals &  0xFF);
 
        *ptr++ = (mDNSu8)(numAdditionals >> 8);
        *ptr++ = (mDNSu8)(numAdditionals &  0xFF);
 
-       if (authInfo)
-               {
-               end = DNSDigest_SignMessage(msg, &end, authInfo, 0);
-               if (!end) return mStatus_UnknownErr;
-               }
-
-       // Send the packet on the wire
-       if (sock)
-               {
-               msglen = (mDNSu16)(end - (mDNSu8 *)msg);
-               lenbuf[0] = (mDNSu8)(msglen >> 8);  // host->network byte conversion
-               lenbuf[1] = (mDNSu8)(msglen &  0xFF);
-
-               nsent = mDNSPlatformWriteTCP(sock, (char*)lenbuf, 2);
-               //!!!KRS make sure kernel is sending these as 1 packet!
-               if (nsent != 2) goto tcp_error;
-
-               nsent = mDNSPlatformWriteTCP(sock, (char *)msg, msglen);
-               if (nsent != (long)msglen) goto tcp_error;
-               status = mStatus_NoError;
-               }
+       if (authInfo) DNSDigest_SignMessage(msg, &end, authInfo, 0);    // DNSDigest_SignMessage operates on message in network byte order
+       if (!end) { LogMsg("mDNSSendDNSMessage: DNSDigest_SignMessage failed"); status = mStatus_NoMemoryErr; }
        else
                {
        else
                {
-               status = mDNSPlatformSendUDP(m, msg, end, InterfaceID, dst, dstport);
+               // Send the packet on the wire
+               if (!sock)
+                       status = mDNSPlatformSendUDP(m, msg, end, InterfaceID, dst, dstport);
+               else
+                       {
+                       mDNSu16 msglen = (mDNSu16)(end - (mDNSu8 *)msg);
+                       mDNSu8 lenbuf[2] = { (mDNSu8)(msglen >> 8), (mDNSu8)(msglen & 0xFF) };
+                       long nsent = mDNSPlatformWriteTCP(sock, (char*)lenbuf, 2);              // Should do scatter/gather here -- this is probably going out as two packets
+                       if (nsent != 2) { LogMsg("mDNSSendDNSMessage: write msg length failed %d/%d", nsent, 2); status = mStatus_ConnFailed; }
+                       else
+                               {
+                               nsent = mDNSPlatformWriteTCP(sock, (char *)msg, msglen);
+                               if (nsent != msglen) { LogMsg("mDNSSendDNSMessage: write msg body failed %d/%d", nsent, msglen); status = mStatus_ConnFailed; }
+                               }
+                       }
                }
 
        // Put all the integer values back the way they were before we return
                }
 
        // Put all the integer values back the way they were before we return
@@ -2555,10 +2588,6 @@ mDNSexport mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNS
                }
 
        return(status);
                }
 
        return(status);
-
-       tcp_error:
-       LogMsg("mDNSSendDNSMessage: error sending message over tcp");
-       return mStatus_UnknownErr;
        }
 
 // ***************************************************************************
        }
 
 // ***************************************************************************
@@ -2615,7 +2644,7 @@ mDNSexport void mDNS_Lock_(mDNS *const m)
 mDNSlocal mDNSs32 GetNextScheduledEvent(const mDNS *const m)
        {
        mDNSs32 e = m->timenow + 0x78000000;
 mDNSlocal mDNSs32 GetNextScheduledEvent(const mDNS *const m)
        {
        mDNSs32 e = m->timenow + 0x78000000;
-       if (m->mDNSPlatformStatus != mStatus_NoError || m->SleepState) return(e);
+       if (m->mDNSPlatformStatus != mStatus_NoError) return(e);
        if (m->NewQuestions)
                {
                if (m->NewQuestions->DelayAnswering) e = m->NewQuestions->DelayAnswering;
        if (m->NewQuestions)
                {
                if (m->NewQuestions->DelayAnswering) e = m->NewQuestions->DelayAnswering;
@@ -2623,15 +2652,25 @@ mDNSlocal mDNSs32 GetNextScheduledEvent(const mDNS *const m)
                }
        if (m->NewLocalOnlyQuestions)                                   return(m->timenow);
        if (m->NewLocalRecords && LocalRecordReady(m->NewLocalRecords)) return(m->timenow);
                }
        if (m->NewLocalOnlyQuestions)                                   return(m->timenow);
        if (m->NewLocalRecords && LocalRecordReady(m->NewLocalRecords)) return(m->timenow);
-       if (m->SuppressSending)                                         return(m->SuppressSending);
 #ifndef UNICAST_DISABLED
        if (e - m->NextuDNSEvent         > 0) e = m->NextuDNSEvent;
 #ifndef UNICAST_DISABLED
        if (e - m->NextuDNSEvent         > 0) e = m->NextuDNSEvent;
+       if (e - m->NextScheduledNATOp    > 0) e = m->NextScheduledNATOp;
 #endif
        if (e - m->NextCacheCheck        > 0) e = m->NextCacheCheck;
 #endif
        if (e - m->NextCacheCheck        > 0) e = m->NextCacheCheck;
-       if (e - m->NextScheduledQuery    > 0) e = m->NextScheduledQuery;
-       if (e - m->NextScheduledProbe    > 0) e = m->NextScheduledProbe;
-       if (e - m->NextScheduledResponse > 0) e = m->NextScheduledResponse;
-       if (e - m->NextScheduledNATOp    > 0) e = m->NextScheduledNATOp;
+
+       if (!m->SleepState)
+               {
+               if (m->SuppressSending)
+                       {
+                       if (e - m->SuppressSending       > 0) e = m->SuppressSending;
+                       }
+               else
+                       {
+                       if (e - m->NextScheduledQuery    > 0) e = m->NextScheduledQuery;
+                       if (e - m->NextScheduledProbe    > 0) e = m->NextScheduledProbe;
+                       if (e - m->NextScheduledResponse > 0) e = m->NextScheduledResponse;
+                       }
+               }
        return(e);
        }
 
        return(e);
        }
 
index 847957316a1b9eee02916d58b858b92171322f4b..f186ac69aac33f5a4fb3c10055199e2f3b4fac42 100644 (file)
     Change History (most recent first):
 
 $Log: DNSCommon.h,v $
     Change History (most recent first):
 
 $Log: DNSCommon.h,v $
+Revision 1.57  2007/12/13 20:20:17  cheshire
+Minor efficiency tweaks -- converted IdenticalResourceRecord, IdenticalSameNameRecord, and
+SameRData from functions to macros, which allows the code to be inlined (the compiler can't
+inline a function defined in a different compilation unit) and therefore optimized better.
+
+Revision 1.56  2007/12/13 00:13:03  cheshire
+Simplified RDataHashValue to take a single ResourceRecord pointer, instead of separate rdlength and RDataBody
+
+Revision 1.55  2007/12/13 00:09:28  cheshire
+For completeness added MX, AFSDB, RT, KX to list of RRTYPES that are considered to have a target domainname in their rdata
+
 Revision 1.54  2007/10/05 17:56:10  cheshire
 Move CountLabels and SkipLeadingLabels to DNSCommon.c so they're callable from other files
 
 Revision 1.54  2007/10/05 17:56:10  cheshire
 Move CountLabels and SkipLeadingLabels to DNSCommon.c so they're callable from other files
 
@@ -192,18 +203,47 @@ extern void AppendLabelSuffix(domainlabel *name, mDNSu32 val, mDNSBool RichText)
 #pragma mark - Resource Record Utility Functions
 #endif
 
 #pragma mark - Resource Record Utility Functions
 #endif
 
-extern mDNSu32 RDataHashValue(mDNSu16 const rdlength, const RDataBody *const rdb);
+// IdenticalResourceRecord returns true if two resources records have
+// the same name, type, class, and identical rdata (InterfaceID and TTL may differ)
+
+// IdenticalSameNameRecord is the same, except it skips the expensive SameDomainName() check,
+// which is at its most expensive and least useful in cases where we know in advance that the names match
+
+// Note: The dominant use of IdenticalResourceRecord is from ProcessQuery(), handling known-answer lists. In this case
+// it's common to have a whole bunch or records with exactly the same name (e.g. "_http._tcp.local") but different RDATA.
+// The SameDomainName() check is expensive when the names match, and in this case *all* the names match, so we
+// used to waste a lot of CPU time verifying that the names match, only then to find that the RDATA is different.
+// We observed mDNSResponder spending 30% of its total CPU time on this single task alone.
+// By swapping the checks so that we check the RDATA first, we can quickly detect when it's different
+// (99% of the time) and then bail out before we waste time on the expensive SameDomainName() check.
+
+#define IdenticalResourceRecord(r1,r2) ( \
+       (r1)->rrtype    == (r2)->rrtype      && \
+       (r1)->rrclass   == (r2)->rrclass     && \
+       (r1)->namehash  == (r2)->namehash    && \
+       (r1)->rdlength  == (r2)->rdlength    && \
+       (r1)->rdatahash == (r2)->rdatahash   && \
+       SameRDataBody((r1), &(r2)->rdata->u) && \
+       SameDomainName((r1)->name, (r2)->name))
+
+#define IdenticalSameNameRecord(r1,r2) ( \
+       (r1)->rrtype    == (r2)->rrtype      && \
+       (r1)->rrclass   == (r2)->rrclass     && \
+       (r1)->rdlength  == (r2)->rdlength    && \
+       (r1)->rdatahash == (r2)->rdatahash   && \
+       SameRDataBody((r1), &(r2)->rdata->u))
+
+extern mDNSu32 RDataHashValue(const ResourceRecord *const rr);
 extern mDNSBool SameRDataBody(const ResourceRecord *const r1, const RDataBody *const r2);
 extern mDNSBool SameRDataBody(const ResourceRecord *const r1, const RDataBody *const r2);
-extern mDNSBool SameRData(const ResourceRecord *const r1, const ResourceRecord *const r2);
+#define SameRData(r1,r2) ((r1)->rrtype == (r2)->rrtype && (r1)->rdlength == (r2)->rdlength && (r1)->rdatahash == (r2)->rdatahash && SameRDataBody((r1), &(r2)->rdata->u))
 extern mDNSBool ResourceRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
 extern mDNSBool SameNameRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
 extern mDNSBool ResourceRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
 extern mDNSBool SameNameRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
-extern mDNSBool SameResourceRecord(ResourceRecord *r1, ResourceRecord *r2);
 extern mDNSu16 GetRDLength(const ResourceRecord *const rr, mDNSBool estimate);
 extern mDNSBool ValidateRData(const mDNSu16 rrtype, const mDNSu16 rdlength, const RData *const rd);
 
 #define GetRRDomainNameTarget(RR) (                                                                          \
 extern mDNSu16 GetRDLength(const ResourceRecord *const rr, mDNSBool estimate);
 extern mDNSBool ValidateRData(const mDNSu16 rrtype, const mDNSu16 rdlength, const RData *const rd);
 
 #define GetRRDomainNameTarget(RR) (                                                                          \
-       ((RR)->rrtype == kDNSType_CNAME || (RR)->rrtype == kDNSType_PTR || (RR)->rrtype == kDNSType_NS)          \
-                                                                        ? &(RR)->rdata->u.name       :          \
+       ((RR)->rrtype == kDNSType_NS || (RR)->rrtype == kDNSType_CNAME || (RR)->rrtype == kDNSType_PTR || (RR)->rrtype == kDNSType_DNAME) ? &(RR)->rdata->u.name        : \
+       ((RR)->rrtype == kDNSType_MX || (RR)->rrtype == kDNSType_AFSDB || (RR)->rrtype == kDNSType_RT  || (RR)->rrtype == kDNSType_KX   ) ? &(RR)->rdata->u.mx.exchange : \
        ((RR)->rrtype == kDNSType_SRV                                  ) ? &(RR)->rdata->u.srv.target : mDNSNULL )
 
 #define LocalRecordReady(X) ((X)->resrec.RecordType != kDNSRecordTypeUnique && (X)->resrec.RecordType != kDNSRecordTypeDeregistering)
        ((RR)->rrtype == kDNSType_SRV                                  ) ? &(RR)->rdata->u.srv.target : mDNSNULL )
 
 #define LocalRecordReady(X) ((X)->resrec.RecordType != kDNSRecordTypeUnique && (X)->resrec.RecordType != kDNSRecordTypeDeregistering)
index 809499bf64f2e51c195d7ed25206fa68601350fb..09ff7c7f7c077a9d3817b4793f15bcb9053bc1a2 100644 (file)
     Change History (most recent first):
 
 $Log: DNSDigest.c,v $
     Change History (most recent first):
 
 $Log: DNSDigest.c,v $
+Revision 1.25  2007/12/17 23:48:29  cheshire
+DNSDigest_SignMessage doesn't need to return a result -- it already updates the 'end' parameter
+
+Revision 1.24  2007/11/30 23:03:51  cheshire
+Fixes for EFI: Use "mDNSPlatformMemCopy" instead of assuming existence of "memcpy"
+
 Revision 1.23  2007/09/21 21:12:36  cheshire
 DNSDigest_SignMessage does not need separate "mDNSu16 *numAdditionals" parameter
 
 Revision 1.23  2007/09/21 21:12:36  cheshire
 DNSDigest_SignMessage does not need separate "mDNSu16 *numAdditionals" parameter
 
@@ -810,7 +816,7 @@ int HASH_UPDATE (HASH_CTX *c, const void *data_, unsigned long len)
 #if !defined(HASH_BLOCK_DATA_ORDER)
                        while (sw--)
                                {
 #if !defined(HASH_BLOCK_DATA_ORDER)
                        while (sw--)
                                {
-                               memcpy (p=c->data,data,HASH_CBLOCK);
+                               mDNSPlatformMemCopy(p=c->data,data,HASH_CBLOCK);
                                HASH_BLOCK_DATA_ORDER_ALIGNED(c,p,1);
                                data+=HASH_CBLOCK;
                                len-=HASH_CBLOCK;
                                HASH_BLOCK_DATA_ORDER_ALIGNED(c,p,1);
                                data+=HASH_CBLOCK;
                                len-=HASH_CBLOCK;
@@ -853,7 +859,7 @@ void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data)
        else
 #if !defined(HASH_BLOCK_DATA_ORDER)
                {
        else
 #if !defined(HASH_BLOCK_DATA_ORDER)
                {
-               memcpy (c->data,data,HASH_CBLOCK);
+               mDNSPlatformMemCopy(c->data,data,HASH_CBLOCK);
                HASH_BLOCK_DATA_ORDER_ALIGNED (c,c->data,1);
                }
 #endif
                HASH_BLOCK_DATA_ORDER_ALIGNED (c,c->data,1);
                }
 #endif
@@ -1404,7 +1410,7 @@ mDNSexport mDNSs32 DNSDigest_ConstructHMACKeyfromBase64(DomainAuthInfo *info, co
        return(keylen);
        }
 
        return(keylen);
        }
 
-mDNSexport mDNSu8 *DNSDigest_SignMessage(DNSMessage *msg, mDNSu8 **end, DomainAuthInfo *info, mDNSu16 tcode)
+mDNSexport void DNSDigest_SignMessage(DNSMessage *msg, mDNSu8 **end, DomainAuthInfo *info, mDNSu16 tcode)
        {
        AuthRecord tsig;
        mDNSu8  *rdata, *const countPtr = (mDNSu8 *)&msg->h.numAdditionals;     // Get existing numAdditionals value
        {
        AuthRecord tsig;
        mDNSu8  *rdata, *const countPtr = (mDNSu8 *)&msg->h.numAdditionals;     // Get existing numAdditionals value
@@ -1447,7 +1453,7 @@ mDNSexport mDNSu8 *DNSDigest_SignMessage(DNSMessage *msg, mDNSu8 **end, DomainAu
        // time
        // get UTC (universal time), convert to 48-bit unsigned in network byte order
        utc32 = (mDNSu32)mDNSPlatformUTC();
        // time
        // get UTC (universal time), convert to 48-bit unsigned in network byte order
        utc32 = (mDNSu32)mDNSPlatformUTC();
-       if (utc32 == (unsigned)-1) { LogMsg("ERROR: DNSDigest_SignMessage - mDNSPlatformUTC returned bad time -1"); return mDNSNULL; }
+       if (utc32 == (unsigned)-1) { LogMsg("ERROR: DNSDigest_SignMessage - mDNSPlatformUTC returned bad time -1"); *end = mDNSNULL; }
        utc48[0] = 0;
        utc48[1] = 0;
        utc48[2] = (mDNSu8)((utc32 >> 24) & 0xff);
        utc48[0] = 0;
        utc48[1] = 0;
        utc48[2] = (mDNSu8)((utc32 >> 24) & 0xff);
@@ -1497,13 +1503,11 @@ mDNSexport mDNSu8 *DNSDigest_SignMessage(DNSMessage *msg, mDNSu8 **end, DomainAu
        
        tsig.resrec.rdlength = (mDNSu16)(rdata - tsig.resrec.rdata->u.data);
        *end = PutResourceRecordTTLJumbo(msg, ptr, &numAdditionals, &tsig.resrec, 0);
        
        tsig.resrec.rdlength = (mDNSu16)(rdata - tsig.resrec.rdata->u.data);
        *end = PutResourceRecordTTLJumbo(msg, ptr, &numAdditionals, &tsig.resrec, 0);
-       if (!*end) { LogMsg("ERROR: DNSDigest_SignMessage - could not put TSIG"); return mDNSNULL; }
+       if (!*end) { LogMsg("ERROR: DNSDigest_SignMessage - could not put TSIG"); *end = mDNSNULL; return; }
 
        // Write back updated numAdditionals value
        countPtr[0] = (mDNSu8)(numAdditionals >> 8);
        countPtr[1] = (mDNSu8)(numAdditionals &  0xFF);
 
        // Write back updated numAdditionals value
        countPtr[0] = (mDNSu8)(numAdditionals >> 8);
        countPtr[1] = (mDNSu8)(numAdditionals &  0xFF);
-
-       return *end;
        }
 
 mDNSexport mDNSBool DNSDigest_VerifyMessage(DNSMessage *msg, mDNSu8 *end, LargeCacheRecord * lcr, DomainAuthInfo *info, mDNSu16 * rcode, mDNSu16 * tcode)
        }
 
 mDNSexport mDNSBool DNSDigest_VerifyMessage(DNSMessage *msg, mDNSu8 *end, LargeCacheRecord * lcr, DomainAuthInfo *info, mDNSu16 * rcode, mDNSu16 * tcode)
index 854c6565d8164e187cfae154c9a8af6163b6af3b..2d4f110d518bfcb598bc5517f16112eb4230a29c 100755 (executable)
     Change History (most recent first):
 
 $Log: mDNS.c,v $
     Change History (most recent first):
 
 $Log: mDNS.c,v $
+Revision 1.767  2007/12/22 02:25:29  cheshire
+<rdar://problem/5661128> Records and Services sometimes not re-registering on wake from sleep
+
+Revision 1.766  2007/12/15 01:12:27  cheshire
+<rdar://problem/5526796> Need to remove active LLQs from server upon question cancellation, on sleep, and on shutdown
+
+Revision 1.765  2007/12/15 00:18:51  cheshire
+Renamed question->origLease to question->ReqLease
+
+Revision 1.764  2007/12/14 00:49:53  cheshire
+Fixed crash in mDNS_StartExit -- the service deregistration loop needs to use
+the CurrentServiceRecordSet mechanism to guard against services being deleted,
+just like the record deregistration loop uses m->CurrentRecord.
+
+Revision 1.763  2007/12/13 20:20:17  cheshire
+Minor efficiency tweaks -- converted IdenticalResourceRecord, IdenticalSameNameRecord, and
+SameRData from functions to macros, which allows the code to be inlined (the compiler can't
+inline a function defined in a different compilation unit) and therefore optimized better.
+
+Revision 1.762  2007/12/13 00:13:03  cheshire
+Simplified RDataHashValue to take a single ResourceRecord pointer, instead of separate rdlength and RDataBody
+
+Revision 1.761  2007/12/13 00:03:31  cheshire
+Improved efficiency in IdenticalResourceRecord() by doing SameRData() check before SameDomainName() check
+
+Revision 1.760  2007/12/08 00:36:19  cheshire
+<rdar://problem/5636422> Updating TXT records is too slow
+Remove unnecessary delays on announcing record updates, and on processing them on reception
+
+Revision 1.759  2007/12/07 22:41:29  cheshire
+<rdar://problem/5526800> BTMM: Need to clean up registrations on shutdown
+Further refinements -- records on the DuplicateRecords list were getting missed on shutdown
+
+Revision 1.758  2007/12/07 00:45:57  cheshire
+<rdar://problem/5526800> BTMM: Need to clean up registrations on shutdown
+
+Revision 1.757  2007/12/06 00:22:27  mcguire
+<rdar://problem/5604567> BTMM: Doesn't work with Linksys WAG300N 1.01.06 (sending from 1026/udp)
+
+Revision 1.756  2007/12/05 01:52:30  cheshire
+<rdar://problem/5624763> BTMM: getaddrinfo_async_start returns EAI_NONAME when resolving BTMM hostname
+Delay returning IPv4 address ("A") results for autotunnel names until after we've set up the tunnel (or tried to)
+
+Revision 1.755  2007/12/03 23:36:45  cheshire
+<rdar://problem/5623140> mDNSResponder unicast DNS improvements
+Need to check GetServerForName() result is non-null before dereferencing pointer
+
+Revision 1.754  2007/12/01 01:21:27  jgraessley
+<rdar://problem/5623140> mDNSResponder unicast DNS improvements
+
+Revision 1.753  2007/12/01 00:44:15  cheshire
+Fixed compile warnings, e.g. declaration of 'rr' shadows a previous local
+
+Revision 1.752  2007/11/14 01:10:51  cheshire
+Fixed LogOperation() message wording
+
 Revision 1.751  2007/10/30 23:49:41  cheshire
 <rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
 LLQ state was not being transferred properly between duplicate questions
 Revision 1.751  2007/10/30 23:49:41  cheshire
 <rdar://problem/5519458> BTMM: Machines don't appear in the sidebar on wake from sleep
 LLQ state was not being transferred properly between duplicate questions
@@ -893,7 +949,7 @@ mDNSlocal mDNSBool AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID Int
 mDNSlocal void AnswerLocalOnlyQuestionWithResourceRecord(mDNS *const m, DNSQuestion *q, AuthRecord *rr, QC_result AddRecord)
        {
        // Indicate that we've given at least one positive answer for this record, so we should be prepared to send a goodbye for it
 mDNSlocal void AnswerLocalOnlyQuestionWithResourceRecord(mDNS *const m, DNSQuestion *q, AuthRecord *rr, QC_result AddRecord)
        {
        // Indicate that we've given at least one positive answer for this record, so we should be prepared to send a goodbye for it
-       if (AddRecord) rr->LocalAnswer = mDNStrue;
+       if (AddRecord) rr->AnsweredLocalQ = mDNStrue;
        mDNS_DropLockBeforeCallback();          // Allow client to legally make mDNS API calls from the callback
        if (q->QuestionCallback && !q->NoAnswer)
                q->QuestionCallback(m, q, &rr->resrec, AddRecord);
        mDNS_DropLockBeforeCallback();          // Allow client to legally make mDNS API calls from the callback
        if (q->QuestionCallback && !q->NoAnswer)
                q->QuestionCallback(m, q, &rr->resrec, AddRecord);
@@ -1015,40 +1071,7 @@ mDNSlocal mDNSBool PacketRRMatchesSignature(const CacheRecord *const pktrr, cons
                SameDomainName(pktrr->resrec.name, authrr->resrec.name));
        }
 
                SameDomainName(pktrr->resrec.name, authrr->resrec.name));
        }
 
-// IdenticalResourceRecord returns true if two resources records have
-// the same name, type, class, and identical rdata (InterfaceID and TTL may differ)
-
-// IdenticalSameNameRecord is the same, except it skips the expensive SameDomainName() check,
-// which is at its most expensive and least useful in cases where we know in advance that the names match
-
-mDNSlocal mDNSBool IdenticalResourceRecord(const ResourceRecord *const r1, const ResourceRecord *const r2)
-       {
-       if (!r1) { LogMsg("IdenticalResourceRecord ERROR: r1 is NULL"); return(mDNSfalse); }
-       if (!r2) { LogMsg("IdenticalResourceRecord ERROR: r2 is NULL"); return(mDNSfalse); }
-       if (r1->rrtype != r2->rrtype || r1->rrclass != r2->rrclass || r1->namehash != r2->namehash || !SameDomainName(r1->name, r2->name))
-               return(mDNSfalse);
-       return(SameRData(r1, r2));
-       }
-
-mDNSlocal mDNSBool IdenticalSameNameRecord(const ResourceRecord *const r1, const ResourceRecord *const r2)
-       {
-       if (!r1) { LogMsg("IdenticalSameNameRecord ERROR: r1 is NULL"); return(mDNSfalse); }
-       if (!r2) { LogMsg("IdenticalSameNameRecord ERROR: r2 is NULL"); return(mDNSfalse); }
-       if (r1->rrtype != r2->rrtype || r1->rrclass != r2->rrclass)
-               return(mDNSfalse);
-
-#if VerifySameNameAssumptions
-       if (r1->namehash != r2->namehash || !SameDomainName(r1->name, r2->name))
-               {
-               LogMsg("Bogus IdenticalSameNameRecord call: %##s does not match %##s", r1->name->c, r1->name->c);
-               return(mDNSfalse);
-               }
-#endif
-
-       return(SameRData(r1, r2));
-       }
-
-// CacheRecord *ks is the CacheRecord from the known answer list in the query.
+// CacheRecord *ka is the CacheRecord from the known answer list in the query.
 // This is the information that the requester believes to be correct.
 // AuthRecord *rr is the answer we are proposing to give, if not suppressed.
 // This is the information that we believe to be correct.
 // This is the information that the requester believes to be correct.
 // AuthRecord *rr is the answer we are proposing to give, if not suppressed.
 // This is the information that we believe to be correct.
@@ -1088,8 +1111,10 @@ mDNSlocal void SetNextAnnounceProbeTime(mDNS *const m, const AuthRecord *const r
                }
        }
 
                }
        }
 
-mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr)
+mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr, mDNSs32 interval)
        {
        {
+       rr->ThisAPInterval = interval;
+
        // To allow us to aggregate probes when a group of services are registered together,
        // the first probe is delayed 1/4 second. This means the common-case behaviour is:
        // 1/4 second wait; probe
        // To allow us to aggregate probes when a group of services are registered together,
        // the first probe is delayed 1/4 second. This means the common-case behaviour is:
        // 1/4 second wait; probe
@@ -1097,19 +1122,22 @@ mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr)
        // 1/4 second wait; probe
        // 1/4 second wait; announce (i.e. service is normally announced exactly one second after being registered)
 
        // 1/4 second wait; probe
        // 1/4 second wait; announce (i.e. service is normally announced exactly one second after being registered)
 
-       // If we have no probe suppression time set, or it is in the past, set it now
-       if (m->SuppressProbes == 0 || m->SuppressProbes - m->timenow < 0)
+       if (rr->ProbeCount)
                {
                {
-               m->SuppressProbes = NonZeroTime(m->timenow + DefaultProbeIntervalForTypeUnique);
-               // If we already have a probe scheduled to go out sooner, then use that time to get better aggregation
-               if (m->SuppressProbes - m->NextScheduledProbe >= 0)
-                       m->SuppressProbes = m->NextScheduledProbe;
-               // If we already have a query scheduled to go out sooner, then use that time to get better aggregation
-               if (m->SuppressProbes - m->NextScheduledQuery >= 0)
-                       m->SuppressProbes = m->NextScheduledQuery;
+               // If we have no probe suppression time set, or it is in the past, set it now
+               if (m->SuppressProbes == 0 || m->SuppressProbes - m->timenow < 0)
+                       {
+                       m->SuppressProbes = NonZeroTime(m->timenow + DefaultProbeIntervalForTypeUnique);
+                       // If we already have a *probe* scheduled to go out sooner, then use that time to get better aggregation
+                       if (m->SuppressProbes - m->NextScheduledProbe >= 0)
+                               m->SuppressProbes = m->NextScheduledProbe;
+                       // If we already have a *query* scheduled to go out sooner, then use that time to get better aggregation
+                       if (m->SuppressProbes - m->NextScheduledQuery >= 0)
+                               m->SuppressProbes = m->NextScheduledQuery;
+                       }
                }
                }
-       
-       rr->LastAPTime      = m->SuppressProbes - rr->ThisAPInterval;
+
+       rr->LastAPTime      = m->SuppressProbes - interval;
        // Set LastMCTime to now, to inhibit multicast responses
        // (no need to send additional multicast responses when we're announcing anyway)
        rr->LastMCTime      = m->timenow;
        // Set LastMCTime to now, to inhibit multicast responses
        // (no need to send additional multicast responses when we're announcing anyway)
        rr->LastMCTime      = m->timenow;
@@ -1118,12 +1146,16 @@ mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr)
        // If this is a record type that's not going to probe, then delay its first announcement so that
        // it will go out synchronized with the first announcement for the other records that *are* probing.
        // This is a minor performance tweak that helps keep groups of related records synchronized together.
        // If this is a record type that's not going to probe, then delay its first announcement so that
        // it will go out synchronized with the first announcement for the other records that *are* probing.
        // This is a minor performance tweak that helps keep groups of related records synchronized together.
-       // The addition of "rr->ThisAPInterval / 2" is to make sure that, in the event that any of the probes are
+       // The addition of "interval / 2" is to make sure that, in the event that any of the probes are
        // delayed by a few milliseconds, this announcement does not inadvertently go out *before* the probing is complete.
        // When the probing is complete and those records begin to announce, these records will also be picked up and accelerated,
        // because they will meet the criterion of being at least half-way to their scheduled announcement time.
        // delayed by a few milliseconds, this announcement does not inadvertently go out *before* the probing is complete.
        // When the probing is complete and those records begin to announce, these records will also be picked up and accelerated,
        // because they will meet the criterion of being at least half-way to their scheduled announcement time.
-       if (rr->resrec.RecordType != kDNSRecordTypeUnique)
-               rr->LastAPTime += DefaultProbeIntervalForTypeUnique * DefaultProbeCountForTypeUnique + rr->ThisAPInterval / 2;
+       // The exception is unique records that have already been verified and are just being updated
+       // via mDNS_Update() -- for these we want to announce the new value immediately, without delay.
+       if (rr->resrec.RecordType == kDNSRecordTypeVerified)
+               rr->LastAPTime = m->timenow - interval;
+       else if (rr->resrec.RecordType != kDNSRecordTypeUnique)
+               rr->LastAPTime += DefaultProbeIntervalForTypeUnique * DefaultProbeCountForTypeUnique + interval / 2;
        
        SetNextAnnounceProbeTime(m, rr);
        }
        
        SetNextAnnounceProbeTime(m, rr);
        }
@@ -1158,8 +1190,7 @@ mDNSlocal void SetTargetToHostName(mDNS *const m, AuthRecord *const rr)
 
                rr->AnnounceCount  = InitialAnnounceCount;
                rr->RequireGoodbye = mDNSfalse;
 
                rr->AnnounceCount  = InitialAnnounceCount;
                rr->RequireGoodbye = mDNSfalse;
-               rr->ThisAPInterval = DefaultAPIntervalForRecordType(rr->resrec.RecordType);
-               InitializeLastAPTime(m,rr);
+               InitializeLastAPTime(m, rr, DefaultAPIntervalForRecordType(rr->resrec.RecordType));
                }
        }
 
                }
        }
 
@@ -1176,6 +1207,16 @@ mDNSlocal void AcknowledgeRecord(mDNS *const m, AuthRecord *const rr)
                }
        }
 
                }
        }
 
+mDNSlocal void ActivateUnicastRegistration(mDNS *const m, AuthRecord *const rr)
+       {
+       rr->ProbeCount     = 0;
+       rr->AnnounceCount  = 0;
+       rr->ThisAPInterval = 5 * mDNSPlatformOneSecond;         // After doubling, first retry will happen after ten seconds
+       rr->LastAPTime     = m->timenow - rr->ThisAPInterval;
+       rr->state = regState_FetchingZoneData;
+       rr->uselease = mDNStrue;
+       }
+
 // Two records qualify to be local duplicates if the RecordTypes are the same, or if one is Unique and the other Verified
 #define RecordLDT(A,B) ((A)->resrec.RecordType == (B)->resrec.RecordType || \
        ((A)->resrec.RecordType | (B)->resrec.RecordType) == (kDNSRecordTypeUnique | kDNSRecordTypeVerified))
 // Two records qualify to be local duplicates if the RecordTypes are the same, or if one is Unique and the other Verified
 #define RecordLDT(A,B) ((A)->resrec.RecordType == (B)->resrec.RecordType || \
        ((A)->resrec.RecordType | (B)->resrec.RecordType) == (kDNSRecordTypeUnique | kDNSRecordTypeVerified))
@@ -1259,7 +1300,7 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
        rr->ProbeCount        = DefaultProbeCountForRecordType(rr->resrec.RecordType);
        rr->AnnounceCount     = InitialAnnounceCount;
        rr->RequireGoodbye    = mDNSfalse;
        rr->ProbeCount        = DefaultProbeCountForRecordType(rr->resrec.RecordType);
        rr->AnnounceCount     = InitialAnnounceCount;
        rr->RequireGoodbye    = mDNSfalse;
-       rr->LocalAnswer       = mDNSfalse;
+       rr->AnsweredLocalQ    = mDNSfalse;
        rr->IncludeInProbe    = mDNSfalse;
        rr->ImmedAnswer       = mDNSNULL;
        rr->ImmedUnicast      = mDNSfalse;
        rr->IncludeInProbe    = mDNSfalse;
        rr->ImmedAnswer       = mDNSNULL;
        rr->ImmedUnicast      = mDNSfalse;
@@ -1270,8 +1311,7 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
        rr->NextResponse      = mDNSNULL;
        rr->NR_AnswerTo       = mDNSNULL;
        rr->NR_AdditionalTo   = mDNSNULL;
        rr->NextResponse      = mDNSNULL;
        rr->NR_AnswerTo       = mDNSNULL;
        rr->NR_AdditionalTo   = mDNSNULL;
-       rr->ThisAPInterval    = DefaultAPIntervalForRecordType(rr->resrec.RecordType);
-       if (!rr->AutoTarget) InitializeLastAPTime(m, rr);
+       if (!rr->AutoTarget) InitializeLastAPTime(m, rr, DefaultAPIntervalForRecordType(rr->resrec.RecordType));
 //     rr->LastAPTime        = Set for us in InitializeLastAPTime()
 //     rr->LastMCTime        = Set for us in InitializeLastAPTime()
 //     rr->LastMCInterface   = Set for us in InitializeLastAPTime()
 //     rr->LastAPTime        = Set for us in InitializeLastAPTime()
 //     rr->LastMCTime        = Set for us in InitializeLastAPTime()
 //     rr->LastMCInterface   = Set for us in InitializeLastAPTime()
@@ -1328,7 +1368,7 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
                { LogMsg("Attempt to register record with invalid rdata: %s", ARDisplayString(m, rr)); return(mStatus_Invalid); }
 
        rr->resrec.namehash   = DomainNameHashValue(rr->resrec.name);
                { LogMsg("Attempt to register record with invalid rdata: %s", ARDisplayString(m, rr)); return(mStatus_Invalid); }
 
        rr->resrec.namehash   = DomainNameHashValue(rr->resrec.name);
-       rr->resrec.rdatahash  = target ? DomainNameHashValue(target) : RDataHashValue(rr->resrec.rdlength, &rr->resrec.rdata->u);
+       rr->resrec.rdatahash  = target ? DomainNameHashValue(target) : RDataHashValue(&rr->resrec);
        
        if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly)
                {
        
        if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly)
                {
@@ -1384,11 +1424,7 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
        else
                {
                if (rr->resrec.RecordType == kDNSRecordTypeUnique) rr->resrec.RecordType = kDNSRecordTypeVerified;
        else
                {
                if (rr->resrec.RecordType == kDNSRecordTypeUnique) rr->resrec.RecordType = kDNSRecordTypeVerified;
-               rr->ProbeCount    = 0;
-               rr->AnnounceCount = 0;
-               rr->state = regState_FetchingZoneData;
-               rr->uselease = mDNStrue;
-               rr->nta = StartGetZoneData(m, rr->resrec.name, ZoneServiceUpdate, RecordRegistrationGotZoneData, rr);
+               ActivateUnicastRegistration(m, rr);
                }
 #endif
        
                }
 #endif
        
@@ -1522,7 +1558,7 @@ mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr,
                }
 #endif UNICAST_DISABLED
 
                }
 #endif UNICAST_DISABLED
 
-       if (RecordType == kDNSRecordTypeShared && (rr->RequireGoodbye || rr->LocalAnswer))
+       if (RecordType == kDNSRecordTypeShared && (rr->RequireGoodbye || rr->AnsweredLocalQ))
                {
                verbosedebugf("mDNS_Deregister_internal: Sending deregister for %s", ARDisplayString(m, rr));
                rr->resrec.RecordType    = kDNSRecordTypeDeregistering;
                {
                verbosedebugf("mDNS_Deregister_internal: Sending deregister for %s", ARDisplayString(m, rr));
                rr->resrec.RecordType    = kDNSRecordTypeDeregistering;
@@ -1732,7 +1768,7 @@ mDNSexport void CompleteDeregistration(mDNS *const m, AuthRecord *rr)
        // it should go ahead and immediately dispose of this registration
        rr->resrec.RecordType = kDNSRecordTypeShared;
        rr->RequireGoodbye    = mDNSfalse;
        // it should go ahead and immediately dispose of this registration
        rr->resrec.RecordType = kDNSRecordTypeShared;
        rr->RequireGoodbye    = mDNSfalse;
-       if (rr->LocalAnswer) { AnswerLocalQuestions(m, rr, mDNSfalse); rr->LocalAnswer = mDNSfalse; }
+       if (rr->AnsweredLocalQ) { AnswerLocalQuestions(m, rr, mDNSfalse); rr->AnsweredLocalQ = mDNSfalse; }
        mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);             // Don't touch rr after this
        }
 
        mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);             // Don't touch rr after this
        }
 
@@ -2062,13 +2098,13 @@ mDNSlocal void SendResponses(mDNS *const m)
                if (rr->SendRNow)
                        {
                        if (rr->resrec.InterfaceID != mDNSInterface_LocalOnly)
                if (rr->SendRNow)
                        {
                        if (rr->resrec.InterfaceID != mDNSInterface_LocalOnly)
-                               LogMsg("SendResponses: No active interface to send: %s", ARDisplayString(m, rr));
+                               LogMsg("SendResponses: No active interface to send: %02X %s", rr->resrec.RecordType, ARDisplayString(m, rr));
                        rr->SendRNow = mDNSNULL;
                        }
 
                if (rr->ImmedAnswer)
                        {
                        rr->SendRNow = mDNSNULL;
                        }
 
                if (rr->ImmedAnswer)
                        {
-                       if (rr->NewRData) CompleteRDataUpdate(m,rr);    // Update our rdata, clear the NewRData pointer, and return memory to the client
+                       if (rr->NewRData) CompleteRDataUpdate(m, rr);   // Update our rdata, clear the NewRData pointer, and return memory to the client
        
                        if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
                                CompleteDeregistration(m, rr);          // Don't touch rr after this
        
                        if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
                                CompleteDeregistration(m, rr);          // Don't touch rr after this
@@ -2094,11 +2130,14 @@ mDNSlocal void SendResponses(mDNS *const m)
 //    and is expiring, and had an original TTL more than ten seconds, we'll allow it to be one second late
 // 4. Else, it is expiring and had an original TTL of ten seconds or less (includes explicit goodbye packets),
 //    so allow at most 1/10 second lateness
 //    and is expiring, and had an original TTL more than ten seconds, we'll allow it to be one second late
 // 4. Else, it is expiring and had an original TTL of ten seconds or less (includes explicit goodbye packets),
 //    so allow at most 1/10 second lateness
+// 5. For records with rroriginalttl set to zero, that means we really want to delete them immediately
+//    (we have a new record with DelayDelivery set, waiting for the old record to go away before we can notify clients).
 #define CacheCheckGracePeriod(RR) (                                                   \
        ((RR)->DelayDelivery                           ) ? (mDNSPlatformOneSecond/10)   : \
        ((RR)->CRActiveQuestion == mDNSNULL            ) ? (60 * mDNSPlatformOneSecond) : \
        ((RR)->UnansweredQueries < MaxUnansweredQueries) ? (TicksTTL(rr)/50)            : \
 #define CacheCheckGracePeriod(RR) (                                                   \
        ((RR)->DelayDelivery                           ) ? (mDNSPlatformOneSecond/10)   : \
        ((RR)->CRActiveQuestion == mDNSNULL            ) ? (60 * mDNSPlatformOneSecond) : \
        ((RR)->UnansweredQueries < MaxUnansweredQueries) ? (TicksTTL(rr)/50)            : \
-       ((RR)->resrec.rroriginalttl > 10               ) ? (mDNSPlatformOneSecond)      : (mDNSPlatformOneSecond/10))
+       ((RR)->resrec.rroriginalttl > 10               ) ? (mDNSPlatformOneSecond)      : \
+       ((RR)->resrec.rroriginalttl > 0                ) ? (mDNSPlatformOneSecond/10)   : 0)
 
 // Note: MUST call SetNextCacheCheckTime any time we change:
 // rr->TimeRcvd
 
 // Note: MUST call SetNextCacheCheckTime any time we change:
 // rr->TimeRcvd
@@ -2211,7 +2250,7 @@ mDNSlocal mDNSBool BuildQuestion(mDNS *const m, DNSMessage *query, mDNSu8 **quer
                                                q->qname.c, DNSTypeName(q->qtype), newptr + forecast - query->data);
                                        query->h.numQuestions--;
                                        ka = *kalistptrptr;             // Go back to where we started and retract these answer records
                                                q->qname.c, DNSTypeName(q->qtype), newptr + forecast - query->data);
                                        query->h.numQuestions--;
                                        ka = *kalistptrptr;             // Go back to where we started and retract these answer records
-                                       while (*ka) { CacheRecord *rr = *ka; *ka = mDNSNULL; ka = &rr->NextInKAList; }
+                                       while (*ka) { CacheRecord *c = *ka; *ka = mDNSNULL; ka = &c->NextInKAList; }
                                        return(mDNSfalse);              // Return false, so we'll try again in the next packet
                                        }
                                }
                                        return(mDNSfalse);              // Return false, so we'll try again in the next packet
                                        }
                                }
@@ -2623,16 +2662,16 @@ mDNSlocal void SendQueries(mDNS *const m)
                // Put our known answer list (either new one from this question or questions, or remainder of old one from last time)
                while (KnownAnswerList)
                        {
                // Put our known answer list (either new one from this question or questions, or remainder of old one from last time)
                while (KnownAnswerList)
                        {
-                       CacheRecord *rr = KnownAnswerList;
-                       mDNSu32 SecsSinceRcvd = ((mDNSu32)(m->timenow - rr->TimeRcvd)) / mDNSPlatformOneSecond;
-                       mDNSu8 *newptr = PutResourceRecordTTL(&m->omsg, queryptr, &m->omsg.h.numAnswers, &rr->resrec, rr->resrec.rroriginalttl - SecsSinceRcvd);
+                       CacheRecord *ka = KnownAnswerList;
+                       mDNSu32 SecsSinceRcvd = ((mDNSu32)(m->timenow - ka->TimeRcvd)) / mDNSPlatformOneSecond;
+                       mDNSu8 *newptr = PutResourceRecordTTL(&m->omsg, queryptr, &m->omsg.h.numAnswers, &ka->resrec, ka->resrec.rroriginalttl - SecsSinceRcvd);
                        if (newptr)
                                {
                                verbosedebugf("SendQueries:   Put %##s (%s) at %d - %d",
                        if (newptr)
                                {
                                verbosedebugf("SendQueries:   Put %##s (%s) at %d - %d",
-                                       rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), queryptr - m->omsg.data, newptr - m->omsg.data);
+                                       ka->resrec.name->c, DNSTypeName(ka->resrec.rrtype), queryptr - m->omsg.data, newptr - m->omsg.data);
                                queryptr = newptr;
                                queryptr = newptr;
-                               KnownAnswerList = rr->NextInKAList;
-                               rr->NextInKAList = mDNSNULL;
+                               KnownAnswerList = ka->NextInKAList;
+                               ka->NextInKAList = mDNSNULL;
                                }
                        else
                                {
                                }
                        else
                                {
@@ -2886,7 +2925,7 @@ mDNSlocal void CacheRecordAdd(mDNS *const m, CacheRecord *rr)
                m->CurrentQuestion = m->Questions;
                while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
                        {
                m->CurrentQuestion = m->Questions;
                while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
                        {
-                       DNSQuestion *q = m->CurrentQuestion;
+                       q = m->CurrentQuestion;
                        if (ResourceRecordAnswersQuestion(&rr->resrec, q))
                                AnswerCurrentQuestionWithResourceRecord(m, rr, QC_add);
                        if (m->CurrentQuestion == q)    // If m->CurrentQuestion was not auto-advanced, do it ourselves now
                        if (ResourceRecordAnswersQuestion(&rr->resrec, q))
                                AnswerCurrentQuestionWithResourceRecord(m, rr, QC_add);
                        if (m->CurrentQuestion == q)    // If m->CurrentQuestion was not auto-advanced, do it ourselves now
@@ -3068,7 +3107,6 @@ mDNSlocal void CheckCacheExpiration(mDNS *const m, CacheGroup *const cg)
 mDNSlocal void AnswerNewQuestion(mDNS *const m)
        {
        mDNSBool ShouldQueryImmediately = mDNStrue;
 mDNSlocal void AnswerNewQuestion(mDNS *const m)
        {
        mDNSBool ShouldQueryImmediately = mDNStrue;
-       CacheRecord *rr;
        DNSQuestion *q = m->NewQuestions;               // Grab the question we're going to answer
        const mDNSu32 slot = HashSlot(&q->qname);
        CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
        DNSQuestion *q = m->NewQuestions;               // Grab the question we're going to answer
        const mDNSu32 slot = HashSlot(&q->qname);
        CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
@@ -3120,6 +3158,7 @@ mDNSlocal void AnswerNewQuestion(mDNS *const m)
 
        if (m->CurrentQuestion == q)
                {
 
        if (m->CurrentQuestion == q)
                {
+               CacheRecord *rr;
                for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
                        if (SameNameRecordAnswersQuestion(&rr->resrec, q))
                                {
                for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
                        if (SameNameRecordAnswersQuestion(&rr->resrec, q))
                                {
@@ -3487,15 +3526,8 @@ mDNSlocal void SuspendLLQs(mDNS *m)
        {
        DNSQuestion *q;
        for (q = m->Questions; q; q = q->next)
        {
        DNSQuestion *q;
        for (q = m->Questions; q; q = q->next)
-               if (ActiveQuestion(q) && !mDNSOpaque16IsZero(q->TargetQID) && q->LongLived)
-                       {
-                       // If necessary, tell server it can delete this LLQ state
-                       if (q->state == LLQ_Established) sendLLQRefresh(m, q, 0);
-                       if (q->nta) { CancelGetZoneData(m, q->nta); q->nta = mDNSNULL; }
-                       if (q->tcp) { DisposeTCPConn(q->tcp); q->tcp = mDNSNULL; }
-                       q->state = LLQ_InitialRequest;  // Will need to set up new LLQ on wake from sleep
-                       q->id = zeroOpaque64;
-                       }
+               if (ActiveQuestion(q) && !mDNSOpaque16IsZero(q->TargetQID) && q->LongLived && q->state == LLQ_Established)
+                       { q->ReqLease = 0; sendLLQRefresh(m, q); }
        }
 
 mDNSlocal void ActivateUnicastQuery(mDNS *const m, DNSQuestion *const question)
        }
 
 mDNSlocal void ActivateUnicastQuery(mDNS *const m, DNSQuestion *const question)
@@ -3503,7 +3535,12 @@ mDNSlocal void ActivateUnicastQuery(mDNS *const m, DNSQuestion *const question)
        // For now this AutoTunnel stuff is specific to Mac OS X.
        // In the future, if there's demand, we may see if we can abstract it out cleanly into the platform layer
 #if APPLE_OSX_mDNSResponder
        // For now this AutoTunnel stuff is specific to Mac OS X.
        // In the future, if there's demand, we may see if we can abstract it out cleanly into the platform layer
 #if APPLE_OSX_mDNSResponder
-       if (question->qtype == kDNSType_AAAA && question->AuthInfo && question->AuthInfo->AutoTunnel && question->QuestionCallback != AutoTunnelCallback)
+       // Even though BTMM client tunnels are only useful for AAAA queries, we need to treat v4 and v6 queries equally.
+       // Otherwise we can get the situation where the A query completes really fast (with an NXDOMAIN result) and the
+       // caller then gives up waiting for the AAAA result while we're still in the process of setting up the tunnel.
+       // To level the playing field, we block both A and AAAA queries while tunnel setup is in progress, and then
+       // returns results for both at the same time.
+       if (RRTypeIsAddressType(question->qtype) && question->AuthInfo && question->AuthInfo->AutoTunnel && question->QuestionCallback != AutoTunnelCallback)
                {
                question->NoAnswer = NoAnswer_Suspended;
                AddNewClientTunnel(m, question);
                {
                question->NoAnswer = NoAnswer_Suspended;
                AddNewClientTunnel(m, question);
@@ -3516,7 +3553,7 @@ mDNSlocal void ActivateUnicastQuery(mDNS *const m, DNSQuestion *const question)
                LogOperation("ActivateUnicastQuery: %##s %s%s",
                        question->qname.c, DNSTypeName(question->qtype), question->AuthInfo ? " (Private)" : "");
                if (question->nta) { CancelGetZoneData(m, question->nta); question->nta = mDNSNULL; }
                LogOperation("ActivateUnicastQuery: %##s %s%s",
                        question->qname.c, DNSTypeName(question->qtype), question->AuthInfo ? " (Private)" : "");
                if (question->nta) { CancelGetZoneData(m, question->nta); question->nta = mDNSNULL; }
-               if (question->LongLived) question->state = LLQ_InitialRequest;
+               if (question->LongLived) { question->state = LLQ_InitialRequest; question->id = zeroOpaque64; }
                question->ThisQInterval = InitialQuestionInterval;
                question->LastQTime     = m->timenow - question->ThisQInterval;
                SetNextQueryTime(m, question);
                question->ThisQInterval = InitialQuestionInterval;
                question->LastQTime     = m->timenow - question->ThisQInterval;
                SetNextQueryTime(m, question);
@@ -3570,12 +3607,13 @@ mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleepstate)
                m->CurrentQuestion = m->Questions;
                while (m->CurrentQuestion)
                        {
                m->CurrentQuestion = m->Questions;
                while (m->CurrentQuestion)
                        {
-                       DNSQuestion *q = m->CurrentQuestion;
+                       q = m->CurrentQuestion;
                        m->CurrentQuestion = m->CurrentQuestion->next;
                        if (!mDNSOpaque16IsZero(q->TargetQID)) ActivateUnicastQuery(m, q);
                        }
                        m->CurrentQuestion = m->CurrentQuestion->next;
                        if (!mDNSOpaque16IsZero(q->TargetQID)) ActivateUnicastQuery(m, q);
                        }
-               // and reactivtate record (and service) registrations
-               uDNS_Wake(m);
+               // and reactivtate service registrations
+               m->NextSRVUpdate = NonZeroTime(m->timenow + mDNSPlatformOneSecond);
+               LogOperation("WakeServiceRegistrations %d %d", m->timenow, m->NextSRVUpdate);
 #endif
         // 1. Retrigger all our mDNS questions
                for (q = m->Questions; q; q=q->next)                            // Scan our list of questions
 #endif
         // 1. Retrigger all our mDNS questions
                for (q = m->Questions; q; q=q->next)                            // Scan our list of questions
@@ -3596,13 +3634,16 @@ mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleepstate)
 
                // 3. Retrigger probing and announcing for all our authoritative records
                for (rr = m->ResourceRecords; rr; rr=rr->next)
 
                // 3. Retrigger probing and announcing for all our authoritative records
                for (rr = m->ResourceRecords; rr; rr=rr->next)
-                       if (!AuthRecord_uDNS(rr))
+                       if (AuthRecord_uDNS(rr))
+                               {
+                               ActivateUnicastRegistration(m, rr);
+                               }
+                       else
                                {
                                if (rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->DependentOn) rr->resrec.RecordType = kDNSRecordTypeUnique;
                                rr->ProbeCount     = DefaultProbeCountForRecordType(rr->resrec.RecordType);
                                rr->AnnounceCount  = InitialAnnounceCount;
                                {
                                if (rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->DependentOn) rr->resrec.RecordType = kDNSRecordTypeUnique;
                                rr->ProbeCount     = DefaultProbeCountForRecordType(rr->resrec.RecordType);
                                rr->AnnounceCount  = InitialAnnounceCount;
-                               rr->ThisAPInterval = DefaultAPIntervalForRecordType(rr->resrec.RecordType);
-                               InitializeLastAPTime(m, rr);
+                               InitializeLastAPTime(m, rr, DefaultAPIntervalForRecordType(rr->resrec.RecordType));
                                }
                }
 
                                }
                }
 
@@ -3824,7 +3865,7 @@ exit:
        m->rec.r.resrec.RecordType = 0;         // Clear RecordType to show we're not still using it
        }
 
        m->rec.r.resrec.RecordType = 0;         // Clear RecordType to show we're not still using it
        }
 
-mDNSlocal CacheRecord *FindIdenticalRecordInCache(const mDNS *const m, ResourceRecord *pktrr)
+mDNSlocal CacheRecord *FindIdenticalRecordInCache(const mDNS *const m, const ResourceRecord *const pktrr)
        {
        mDNSu32 slot = HashSlot(pktrr->name);
        CacheGroup *cg = CacheGroupForRecord(m, slot, pktrr);
        {
        mDNSu32 slot = HashSlot(pktrr->name);
        CacheGroup *cg = CacheGroupForRecord(m, slot, pktrr);
@@ -3928,24 +3969,24 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
                        {
                        const mDNSu32 slot = HashSlot(&pktq.qname);
                        CacheGroup *cg = CacheGroupForName(m, slot, pktq.qnamehash, &pktq.qname);
                        {
                        const mDNSu32 slot = HashSlot(&pktq.qname);
                        CacheGroup *cg = CacheGroupForName(m, slot, pktq.qnamehash, &pktq.qname);
-                       CacheRecord *rr;
+                       CacheRecord *cr;
 
                        // Make a list indicating which of our own cache records we expect to see updated as a result of this query
                        // Note: Records larger than 1K are not habitually multicast, so don't expect those to be updated
 
                        // Make a list indicating which of our own cache records we expect to see updated as a result of this query
                        // Note: Records larger than 1K are not habitually multicast, so don't expect those to be updated
-                       for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
-                               if (SameNameRecordAnswersQuestion(&rr->resrec, &pktq) && rr->resrec.rdlength <= SmallRecordLimit)
-                                       if (!rr->NextInKAList && eap != &rr->NextInKAList)
+                       for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)
+                               if (SameNameRecordAnswersQuestion(&cr->resrec, &pktq) && cr->resrec.rdlength <= SmallRecordLimit)
+                                       if (!cr->NextInKAList && eap != &cr->NextInKAList)
                                                {
                                                {
-                                               *eap = rr;
-                                               eap = &rr->NextInKAList;
-                                               if (rr->MPUnansweredQ == 0 || m->timenow - rr->MPLastUnansweredQT >= mDNSPlatformOneSecond)
+                                               *eap = cr;
+                                               eap = &cr->NextInKAList;
+                                               if (cr->MPUnansweredQ == 0 || m->timenow - cr->MPLastUnansweredQT >= mDNSPlatformOneSecond)
                                                        {
                                                        // Although MPUnansweredQ is only really used for multi-packet query processing,
                                                        // we increment it for both single-packet and multi-packet queries, so that it stays in sync
                                                        // with the MPUnansweredKA value, which by necessity is incremented for both query types.
                                                        {
                                                        // Although MPUnansweredQ is only really used for multi-packet query processing,
                                                        // we increment it for both single-packet and multi-packet queries, so that it stays in sync
                                                        // with the MPUnansweredKA value, which by necessity is incremented for both query types.
-                                                       rr->MPUnansweredQ++;
-                                                       rr->MPLastUnansweredQT = m->timenow;
-                                                       rr->MPExpectingKA = mDNStrue;
+                                                       cr->MPUnansweredQ++;
+                                                       cr->MPLastUnansweredQT = m->timenow;
+                                                       cr->MPExpectingKA = mDNStrue;
                                                        }
                                                }
        
                                                        }
                                                }
        
@@ -3983,7 +4024,6 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
        for (i=0; i<query->h.numAnswers; i++)                                           // For each record in the query's answer section...
                {
                // Get the record...
        for (i=0; i<query->h.numAnswers; i++)                                           // For each record in the query's answer section...
                {
                // Get the record...
-               AuthRecord *rr;
                CacheRecord *ourcacherr;
                ptr = GetLargeResourceRecord(m, query, ptr, end, InterfaceID, kDNSRecordTypePacketAns, &m->rec);
                if (!ptr) goto exit;
                CacheRecord *ourcacherr;
                ptr = GetLargeResourceRecord(m, query, ptr, end, InterfaceID, kDNSRecordTypePacketAns, &m->rec);
                if (!ptr) goto exit;
@@ -4033,10 +4073,10 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
                eap = &ExpectedAnswers;
                while (*eap)
                        {
                eap = &ExpectedAnswers;
                while (*eap)
                        {
-                       CacheRecord *rr = *eap;
-                       if (rr->resrec.InterfaceID == InterfaceID && IdenticalResourceRecord(&m->rec.r.resrec, &rr->resrec))
-                               { *eap = rr->NextInKAList; rr->NextInKAList = mDNSNULL; }
-                       else eap = &rr->NextInKAList;
+                       CacheRecord *cr = *eap;
+                       if (cr->resrec.InterfaceID == InterfaceID && IdenticalResourceRecord(&m->rec.r.resrec, &cr->resrec))
+                               { *eap = cr->NextInKAList; cr->NextInKAList = mDNSNULL; }
+                       else eap = &cr->NextInKAList;
                        }
                
                // See if this Known-Answer is a surprise to us. If so, we shouldn't suppress our own query.
                        }
                
                // See if this Known-Answer is a surprise to us. If so, we shouldn't suppress our own query.
@@ -4183,38 +4223,37 @@ exit:
        
        while (ExpectedAnswers)
                {
        
        while (ExpectedAnswers)
                {
-               CacheRecord *rr;
-               rr = ExpectedAnswers;
-               ExpectedAnswers = rr->NextInKAList;
-               rr->NextInKAList = mDNSNULL;
+               CacheRecord *cr = ExpectedAnswers;
+               ExpectedAnswers = cr->NextInKAList;
+               cr->NextInKAList = mDNSNULL;
                
                // For non-truncated queries, we can definitively say that we should expect
                // to be seeing a response for any records still left in the ExpectedAnswers list
                if (!(query->h.flags.b[0] & kDNSFlag0_TC))
                
                // For non-truncated queries, we can definitively say that we should expect
                // to be seeing a response for any records still left in the ExpectedAnswers list
                if (!(query->h.flags.b[0] & kDNSFlag0_TC))
-                       if (rr->UnansweredQueries == 0 || m->timenow - rr->LastUnansweredTime >= mDNSPlatformOneSecond)
+                       if (cr->UnansweredQueries == 0 || m->timenow - cr->LastUnansweredTime >= mDNSPlatformOneSecond)
                                {
                                {
-                               rr->UnansweredQueries++;
-                               rr->LastUnansweredTime = m->timenow;
-                               if (rr->UnansweredQueries > 1)
+                               cr->UnansweredQueries++;
+                               cr->LastUnansweredTime = m->timenow;
+                               if (cr->UnansweredQueries > 1)
                                        debugf("ProcessQuery: (!TC) UAQ %lu MPQ %lu MPKA %lu %s",
                                        debugf("ProcessQuery: (!TC) UAQ %lu MPQ %lu MPKA %lu %s",
-                                               rr->UnansweredQueries, rr->MPUnansweredQ, rr->MPUnansweredKA, CRDisplayString(m, rr));
-                               SetNextCacheCheckTime(m, rr);
+                                               cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr));
+                               SetNextCacheCheckTime(m, cr);
                                }
 
                // If we've seen multiple unanswered queries for this record,
                // then mark it to expire in five seconds if we don't get a response by then.
                                }
 
                // If we've seen multiple unanswered queries for this record,
                // then mark it to expire in five seconds if we don't get a response by then.
-               if (rr->UnansweredQueries >= MaxUnansweredQueries)
+               if (cr->UnansweredQueries >= MaxUnansweredQueries)
                        {
                        // Only show debugging message if this record was not about to expire anyway
                        {
                        // Only show debugging message if this record was not about to expire anyway
-                       if (RRExpireTime(rr) - m->timenow > 4 * mDNSPlatformOneSecond)
+                       if (RRExpireTime(cr) - m->timenow > 4 * mDNSPlatformOneSecond)
                                debugf("ProcessQuery: (Max) UAQ %lu MPQ %lu MPKA %lu mDNS_Reconfirm() for %s",
                                debugf("ProcessQuery: (Max) UAQ %lu MPQ %lu MPKA %lu mDNS_Reconfirm() for %s",
-                                       rr->UnansweredQueries, rr->MPUnansweredQ, rr->MPUnansweredKA, CRDisplayString(m, rr));
-                       mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForNoAnswer);
+                                       cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr));
+                       mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
                        }
                // Make a guess, based on the multi-packet query / known answer counts, whether we think we
                // should have seen an answer for this. (We multiply MPQ by 4 and MPKA by 5, to allow for
                // possible packet loss of up to 20% of the additional KA packets.)
                        }
                // Make a guess, based on the multi-packet query / known answer counts, whether we think we
                // should have seen an answer for this. (We multiply MPQ by 4 and MPKA by 5, to allow for
                // possible packet loss of up to 20% of the additional KA packets.)
-               else if (rr->MPUnansweredQ * 4 > rr->MPUnansweredKA * 5 + 8)
+               else if (cr->MPUnansweredQ * 4 > cr->MPUnansweredKA * 5 + 8)
                        {
                        // We want to do this conservatively.
                        // If there are so many machines on the network that they have to use multi-packet known-answer lists,
                        {
                        // We want to do this conservatively.
                        // If there are so many machines on the network that they have to use multi-packet known-answer lists,
@@ -4222,30 +4261,29 @@ exit:
                        // By setting the record to expire in four minutes, we achieve two things:
                        // (a) the 90-95% final expiration queries will be less bunched together
                        // (b) we allow some time for us to witness enough other failed queries that we don't have to do our own
                        // By setting the record to expire in four minutes, we achieve two things:
                        // (a) the 90-95% final expiration queries will be less bunched together
                        // (b) we allow some time for us to witness enough other failed queries that we don't have to do our own
-                       mDNSu32 remain = (mDNSu32)(RRExpireTime(rr) - m->timenow) / 4;
+                       mDNSu32 remain = (mDNSu32)(RRExpireTime(cr) - m->timenow) / 4;
                        if (remain > 240 * (mDNSu32)mDNSPlatformOneSecond)
                                remain = 240 * (mDNSu32)mDNSPlatformOneSecond;
                        
                        // Only show debugging message if this record was not about to expire anyway
                        if (remain > 240 * (mDNSu32)mDNSPlatformOneSecond)
                                remain = 240 * (mDNSu32)mDNSPlatformOneSecond;
                        
                        // Only show debugging message if this record was not about to expire anyway
-                       if (RRExpireTime(rr) - m->timenow > 4 * mDNSPlatformOneSecond)
+                       if (RRExpireTime(cr) - m->timenow > 4 * mDNSPlatformOneSecond)
                                debugf("ProcessQuery: (MPQ) UAQ %lu MPQ %lu MPKA %lu mDNS_Reconfirm() for %s",
                                debugf("ProcessQuery: (MPQ) UAQ %lu MPQ %lu MPKA %lu mDNS_Reconfirm() for %s",
-                                       rr->UnansweredQueries, rr->MPUnansweredQ, rr->MPUnansweredKA, CRDisplayString(m, rr));
+                                       cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr));
 
                        if (remain <= 60 * (mDNSu32)mDNSPlatformOneSecond)
 
                        if (remain <= 60 * (mDNSu32)mDNSPlatformOneSecond)
-                               rr->UnansweredQueries++;        // Treat this as equivalent to one definite unanswered query
-                       rr->MPUnansweredQ  = 0;                 // Clear MPQ/MPKA statistics
-                       rr->MPUnansweredKA = 0;
-                       rr->MPExpectingKA  = mDNSfalse;
+                               cr->UnansweredQueries++;        // Treat this as equivalent to one definite unanswered query
+                       cr->MPUnansweredQ  = 0;                 // Clear MPQ/MPKA statistics
+                       cr->MPUnansweredKA = 0;
+                       cr->MPExpectingKA  = mDNSfalse;
                        
                        if (remain < kDefaultReconfirmTimeForNoAnswer)
                                remain = kDefaultReconfirmTimeForNoAnswer;
                        
                        if (remain < kDefaultReconfirmTimeForNoAnswer)
                                remain = kDefaultReconfirmTimeForNoAnswer;
-                       mDNS_Reconfirm_internal(m, rr, remain);
+                       mDNS_Reconfirm_internal(m, cr, remain);
                        }
                }
        
        while (DupQuestions)
                {
                        }
                }
        
        while (DupQuestions)
                {
-               int i;
                DNSQuestion *q = DupQuestions;
                DupQuestions = q->NextInDQList;
                q->NextInDQList = mDNSNULL;
                DNSQuestion *q = DupQuestions;
                DupQuestions = q->NextInDQList;
                q->NextInDQList = mDNSNULL;
@@ -4338,7 +4376,7 @@ mDNSlocal mDNSBool ExpectingUnicastResponseForRecord(mDNS *const m, const mDNSAd
                                        if (mDNSSameOpaque16(q->TargetQID, id))                     return(mDNStrue);
                                //      if (q->LongLived && mDNSSameAddress(srcaddr, &q->servAddr)) return(mDNStrue); Shouldn't need this now that we have LLQType checking
                                        if (TrustedSource(m, srcaddr))                              return(mDNStrue);
                                        if (mDNSSameOpaque16(q->TargetQID, id))                     return(mDNStrue);
                                //      if (q->LongLived && mDNSSameAddress(srcaddr, &q->servAddr)) return(mDNStrue); Shouldn't need this now that we have LLQType checking
                                        if (TrustedSource(m, srcaddr))                              return(mDNStrue);
-                                       LogOperation("WARNING: Ignoring suspect uDNS response for %##s (%s) %#a from %#a: %s",
+                                       LogOperation("WARNING: Ignoring suspect uDNS response for %##s (%s) [q->Target %#a] from %#a: %s",
                                                q->qname.c, DNSTypeName(q->qtype), &q->Target, srcaddr, CRDisplayString(m, rr));
                                        return(mDNSfalse);
                                        }
                                                q->qname.c, DNSTypeName(q->qtype), &q->Target, srcaddr, CRDisplayString(m, rr));
                                        return(mDNSfalse);
                                        }
@@ -4618,8 +4656,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
                                                                debugf("mDNSCoreReceiveResponse: Reseting to Probing: %##s (%s)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
                                                                rr->resrec.RecordType     = kDNSRecordTypeUnique;
                                                                rr->ProbeCount     = DefaultProbeCountForTypeUnique + 1;
                                                                debugf("mDNSCoreReceiveResponse: Reseting to Probing: %##s (%s)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
                                                                rr->resrec.RecordType     = kDNSRecordTypeUnique;
                                                                rr->ProbeCount     = DefaultProbeCountForTypeUnique + 1;
-                                                               rr->ThisAPInterval = DefaultAPIntervalForRecordType(kDNSRecordTypeUnique);
-                                                               InitializeLastAPTime(m, rr);
+                                                               InitializeLastAPTime(m, rr, DefaultAPIntervalForRecordType(kDNSRecordTypeUnique));
                                                                RecordProbeFailure(m, rr);      // Repeated late conflicts also cause us to back off to the slower probing rate
                                                                }
                                                        // If we're probing for this record, we just failed
                                                                RecordProbeFailure(m, rr);      // Repeated late conflicts also cause us to back off to the slower probing rate
                                                                }
                                                        // If we're probing for this record, we just failed
@@ -4711,6 +4748,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
                                                // out one second into the future. Also, we set UnansweredQueries to MaxUnansweredQueries.
                                                // Otherwise, we'll do final queries for this record at 80% and 90% of its apparent
                                                // lifetime (800ms and 900ms from now) which is a pointless waste of network bandwidth.
                                                // out one second into the future. Also, we set UnansweredQueries to MaxUnansweredQueries.
                                                // Otherwise, we'll do final queries for this record at 80% and 90% of its apparent
                                                // lifetime (800ms and 900ms from now) which is a pointless waste of network bandwidth.
+                                               debugf("DE for %s", CRDisplayString(m, rr));
                                                rr->resrec.rroriginalttl = 1;
                                                rr->UnansweredQueries = MaxUnansweredQueries;
                                                SetNextCacheCheckTime(m, rr);
                                                rr->resrec.rroriginalttl = 1;
                                                rr->UnansweredQueries = MaxUnansweredQueries;
                                                SetNextCacheCheckTime(m, rr);
@@ -4756,58 +4794,76 @@ exit:
                // in one second, thereby inadvertently delaying its actual expiration, instead of hastening it.
                // If this were to happen repeatedly, the record's expiration could be deferred indefinitely.
                // To avoid this, we need to ensure that the cache flushing operation will only act to
                // in one second, thereby inadvertently delaying its actual expiration, instead of hastening it.
                // If this were to happen repeatedly, the record's expiration could be deferred indefinitely.
                // To avoid this, we need to ensure that the cache flushing operation will only act to
-               // *decrease* a record's remaining lifetime, never *increase* it. If a record has less than
-               // one second to go, we simply leave it alone, and leave it to expire at its assigned time.
+               // *decrease* a record's remaining lifetime, never *increase* it.
                for (r2 = cg ? cg->members : mDNSNULL; r2; r2=r2->next)
                        if (r1->resrec.InterfaceID == r2->resrec.InterfaceID &&
                                r1->resrec.rrtype      == r2->resrec.rrtype &&
                                r1->resrec.rrclass     == r2->resrec.rrclass)
                for (r2 = cg ? cg->members : mDNSNULL; r2; r2=r2->next)
                        if (r1->resrec.InterfaceID == r2->resrec.InterfaceID &&
                                r1->resrec.rrtype      == r2->resrec.rrtype &&
                                r1->resrec.rrclass     == r2->resrec.rrclass)
-                               if (RRExpireTime(r2) - m->timenow > mDNSPlatformOneSecond)
+                               {
+                               // If record is recent, just ensure the whole RRSet has the same TTL (as required by DNS semantics)
+                               // else, if record is old, mark it to be flushed
+                               if (m->timenow - r2->TimeRcvd < mDNSPlatformOneSecond && RRExpireTime(r2) - m->timenow > mDNSPlatformOneSecond)
                                        {
                                        {
-                                       // If record is recent, just ensure the whole RRSet has the same TTL (as required by DNS semantics)
-                                       // else, if record is old, mark it to be flushed
-                                       if (m->timenow - r2->TimeRcvd < mDNSPlatformOneSecond)
+                                       // If we find mismatched TTLs in an RRSet, correct them.
+                                       // We only do this for records with a TTL of 2 or higher. It's possible to have a
+                                       // goodbye announcement with the cache flush bit set (or a case change on record rdata,
+                                       // which we treat as a goodbye followed by an addition) and in that case it would be
+                                       // inappropriate to synchronize all the other records to a TTL of 0 (or 1).
+                                       // We suppress the message for the specific case of correcting from 240 to 60 for type TXT,
+                                       // because certain early Bonjour devices are known to have this specific mismatch, and
+                                       // there's no point filling syslog with messages about something we already know about.
+                                       // We also don't log this for uDNS responses, since a caching name server is obliged
+                                       // to give us an aged TTL to correct for how long it has held the record,
+                                       // so our received TTLs are expected to vary in that case
+                                       if (r2->resrec.rroriginalttl != r1->resrec.rroriginalttl && r1->resrec.rroriginalttl > 1)
                                                {
                                                {
-                                               // If we find mismatched TTLs in an RRSet, correct them.
-                                               // We only do this for records with a TTL of 2 or higher. It's possible to have a
-                                               // goodbye announcement with the cache flush bit set (or a case change on record rdata,
-                                               // which we treat as a goodbye followed by an addition) and in that case it would be
-                                               // inappropriate to synchronize all the other records to a TTL of 0 (or 1).
-                                               // We suppress the message for the specific case of correcting from 240 to 60 for type TXT,
-                                               // because certain early Bonjour devices are known to have this specific mismatch, and
-                                               // there's no point filling syslog with messages about something we already know about.
-                                               // We also don't log this for uDNS responses, since a caching name server is obliged
-                                               // to give us an aged TTL to correct for how long it has held the record,
-                                               // so our received TTLs are expected to vary in that case
-                                               if (r2->resrec.rroriginalttl != r1->resrec.rroriginalttl && r1->resrec.rroriginalttl > 1)
-                                                       {
-                                                       if (!(r2->resrec.rroriginalttl == 240 && r1->resrec.rroriginalttl == 60 && r2->resrec.rrtype == kDNSType_TXT) &&
-                                                               mDNSOpaque16IsZero(response->h.id))
-                                                               LogOperation("Correcting TTL from %4d to %4d for %s",
-                                                                       r2->resrec.rroriginalttl, r1->resrec.rroriginalttl, CRDisplayString(m, r2));
-                                                       r2->resrec.rroriginalttl = r1->resrec.rroriginalttl;
-                                                       }
+                                               if (!(r2->resrec.rroriginalttl == 240 && r1->resrec.rroriginalttl == 60 && r2->resrec.rrtype == kDNSType_TXT) &&
+                                                       mDNSOpaque16IsZero(response->h.id))
+                                                       LogOperation("Correcting TTL from %4d to %4d for %s",
+                                                               r2->resrec.rroriginalttl, r1->resrec.rroriginalttl, CRDisplayString(m, r2));
+                                               r2->resrec.rroriginalttl = r1->resrec.rroriginalttl;
+                                               }
+                                       r2->TimeRcvd = m->timenow;
+                                       }
+                               else                            // else, if record is old, mark it to be flushed
+                                       {
+                                       verbosedebugf("Cache flush %p X %p %s", r1, r2, CRDisplayString(m, r2));
+                                       // We set stale records to expire in one second.
+                                       // This gives the owner a chance to rescue it if necessary.
+                                       // This is important in the case of multi-homing and bridged networks:
+                                       //   Suppose host X is on Ethernet. X then connects to an AirPort base station, which happens to be
+                                       //   bridged onto the same Ethernet. When X announces its AirPort IP address with the cache-flush bit
+                                       //   set, the AirPort packet will be bridged onto the Ethernet, and all other hosts on the Ethernet
+                                       //   will promptly delete their cached copies of the (still valid) Ethernet IP address record.
+                                       //   By delaying the deletion by one second, we give X a change to notice that this bridging has
+                                       //   happened, and re-announce its Ethernet IP address to rescue it from deletion from all our caches.
+
+                                       // We set UnansweredQueries to MaxUnansweredQueries to avoid expensive and unnecessary
+                                       // final expiration queries for this record.
+
+                                       // If a record is deleted twice, first with an explicit DE record, then a second time by virtue of the cache
+                                       // flush bit on the new record replacing it, then we allow the record to be deleted immediately, without the usual
+                                       // one-second grace period. This improves responsiveness for mDNS_Update(), as used for things like iChat status updates.
+                                       if (r2->TimeRcvd == m->timenow && r2->resrec.rroriginalttl <= 1 && r2->UnansweredQueries == MaxUnansweredQueries)
+                                               {
+                                               debugf("Cache flush for DE record %s", CRDisplayString(m, r2));
+                                               r2->resrec.rroriginalttl = 0;
+                                               m->NextCacheCheck = m->timenow;
+                                               m->NextScheduledEvent = m->timenow;
                                                }
                                                }
-                                       else                            // else, if record is old, mark it to be flushed
+                                       else if (RRExpireTime(r2) - m->timenow > mDNSPlatformOneSecond)
                                                {
                                                {
-                                               verbosedebugf("Cache flush %p X %p %s", r1, r2, CRDisplayString(m, r2));
-                                               // We set stale records to expire in one second.
-                                               // This gives the owner a chance to rescue it if necessary.
-                                               // This is important in the case of multi-homing and bridged networks:
-                                               //   Suppose host X is on Ethernet. X then connects to an AirPort base station, which happens to be
-                                               //   bridged onto the same Ethernet. When X announces its AirPort IP address with the cache-flush bit
-                                               //   set, the AirPort packet will be bridged onto the Ethernet, and all other hosts on the Ethernet
-                                               //   will promptly delete their cached copies of the (still valid) Ethernet IP address record.
-                                               //   By delaying the deletion by one second, we give X a change to notice that this bridging has
-                                               //   happened, and re-announce its Ethernet IP address to rescue it from deletion from all our caches.
-                                               // We set UnansweredQueries to MaxUnansweredQueries to avoid expensive and unnecessary
-                                               // final expiration queries for this record.
+                                               // We only set a record to expire in one second if it currently has *more* than a second to live
+                                               // If it's already due to expire in a second or less, we just leave it alone
                                                r2->resrec.rroriginalttl = 1;
                                                r2->UnansweredQueries = MaxUnansweredQueries;
                                                r2->resrec.rroriginalttl = 1;
                                                r2->UnansweredQueries = MaxUnansweredQueries;
+                                               r2->TimeRcvd = m->timenow - 1;
+                                               // We use (m->timenow - 1) instead of m->timenow, because we use that to identify records
+                                               // that we marked for deletion via an explicit DE record
                                                }
                                                }
-                                       r2->TimeRcvd = m->timenow;
-                                       SetNextCacheCheckTime(m, r2);
                                        }
                                        }
+                               SetNextCacheCheckTime(m, r2);
+                               }
                if (r1->DelayDelivery)  // If we were planning to delay delivery of this record, see if we still need to
                        {
                        // Note, only need to call SetNextCacheCheckTime() when DelayDelivery is set, not when it's cleared
                if (r1->DelayDelivery)  // If we were planning to delay delivery of this record, see if we still need to
                        {
                        // Note, only need to call SetNextCacheCheckTime() when DelayDelivery is set, not when it's cleared
@@ -4942,6 +4998,11 @@ mDNSexport void MakeNegativeCacheRecord(mDNS *const m, const domainname *const n
        m->rec.r.NextInCFList       = mDNSNULL;
        }
 
        m->rec.r.NextInCFList       = mDNSNULL;
        }
 
+struct UDPSocket_struct
+       {
+       mDNSIPPort port; // MUST BE FIRST FIELD -- mDNSCoreReceive expects every UDPSocket_struct to begin with mDNSIPPort port
+       };
+       
 mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *const end,
        const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport,
        const mDNSInterfaceID InterfaceID)
 mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *const end,
        const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport,
        const mDNSInterfaceID InterfaceID)
@@ -4959,22 +5020,22 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *co
 #ifndef UNICAST_DISABLED
        if (mDNSSameAddress(srcaddr, &m->Router))
                {
 #ifndef UNICAST_DISABLED
        if (mDNSSameAddress(srcaddr, &m->Router))
                {
-               if (mDNSSameIPPort(srcport, NATPMPPort))
+#ifdef _LEGACY_NAT_TRAVERSAL_
+               if (mDNSSameIPPort(srcport, SSDPPort) || (m->SSDPSocket && mDNSSameIPPort(dstport, m->SSDPSocket->port)))
                        {
                        mDNS_Lock(m);
                        {
                        mDNS_Lock(m);
-                       uDNS_ReceiveNATPMPPacket(m, InterfaceID, pkt, (mDNSu16)(end - (mDNSu8 *)pkt));
+                       LNT_ConfigureRouterInfo(m, InterfaceID, pkt, (mDNSu16)(end - (mDNSu8 *)pkt));
                        mDNS_Unlock(m);
                        return;
                        }
                        mDNS_Unlock(m);
                        return;
                        }
-#ifdef _LEGACY_NAT_TRAVERSAL_
-               if (mDNSSameIPPort(srcport, SSDPPort))
+#endif
+               if (mDNSSameIPPort(srcport, NATPMPPort))
                        {
                        mDNS_Lock(m);
                        {
                        mDNS_Lock(m);
-                       LNT_ConfigureRouterInfo(m, InterfaceID, pkt, (mDNSu16)(end - (mDNSu8 *)pkt));
+                       uDNS_ReceiveNATPMPPacket(m, InterfaceID, pkt, (mDNSu16)(end - (mDNSu8 *)pkt));
                        mDNS_Unlock(m);
                        return;
                        }
                        mDNS_Unlock(m);
                        return;
                        }
-#endif
                }
 #endif
        if ((unsigned)(end - (mDNSu8 *)pkt) < sizeof(DNSMessageHeader)) { LogMsg("DNS Message too short"); return; }
                }
 #endif
        if ((unsigned)(end - (mDNSu8 *)pkt) < sizeof(DNSMessageHeader)) { LogMsg("DNS Message too short"); return; }
@@ -5058,8 +5119,7 @@ mDNSlocal DNSQuestion *FindDuplicateQuestion(const mDNS *const m, const DNSQuest
        return(mDNSNULL);
        }
 
        return(mDNSNULL);
        }
 
-// This is called after a question is deleted, in case other identical questions were being
-// suppressed as duplicates
+// This is called after a question is deleted, in case other identical questions were being suppressed as duplicates
 mDNSlocal void UpdateQuestionDuplicates(mDNS *const m, DNSQuestion *const question)
        {
        DNSQuestion *q;
 mDNSlocal void UpdateQuestionDuplicates(mDNS *const m, DNSQuestion *const question)
        {
        DNSQuestion *q;
@@ -5083,7 +5143,7 @@ mDNSlocal void UpdateQuestionDuplicates(mDNS *const m, DNSQuestion *const questi
 
                                q->state             = question->state;
                        //      q->tcp               = question->tcp;
 
                                q->state             = question->state;
                        //      q->tcp               = question->tcp;
-                               q->origLease         = question->origLease;
+                               q->ReqLease          = question->ReqLease;
                                q->expire            = question->expire;
                                q->ntries            = question->ntries;
                                q->id                = question->id;
                                q->expire            = question->expire;
                                q->ntries            = question->ntries;
                                q->id                = question->id;
@@ -5109,7 +5169,7 @@ mDNSlocal void UpdateQuestionDuplicates(mDNS *const m, DNSQuestion *const questi
                                }
        }
 
                                }
        }
 
-// lookup a DNS Server, matching by name in split-dns configurations.  Result stored in addr parameter if successful
+// Look up a DNS Server, matching by name in split-dns configurations.
 mDNSlocal DNSServer *GetServerForName(mDNS *m, const domainname *name)
     {
        DNSServer *curmatch = mDNSNULL, *p;
 mDNSlocal DNSServer *GetServerForName(mDNS *m, const domainname *name)
     {
        DNSServer *curmatch = mDNSNULL, *p;
@@ -5118,7 +5178,7 @@ mDNSlocal DNSServer *GetServerForName(mDNS *m, const domainname *name)
        for (p = m->DNSServers; p; p = p->next)
                {
                int scount = CountLabels(&p->domain);
        for (p = m->DNSServers; p; p = p->next)
                {
                int scount = CountLabels(&p->domain);
-               if (!p->del && ncount >= scount && scount > curmatchlen)
+               if (!(p->flags & DNSServer_FlagDelete) && ncount >= scount && scount > curmatchlen)
                        if (SameDomainName(SkipLeadingLabels(name, ncount - scount), &p->domain))
                                { curmatch = p; curmatchlen = scount; }
                }
                        if (SameDomainName(SkipLeadingLabels(name, ncount - scount), &p->domain))
                                { curmatch = p; curmatchlen = scount; }
                }
@@ -5242,7 +5302,7 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu
                question->NoAnswer          = NoAnswer_Normal;
 
                question->state             = LLQ_InitialRequest;
                question->NoAnswer          = NoAnswer_Normal;
 
                question->state             = LLQ_InitialRequest;
-               question->origLease         = 0;
+               question->ReqLease          = 0;
                question->expire            = 0;
                question->ntries            = 0;
                question->id                = zeroOpaque64;
                question->expire            = 0;
                question->ntries            = 0;
                question->id                = zeroOpaque64;
@@ -5311,13 +5371,13 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que
        const mDNSu32 slot = HashSlot(&question->qname);
        CacheGroup *cg = CacheGroupForName(m, slot, question->qnamehash, &question->qname);
        CacheRecord *rr;
        const mDNSu32 slot = HashSlot(&question->qname);
        CacheGroup *cg = CacheGroupForName(m, slot, question->qnamehash, &question->qname);
        CacheRecord *rr;
-       DNSQuestion **q = &m->Questions;
+       DNSQuestion **qp = &m->Questions;
        
        //LogOperation("mDNS_StopQuery_internal %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
 
        
        //LogOperation("mDNS_StopQuery_internal %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
 
-       if (question->InterfaceID == mDNSInterface_LocalOnly) q = &m->LocalOnlyQuestions;
-       while (*q && *q != question) q=&(*q)->next;
-       if (*q) *q = (*q)->next;
+       if (question->InterfaceID == mDNSInterface_LocalOnly) qp = &m->LocalOnlyQuestions;
+       while (*qp && *qp != question) qp=&(*qp)->next;
+       if (*qp) *qp = (*qp)->next;
        else
                {
 #if !ForceAlerts
        else
                {
 #if !ForceAlerts
@@ -5401,7 +5461,20 @@ mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const que
                        }
 
                // If necessary, tell server it can delete this LLQ state
                        }
 
                // If necessary, tell server it can delete this LLQ state
-               if (question->state == LLQ_Established) sendLLQRefresh(m, question, 0);
+               if (question->state == LLQ_Established)
+                       {
+                       question->ReqLease = 0;
+                       sendLLQRefresh(m, question);
+                       // If we need need to make a TCP connection to cancel the LLQ, that's going to take a little while.
+                       // We clear the tcp->question backpointer so that when the TCP connection completes, it doesn't
+                       // crash trying to access our cancelled question, but we don't cancel the TCP operation itself --
+                       // we let that run out its natural course and complete asynchronously.
+                       if (question->tcp)
+                               {
+                               question->tcp->question = mDNSNULL;
+                               question->tcp           = mDNSNULL;
+                               }
+                       }
                }
 
        return(mStatus_NoError);
                }
 
        return(mStatus_NoError);
@@ -5824,8 +5897,7 @@ mDNSexport mStatus mDNS_Update(mDNS *const m, AuthRecord *const rr, mDNSu32 newt
                // even though there's no actual semantic change, so the mDNSPlatformMemSame() check doesn't help us.
                // To work around this, we simply unilaterally limit all legacy _ichat-type updates to a single announcement.
                if (SameDomainLabel(type.c, (mDNSu8*)"\x6_ichat")) rr->AnnounceCount = 1;
                // even though there's no actual semantic change, so the mDNSPlatformMemSame() check doesn't help us.
                // To work around this, we simply unilaterally limit all legacy _ichat-type updates to a single announcement.
                if (SameDomainLabel(type.c, (mDNSu8*)"\x6_ichat")) rr->AnnounceCount = 1;
-               rr->ThisAPInterval       = DefaultAPIntervalForRecordType(rr->resrec.RecordType);
-               InitializeLastAPTime(m, rr);
+               InitializeLastAPTime(m, rr, DefaultAPIntervalForRecordType(rr->resrec.RecordType));
                while (rr->NextUpdateCredit && m->timenow - rr->NextUpdateCredit >= 0) GrantUpdateCredit(rr);
                if (!rr->UpdateBlocked && rr->UpdateCredits) rr->UpdateCredits--;
                if (!rr->NextUpdateCredit) rr->NextUpdateCredit = NonZeroTime(m->timenow + kUpdateCreditRefreshInterval);
                while (rr->NextUpdateCredit && m->timenow - rr->NextUpdateCredit >= 0) GrantUpdateCredit(rr);
                if (!rr->UpdateBlocked && rr->UpdateCredits) rr->UpdateCredits--;
                if (!rr->NextUpdateCredit) rr->NextUpdateCredit = NonZeroTime(m->timenow + kUpdateCreditRefreshInterval);
@@ -5950,7 +6022,7 @@ mDNSlocal void DeadvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set)
                        intf->RR_A.RRSet = A;
 
        // Unregister these records.
                        intf->RR_A.RRSet = A;
 
        // Unregister these records.
-       // When doing the mDNS_Close processing, we first call DeadvertiseInterface for each interface, so by the time the platform
+       // When doing the mDNS_Exit processing, we first call DeadvertiseInterface for each interface, so by the time the platform
        // support layer gets to call mDNS_DeregisterInterface, the address and PTR records have already been deregistered for it.
        // Also, in the event of a name conflict, one or more of our records will have been forcibly deregistered.
        // To avoid unnecessary and misleading warning messages, we check the RecordType before calling mDNS_Deregister_internal().
        // support layer gets to call mDNS_DeregisterInterface, the address and PTR records have already been deregistered for it.
        // Also, in the event of a name conflict, one or more of our records will have been forcibly deregistered.
        // To avoid unnecessary and misleading warning messages, we check the RecordType before calling mDNS_Deregister_internal().
@@ -6135,7 +6207,7 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s
                                        mDNSBool dodelay = flapping && (q->FlappingInterface1 == set->InterfaceID || q->FlappingInterface2 == set->InterfaceID);
                                        mDNSs32 initial  = dodelay ? InitialQuestionInterval * QuestionIntervalStep2 : InitialQuestionInterval;
                                        mDNSs32 qdelay   = dodelay ? mDNSPlatformOneSecond * 5 : 0;
                                        mDNSBool dodelay = flapping && (q->FlappingInterface1 == set->InterfaceID || q->FlappingInterface2 == set->InterfaceID);
                                        mDNSs32 initial  = dodelay ? InitialQuestionInterval * QuestionIntervalStep2 : InitialQuestionInterval;
                                        mDNSs32 qdelay   = dodelay ? mDNSPlatformOneSecond * 5 : 0;
-                                       if (dodelay) LogOperation("No cache records for expired %##s (%s); okay to delay questions a little", q->qname.c, DNSTypeName(q->qtype));
+                                       if (dodelay) LogOperation("No cache records expired for %##s (%s); okay to delay questions a little", q->qname.c, DNSTypeName(q->qtype));
                                                
                                        if (!q->ThisQInterval || q->ThisQInterval > initial)
                                                {
                                                
                                        if (!q->ThisQInterval || q->ThisQInterval > initial)
                                                {
@@ -6156,8 +6228,7 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s
                                        if (rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->DependentOn) rr->resrec.RecordType = kDNSRecordTypeUnique;
                                        rr->ProbeCount     = DefaultProbeCountForRecordType(rr->resrec.RecordType);
                                        if (rr->AnnounceCount < announce) rr->AnnounceCount  = announce;
                                        if (rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->DependentOn) rr->resrec.RecordType = kDNSRecordTypeUnique;
                                        rr->ProbeCount     = DefaultProbeCountForRecordType(rr->resrec.RecordType);
                                        if (rr->AnnounceCount < announce) rr->AnnounceCount  = announce;
-                                       rr->ThisAPInterval = DefaultAPIntervalForRecordType(rr->resrec.RecordType);
-                                       InitializeLastAPTime(m, rr);
+                                       InitializeLastAPTime(m, rr, DefaultAPIntervalForRecordType(rr->resrec.RecordType));
                                        }
                }
 
                                        }
                }
 
@@ -6293,7 +6364,7 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se
        // In some versions of OS X the IPv6 address remains on an interface even when the interface is turned off,
        // giving the false impression that there's an active representative of this interface when there really isn't.
        // Don't need to do this when shutting down, because *all* interfaces are about to go away
        // In some versions of OS X the IPv6 address remains on an interface even when the interface is turned off,
        // giving the false impression that there's an active representative of this interface when there really isn't.
        // Don't need to do this when shutting down, because *all* interfaces are about to go away
-       if (revalidate && !m->mDNS_shutdown)
+       if (revalidate && !m->ShutdownTime)
                {
                mDNSu32 slot;
                CacheGroup *cg;
                {
                mDNSu32 slot;
                CacheGroup *cg;
@@ -6394,9 +6465,10 @@ mDNSlocal mStatus uDNS_RegisterService(mDNS *const m, ServiceRecordSet *srs)
                return mStatus_NoError;
                }
 
                return mStatus_NoError;
                }
 
+       ActivateUnicastRegistration(m, &srs->RR_SRV);
        srs->state = regState_FetchingZoneData;
        srs->state = regState_FetchingZoneData;
-       srs->nta = StartGetZoneData(m, srs->RR_SRV.resrec.name, ZoneServiceUpdate, ServiceRegistrationGotZoneData, srs);
-       return srs->nta ? mStatus_NoError : mStatus_NoMemoryErr;
+       srs->nta   = mDNSNULL;
+       return mStatus_NoError;
        }
 
 // Note:
        }
 
 // Note:
@@ -6532,7 +6604,7 @@ mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr,
        err = mDNS_Register_internal(m, &sr->RR_SRV);
        if (!err) err = mDNS_Register_internal(m, &sr->RR_TXT);
        // We register the RR_PTR last, because we want to be sure that in the event of a forced call to
        err = mDNS_Register_internal(m, &sr->RR_SRV);
        if (!err) err = mDNS_Register_internal(m, &sr->RR_TXT);
        // We register the RR_PTR last, because we want to be sure that in the event of a forced call to
-       // mDNS_Close, the RR_PTR will be the last one to be forcibly deregistered, since that is what triggers
+       // mDNS_StartExit, the RR_PTR will be the last one to be forcibly deregistered, since that is what triggers
        // the mStatus_MemFree callback to ServiceCallback, which in turn passes on the mStatus_MemFree back to
        // the client callback, which is then at liberty to free the ServiceRecordSet memory at will. We need to
        // make sure we've deregistered all our records and done any other necessary cleanup before that happens.
        // the mStatus_MemFree callback to ServiceCallback, which in turn passes on the mStatus_MemFree back to
        // the client callback, which is then at liberty to free the ServiceRecordSet memory at will. We need to
        // make sure we've deregistered all our records and done any other necessary cleanup before that happens.
@@ -6826,7 +6898,7 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
        // For debugging: To catch and report locking failures
        m->mDNS_busy               = 0;
        m->mDNS_reentrancy         = 0;
        // For debugging: To catch and report locking failures
        m->mDNS_busy               = 0;
        m->mDNS_reentrancy         = 0;
-       m->mDNS_shutdown           = mDNSfalse;
+       m->ShutdownTime            = 0;
        m->lock_rrcache            = 0;
        m->lock_Questions          = 0;
        m->lock_Records            = 0;
        m->lock_rrcache            = 0;
        m->lock_Questions          = 0;
        m->lock_Records            = 0;
@@ -6922,6 +6994,7 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
        m->LastNATReplyLocalTime    = timenow;
 
        m->UPnPInterfaceID          = 0;
        m->LastNATReplyLocalTime    = timenow;
 
        m->UPnPInterfaceID          = 0;
+       m->SSDPSocket               = mDNSNULL;
        m->UPnPRouterPort           = zeroIPPort;
        m->UPnPSOAPPort             = zeroIPPort;
        m->UPnPRouterURL            = mDNSNULL;
        m->UPnPRouterPort           = zeroIPPort;
        m->UPnPSOAPPort             = zeroIPPort;
        m->UPnPRouterURL            = mDNSNULL;
@@ -6971,7 +7044,7 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m)
        // Let the platform layer get the current DNS information
        // The m->RegisterSearchDomains boolean is so that we lazily get the search domain list only on-demand
        // (no need to hit the network with domain enumeration queries until we actually need that information).
        // Let the platform layer get the current DNS information
        // The m->RegisterSearchDomains boolean is so that we lazily get the search domain list only on-demand
        // (no need to hit the network with domain enumeration queries until we actually need that information).
-       for (ptr = m->DNSServers; ptr; ptr = ptr->next) ptr->del = mDNStrue;
+       for (ptr = m->DNSServers; ptr; ptr = ptr->next) ptr->flags |= DNSServer_FlagDelete;
 
        mDNSPlatformSetDNSConfig(m, mDNStrue, mDNSfalse, &fqdn, mDNSNULL, mDNSNULL);
 
 
        mDNSPlatformSetDNSConfig(m, mDNStrue, mDNSfalse, &fqdn, mDNSNULL, mDNSNULL);
 
@@ -6993,15 +7066,28 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m)
                                }
                        }
 
                                }
                        }
 
+       // Flush all records that match a new resolver
+       FORALL_CACHERECORDS(slot, cg, cr)
+               {
+               ptr = GetServerForName(m, cr->resrec.name);
+               if (ptr && (ptr->flags & DNSServer_FlagNew) && !cr->resrec.InterfaceID)
+                       {
+                       if (cr->resrec.RecordType == kDNSRecordTypePacketNegative)
+                               mDNS_PurgeCacheResourceRecord(m, cr);
+                       else
+                               mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
+                       }
+               }
+       
        while (*p)
                {
        while (*p)
                {
-               if ((*p)->del)
+               if (((*p)->flags & DNSServer_FlagDelete) != 0)
                        {
                        // Scan our cache, looking for uDNS records that we would have queried this server for.
                        // We reconfirm any records that match, because in this world of split DNS, firewalls, etc.
                        // different DNS servers can give different answers to the same question.
                        ptr = *p;
                        {
                        // Scan our cache, looking for uDNS records that we would have queried this server for.
                        // We reconfirm any records that match, because in this world of split DNS, firewalls, etc.
                        // different DNS servers can give different answers to the same question.
                        ptr = *p;
-                       ptr->del = mDNSfalse;   // Clear del so GetServerForName will (temporarily) find this server again before it's finally deleted
+                       ptr->flags &= ~DNSServer_FlagDelete;    // Clear del so GetServerForName will (temporarily) find this server again before it's finally deleted
                        FORALL_CACHERECORDS(slot, cg, cr)
                                if (!cr->resrec.InterfaceID && GetServerForName(m, cr->resrec.name) == ptr)
                                        mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
                        FORALL_CACHERECORDS(slot, cg, cr)
                                if (!cr->resrec.InterfaceID && GetServerForName(m, cr->resrec.name) == ptr)
                                        mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
@@ -7009,7 +7095,10 @@ mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m)
                        mDNSPlatformMemFree(ptr);
                        }
                else
                        mDNSPlatformMemFree(ptr);
                        }
                else
+                       {
+                       (*p)->flags &= ~DNSServer_FlagNew;
                        p = &(*p)->next;
                        p = &(*p)->next;
+                       }
                }
 
        // If we now have no DNS servers at all and we used to have some, then immediately purge all unicast cache records (including for LLQs).
                }
 
        // If we now have no DNS servers at all and we used to have some, then immediately purge all unicast cache records (including for LLQs).
@@ -7073,44 +7162,24 @@ mDNSexport void mDNSCoreInitComplete(mDNS *const m, mStatus result)
                }
        }
 
                }
        }
 
-mDNSexport void mDNS_Close(mDNS *const m)
+extern ServiceRecordSet *CurrentServiceRecordSet;
+
+mDNSexport void mDNS_StartExit(mDNS *const m)
        {
        {
-       mDNSu32 rrcache_active = 0;
-       mDNSu32 rrcache_totalused = 0;
-       mDNSu32 slot;
        NetworkInterfaceInfo *intf;
        AuthRecord *rr;
        NetworkInterfaceInfo *intf;
        AuthRecord *rr;
+
        mDNS_Lock(m);
        mDNS_Lock(m);
-       
-       m->mDNS_shutdown = mDNStrue;
+
+       m->ShutdownTime = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 5);
 
 #ifndef UNICAST_DISABLED
        SuspendLLQs(m);
 
 #ifndef UNICAST_DISABLED
        SuspendLLQs(m);
-       SleepServiceRegistrations(m);
+       // Don't need to do SleepRecordRegistrations() or SleepServiceRegistrations() here,
+       // because we deregister all records and services later in this routine
        while (m->Hostnames) mDNS_RemoveDynDNSHostName(m, &m->Hostnames->fqdn);
 #endif
 
        while (m->Hostnames) mDNS_RemoveDynDNSHostName(m, &m->Hostnames->fqdn);
 #endif
 
-       rrcache_totalused = m->rrcache_totalused;
-       for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
-               {
-               while (m->rrcache_hash[slot])
-                       {
-                       CacheGroup *cg = m->rrcache_hash[slot];
-                       while (cg->members)
-                               {
-                               CacheRecord *cr = cg->members;
-                               cg->members = cg->members->next;
-                               if (cr->CRActiveQuestion) rrcache_active++;
-                               ReleaseCacheRecord(m, cr);
-                               }
-                       cg->rrcache_tail = &cg->members;
-                       ReleaseCacheGroup(m, &m->rrcache_hash[slot]);
-                       }
-               }
-       debugf("mDNS_Close: RR Cache was using %ld records, %lu active", rrcache_totalused, rrcache_active);
-       if (rrcache_active != m->rrcache_active)
-               LogMsg("*** ERROR *** rrcache_active %lu != m->rrcache_active %lu", rrcache_active, m->rrcache_active);
-
        for (intf = m->HostInterfaces; intf; intf = intf->next)
                if (intf->Advertise)
                        DeadvertiseInterface(m, intf);
        for (intf = m->HostInterfaces; intf; intf = intf->next)
                if (intf->Advertise)
                        DeadvertiseInterface(m, intf);
@@ -7134,17 +7203,22 @@ mDNSexport void mDNS_Close(mDNS *const m)
 
        // Make sure there are nothing but deregistering records remaining in the list
        if (m->CurrentRecord)
 
        // Make sure there are nothing but deregistering records remaining in the list
        if (m->CurrentRecord)
-               LogMsg("mDNS_Close ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
+               LogMsg("mDNS_StartExit ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
 
        // First we deregister any non-shared records. In particular, we want to make sure we deregister
 
        // First we deregister any non-shared records. In particular, we want to make sure we deregister
-       // any extra records added to a Service Record Set first, before we deregister its PTR record.
+       // any extra records added to a Service Record Set first, before we deregister its PTR record,
+       // because the freeing of the memory is triggered off the mStatus_MemFree for the PTR record.
        m->CurrentRecord = m->ResourceRecords;
        while (m->CurrentRecord)
                {
                rr = m->CurrentRecord;
        m->CurrentRecord = m->ResourceRecords;
        while (m->CurrentRecord)
                {
                rr = m->CurrentRecord;
-               m->CurrentRecord = rr->next;
                if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
                        mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
                if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
                        mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
+               // Note: We mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal, because when
+               // we have records on the DuplicateRecords list, the duplicate gets inserted in place of the record
+               // we're removing, and if we've already advanced to rr->next we'll miss the newly activated duplicate
+               if (m->CurrentRecord == rr)             // If m->CurrentRecord was not auto-advanced, do it ourselves now
+                       m->CurrentRecord = rr->next;
                }
 
        // Now deregister any remaining records we didn't get the first time through
                }
 
        // Now deregister any remaining records we didn't get the first time through
@@ -7152,23 +7226,79 @@ mDNSexport void mDNS_Close(mDNS *const m)
        while (m->CurrentRecord)
                {
                rr = m->CurrentRecord;
        while (m->CurrentRecord)
                {
                rr = m->CurrentRecord;
-               m->CurrentRecord = rr->next;
                if (rr->resrec.RecordType != kDNSRecordTypeDeregistering)
                if (rr->resrec.RecordType != kDNSRecordTypeDeregistering)
+                       {
+                       //LogOperation("mDNS_StartExit: Deregistering %s", ARDisplayString(m, rr));
                        mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
                        mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
+                       }
+               // Note: We mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal, because when
+               // we have records on the DuplicateRecords list, the duplicate gets inserted in place of the record
+               // we're removing, and if we've already advanced to rr->next we'll miss the newly activated duplicate
+               if (m->CurrentRecord == rr)             // If m->CurrentRecord was not auto-advanced, do it ourselves now
+                       m->CurrentRecord = rr->next;
+               }
+
+       CurrentServiceRecordSet = m->ServiceRegistrations;
+       while (CurrentServiceRecordSet)
+               {
+               ServiceRecordSet *srs = CurrentServiceRecordSet;
+               LogOperation("mDNS_StartExit: Deregistering %##s", srs->RR_SRV.resrec.name->c);
+               uDNS_DeregisterService(m, srs);
+               if (CurrentServiceRecordSet == srs)
+                       CurrentServiceRecordSet = srs->uDNS_next;
                }
 
                }
 
-       if (m->ResourceRecords) LogOperation("mDNS_Close: Sending final packets for deregistering records");
-       else                    LogOperation("mDNS_Close: No deregistering records remain");
+       if (m->ResourceRecords) LogOperation("mDNS_StartExit: Sending final record deregistrations");
+       else                    LogOperation("mDNS_StartExit: No deregistering records remain");
+
+       if (m->ServiceRegistrations) LogOperation("mDNS_StartExit: Sending final service deregistrations");
+       else                         LogOperation("mDNS_StartExit: No deregistering services remain");
 
        // If any deregistering records remain, send their deregistration announcements before we exit
        if (m->mDNSPlatformStatus != mStatus_NoError) DiscardDeregistrations(m);
 
        // If any deregistering records remain, send their deregistration announcements before we exit
        if (m->mDNSPlatformStatus != mStatus_NoError) DiscardDeregistrations(m);
-       else if (m->ResourceRecords) SendResponses(m);
 
 
-       for (rr = m->ResourceRecords; rr; rr = rr->next)
-               LogMsg("mDNS_Close failed to send goodbye for: %s", ARDisplayString(m, rr));
-       
        mDNS_Unlock(m);
        mDNS_Unlock(m);
-       debugf("mDNS_Close: mDNSPlatformClose");
+
+       LogOperation("mDNS_StartExit: done");
+       }
+
+mDNSexport void mDNS_FinalExit(mDNS *const m)
+       {
+       mDNSu32 rrcache_active = 0;
+       mDNSu32 rrcache_totalused = 0;
+       mDNSu32 slot;
+       AuthRecord *rr;
+       ServiceRecordSet *srs;
+
+       LogOperation("mDNS_FinalExit: mDNSPlatformClose");
        mDNSPlatformClose(m);
        mDNSPlatformClose(m);
-       debugf("mDNS_Close: done");
+
+       rrcache_totalused = m->rrcache_totalused;
+       for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
+               {
+               while (m->rrcache_hash[slot])
+                       {
+                       CacheGroup *cg = m->rrcache_hash[slot];
+                       while (cg->members)
+                               {
+                               CacheRecord *cr = cg->members;
+                               cg->members = cg->members->next;
+                               if (cr->CRActiveQuestion) rrcache_active++;
+                               ReleaseCacheRecord(m, cr);
+                               }
+                       cg->rrcache_tail = &cg->members;
+                       ReleaseCacheGroup(m, &m->rrcache_hash[slot]);
+                       }
+               }
+       debugf("mDNS_StartExit: RR Cache was using %ld records, %lu active", rrcache_totalused, rrcache_active);
+       if (rrcache_active != m->rrcache_active)
+               LogMsg("*** ERROR *** rrcache_active %lu != m->rrcache_active %lu", rrcache_active, m->rrcache_active);
+
+       for (rr = m->ResourceRecords; rr; rr = rr->next)
+               LogMsg("mDNS_FinalExit failed to send goodbye for: %02X %s", rr->resrec.RecordType, ARDisplayString(m, rr));
+
+       for (srs = m->ServiceRegistrations; srs; srs = srs->uDNS_next)
+               LogMsg("mDNS_FinalExit failed to deregister service: %##s", srs->RR_SRV.resrec.name->c);
+
+       LogOperation("mDNS_FinalExit: done");
        }
        }
index e5ad7d088cd56ed218646a083b57b231c4ec490f..81bcedbc84c7b9f33d83eef104e56fd609b3d50c 100755 (executable)
     Change History (most recent first):
 
 $Log: mDNSDebug.h,v $
     Change History (most recent first):
 
 $Log: mDNSDebug.h,v $
+Revision 1.38  2007/12/13 20:27:07  cheshire
+Remove unused VerifySameNameAssumptions symbol
+
+Revision 1.37  2007/12/01 00:33:17  cheshire
+Fixes from Bob Bradley for building on EFI
+
 Revision 1.36  2007/10/01 19:06:19  cheshire
 Defined symbolic constant MDNS_LOG_INITIAL_LEVEL to set the logging level we start out at
 
 Revision 1.36  2007/10/01 19:06:19  cheshire
 Defined symbolic constant MDNS_LOG_INITIAL_LEVEL to set the logging level we start out at
 
@@ -140,14 +146,39 @@ Merge in license terms from Quinn's copy, in preparation for Darwin release
        extern "C" {
 #endif
 
        extern "C" {
 #endif
 
+// Variable argument macro support. Use ANSI C99 __VA_ARGS__ where possible. Otherwise, use the next best thing.
+
+#if (defined(__GNUC__))
+       #if ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 2)))
+               #define MDNS_C99_VA_ARGS                1
+               #define MDNS_GNU_VA_ARGS                0
+       #else
+               #define MDNS_C99_VA_ARGS                0
+               #define MDNS_GNU_VA_ARGS                1
+       #endif
+       #define MDNS_HAS_VA_ARG_MACROS          1
+#elif (_MSC_VER >= 1400) // Visual Studio 2005 and later
+       #define MDNS_C99_VA_ARGS                        1
+       #define MDNS_GNU_VA_ARGS                        0
+       #define MDNS_HAS_VA_ARG_MACROS          1
+#elif (defined(__MWERKS__))
+       #define MDNS_C99_VA_ARGS                        1
+       #define MDNS_GNU_VA_ARGS                        0
+       #define MDNS_HAS_VA_ARG_MACROS          1
+#else
+       #define MDNS_C99_VA_ARGS                        0
+       #define MDNS_GNU_VA_ARGS                        0
+       #define MDNS_HAS_VA_ARG_MACROS          0
+#endif
+
 #if MDNS_DEBUGMSGS
 #define debugf debugf_
 extern void debugf_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
 #else // If debug breaks are off, use a preprocessor trick to optimize those calls out of the code
 #if MDNS_DEBUGMSGS
 #define debugf debugf_
 extern void debugf_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
 #else // If debug breaks are off, use a preprocessor trick to optimize those calls out of the code
-       #if (defined(__GNUC__))
+       #if (MDNS_C99_VA_ARGS)
+               #define debugf( ... ) ((void)0)
+       #elif (MDNS_GNU_VA_ARGS)
                #define debugf( ARGS... ) ((void)0)
                #define debugf( ARGS... ) ((void)0)
-       #elif (defined(__MWERKS__))
-               #define debugf( ... )
        #else
                #define debugf 1 ? ((void)0) : (void)
        #endif
        #else
                #define debugf 1 ? ((void)0) : (void)
        #endif
@@ -157,10 +188,10 @@ extern void debugf_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
 #define verbosedebugf verbosedebugf_
 extern void verbosedebugf_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
 #else
 #define verbosedebugf verbosedebugf_
 extern void verbosedebugf_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
 #else
-       #if (defined(__GNUC__))
+       #if (MDNS_C99_VA_ARGS)
+               #define verbosedebugf( ... ) ((void)0)
+       #elif (MDNS_GNU_VA_ARGS)
                #define verbosedebugf( ARGS... ) ((void)0)
                #define verbosedebugf( ARGS... ) ((void)0)
-       #elif (defined(__MWERKS__))
-               #define verbosedebugf( ... )
        #else
                #define verbosedebugf 1 ? ((void)0) : (void)
        #endif
        #else
                #define verbosedebugf 1 ? ((void)0) : (void)
        #endif
@@ -216,8 +247,6 @@ extern void udns_validatelists(void *const v);
 
 #define ForceAlerts 0
 
 
 #define ForceAlerts 0
 
-#define VerifySameNameAssumptions 0
-
 #ifdef __cplusplus
        }
 #endif
 #ifdef __cplusplus
        }
 #endif
index 8673da9c4f58da4657dee7358c1f42c4f922ef84..a67e1f37bfe182444630f55dc33388bd2bb92310 100755 (executable)
     Change History (most recent first):
 
 $Log: mDNSEmbeddedAPI.h,v $
     Change History (most recent first):
 
 $Log: mDNSEmbeddedAPI.h,v $
+Revision 1.463  2007/12/17 23:53:25  cheshire
+Added DNSDigest_SignMessageHostByteOrder, for signing messages not yet converted to network byte order
+
+Revision 1.462  2007/12/17 23:48:29  cheshire
+DNSDigest_SignMessage doesn't need to return a result -- it already updates the 'end' parameter
+
+Revision 1.461  2007/12/15 00:18:51  cheshire
+Renamed question->origLease to question->ReqLease
+
+Revision 1.460  2007/12/14 23:55:28  cheshire
+Moved "struct tcpInfo_t" definition from uDNS.c to mDNSEmbeddedAPI.h
+
+Revision 1.459  2007/12/07 22:40:34  cheshire
+Rename 'LocalAnswer' to more descriptive 'AnsweredLocalQ'
+
+Revision 1.458  2007/12/07 00:45:58  cheshire
+<rdar://problem/5526800> BTMM: Need to clean up registrations on shutdown
+
+Revision 1.457  2007/12/06 00:22:27  mcguire
+<rdar://problem/5604567> BTMM: Doesn't work with Linksys WAG300N 1.01.06 (sending from 1026/udp)
+
+Revision 1.456  2007/12/05 01:45:35  cheshire
+Renamed markedForDeletion -> MarkedForDeletion
+
+Revision 1.455  2007/12/01 01:21:27  jgraessley
+<rdar://problem/5623140> mDNSResponder unicast DNS improvements
+
+Revision 1.454  2007/12/01 00:34:03  cheshire
+Fixes from Bob Bradley for building on EFI
+
 Revision 1.453  2007/10/29 23:51:22  cheshire
 Added comment about NATTraversalInfo ExternalAddress field
 
 Revision 1.453  2007/10/29 23:51:22  cheshire
 Added comment about NATTraversalInfo ExternalAddress field
 
@@ -605,13 +635,15 @@ Fixes to avoid code generation warning/error on FreeBSD 7
 #ifndef __mDNSClientAPI_h
 #define __mDNSClientAPI_h
 
 #ifndef __mDNSClientAPI_h
 #define __mDNSClientAPI_h
 
-#if defined(EFI32) || defined(EFI64)
-// EFI doesn't have stdarg.h
+#if defined(EFI32) || defined(EFI64) || defined(EFIX64)
+// EFI doesn't have stdarg.h unless it's building with GCC.
 #include "Tiano.h"
 #include "Tiano.h"
+#if !defined(__GNUC__)
 #define va_list         VA_LIST
 #define va_start(a, b)  VA_START(a, b)
 #define va_end(a)       VA_END(a)
 #define va_arg(a, b)    VA_ARG(a, b)
 #define va_list         VA_LIST
 #define va_start(a, b)  VA_START(a, b)
 #define va_end(a)       VA_END(a)
 #define va_arg(a, b)    VA_ARG(a, b)
+#endif
 #else
 #include <stdarg.h>            // stdarg.h is required for for va_list support for the mDNS_vsnprintf declaration
 #endif
 #else
 #include <stdarg.h>            // stdarg.h is required for for va_list support for the mDNS_vsnprintf declaration
 #endif
@@ -921,6 +953,21 @@ typedef struct { mDNSu8 c[256]; } UTF8str255;              // Null-terminated C string
 
 #define DefaultTTLforRRType(X) (((X) == kDNSType_A || (X) == kDNSType_AAAA || (X) == kDNSType_SRV) ? kHostNameTTL : kStandardTTL)
 
 
 #define DefaultTTLforRRType(X) (((X) == kDNSType_A || (X) == kDNSType_AAAA || (X) == kDNSType_SRV) ? kHostNameTTL : kStandardTTL)
 
+typedef struct AuthRecord_struct AuthRecord;
+typedef struct ServiceRecordSet_struct ServiceRecordSet;
+typedef struct CacheRecord_struct CacheRecord;
+typedef struct CacheGroup_struct CacheGroup;
+typedef struct DNSQuestion_struct DNSQuestion;
+typedef struct ZoneData_struct ZoneData;
+typedef struct mDNS_struct mDNS;
+typedef struct mDNS_PlatformSupport_struct mDNS_PlatformSupport;
+typedef struct NATTraversalInfo_struct NATTraversalInfo;
+
+// Structure to abstract away the differences between TCP/SSL sockets, and one for UDP sockets
+// The actual definition of these structures in the in the appropriate platform support code
+typedef struct TCPSocket_struct TCPSocket;
+typedef struct UDPSocket_struct UDPSocket;
+
 // ***************************************************************************
 #if 0
 #pragma mark - DNS Message structures
 // ***************************************************************************
 #if 0
 #pragma mark - DNS Message structures
@@ -951,6 +998,23 @@ typedef packedstruct
        mDNSu8 data[AbsoluteMaxDNSMessageData]; // 40 (IPv6) + 8 (UDP) + 12 (DNS header) + 8940 (data) = 9000
        } DNSMessage;
 
        mDNSu8 data[AbsoluteMaxDNSMessageData]; // 40 (IPv6) + 8 (UDP) + 12 (DNS header) + 8940 (data) = 9000
        } DNSMessage;
 
+typedef struct tcpInfo_t
+       {
+       mDNS             *m;
+       TCPSocket        *sock;
+       DNSMessage        request;
+       int               requestLen;
+       DNSQuestion      *question;   // For queries
+       ServiceRecordSet *srs;        // For service record updates
+       AuthRecord       *rr;         // For record updates
+       mDNSAddr          Addr;
+       mDNSIPPort        Port;
+       DNSMessage       *reply;
+       mDNSu16           replylen;
+       unsigned long     nread;
+       int               numReplies;
+       } tcpInfo_t;
+
 // ***************************************************************************
 #if 0
 #pragma mark - Resource Record structures
 // ***************************************************************************
 #if 0
 #pragma mark - Resource Record structures
@@ -1120,16 +1184,7 @@ typedef struct
        } RData;
 #define sizeofRDataHeader (sizeof(RData) - sizeof(RDataBody))
 
        } RData;
 #define sizeofRDataHeader (sizeof(RData) - sizeof(RDataBody))
 
-typedef struct AuthRecord_struct AuthRecord;
-typedef struct CacheRecord_struct CacheRecord;
-typedef struct CacheGroup_struct CacheGroup;
-typedef struct DNSQuestion_struct DNSQuestion;
-typedef struct ZoneData_struct ZoneData;
-typedef struct mDNS_struct mDNS;
-typedef struct mDNS_PlatformSupport_struct mDNS_PlatformSupport;
-typedef struct NATTraversalInfo_struct NATTraversalInfo;
-
-// Note: Within an mDNSRecordCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Close(), mDNS_Execute()
+// Note: Within an mDNSRecordCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
 typedef void mDNSRecordCallback(mDNS *const m, AuthRecord *const rr, mStatus result);
 
 // Note:
 typedef void mDNSRecordCallback(mDNS *const m, AuthRecord *const rr, mStatus result);
 
 // Note:
@@ -1149,11 +1204,6 @@ typedef void mDNSRecordUpdateCallback(mDNS *const m, AuthRecord *const rr, RData
 #define NATMAP_DEFAULT_LEASE (60 * 60)                             // lease life in seconds
 #define NATMAP_VERS 0
 
 #define NATMAP_DEFAULT_LEASE (60 * 60)                             // lease life in seconds
 #define NATMAP_VERS 0
 
-// Structure to abstract away the differences between TCP/SSL sockets, and one for UDP sockets
-// The actual definition of these structures in the in the appropriate platform support code
-typedef struct TCPSocket_struct TCPSocket;
-typedef struct UDPSocket_struct UDPSocket;
-
 typedef enum
        {
        NATOp_AddrRequest    = 0,
 typedef enum
        {
        NATOp_AddrRequest    = 0,
@@ -1361,7 +1411,7 @@ struct AuthRecord_struct
        mDNSu8          ProbeCount;                     // Number of probes remaining before this record is valid (kDNSRecordTypeUnique)
        mDNSu8          AnnounceCount;          // Number of announcements remaining (kDNSRecordTypeShared)
        mDNSu8          RequireGoodbye;         // Set if this RR has been announced on the wire and will require a goodbye packet
        mDNSu8          ProbeCount;                     // Number of probes remaining before this record is valid (kDNSRecordTypeUnique)
        mDNSu8          AnnounceCount;          // Number of announcements remaining (kDNSRecordTypeShared)
        mDNSu8          RequireGoodbye;         // Set if this RR has been announced on the wire and will require a goodbye packet
-       mDNSu8          LocalAnswer;            // Set if this RR has been delivered to LocalOnly questions
+       mDNSu8          AnsweredLocalQ;         // Set if this RR has been delivered to LocalOnly questions
        mDNSu8          IncludeInProbe;         // Set if this RR is being put into a probe right now
        mDNSInterfaceID ImmedAnswer;            // Someone on this interface issued a query we need to answer (all-ones for all interfaces)
        mDNSu8          ImmedUnicast;           // Set if we may send our response directly via unicast to the requester
        mDNSu8          IncludeInProbe;         // Set if this RR is being put into a probe right now
        mDNSInterfaceID ImmedAnswer;            // Someone on this interface issued a query we need to answer (all-ones for all interfaces)
        mDNSu8          ImmedUnicast;           // Set if we may send our response directly via unicast to the requester
@@ -1427,7 +1477,7 @@ struct AuthRecord_struct
 typedef struct ARListElem
        {
        struct ARListElem *next;
 typedef struct ARListElem
        {
        struct ARListElem *next;
-       AuthRecord ar;          // Note: Must be last struct in field to accomodate oversized AuthRecords
+       AuthRecord ar;          // Note: Must be last element of structure, to accomodate oversized AuthRecords
        } ARListElem;
 
 struct CacheGroup_struct                               // Header object for a list of CacheRecords with the same name
        } ARListElem;
 
 struct CacheGroup_struct                               // Header object for a list of CacheRecords with the same name
@@ -1493,13 +1543,19 @@ enum
        DNSServer_Disabled = 3
        };
 
        DNSServer_Disabled = 3
        };
 
+enum
+       {
+       DNSServer_FlagDelete = 1,
+       DNSServer_FlagNew    = 2
+       };
+
 typedef struct DNSServer
        {
        struct DNSServer *next;
        mDNSInterfaceID interface;      // For specialized uses; we can have DNS servers reachable over specific interfaces
        mDNSAddr        addr;
        mDNSIPPort      port;
 typedef struct DNSServer
        {
        struct DNSServer *next;
        mDNSInterfaceID interface;      // For specialized uses; we can have DNS servers reachable over specific interfaces
        mDNSAddr        addr;
        mDNSIPPort      port;
-       mDNSBool        del;            // Set when we're planning to delete this from the list
+       mDNSu32         flags;          // Set when we're planning to delete this from the list
        mDNSu32         teststate;      // Have we sent bug-detection query to this server?
        mDNSs32         lasttest;       // Time we sent last bug-detection query to this server
        domainname      domain;         // name->server matching for "split dns"
        mDNSu32         teststate;      // Have we sent bug-detection query to this server?
        mDNSs32         lasttest;       // Time we sent last bug-detection query to this server
        domainname      domain;         // name->server matching for "split dns"
@@ -1550,8 +1606,7 @@ struct ExtraResourceRecord_struct
        // that this extra memory is available, which would result in any fields after the AuthRecord getting smashed
        };
 
        // that this extra memory is available, which would result in any fields after the AuthRecord getting smashed
        };
 
-// Note: Within an mDNSServiceCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Close(), mDNS_Execute()
-typedef struct ServiceRecordSet_struct ServiceRecordSet;
+// Note: Within an mDNSServiceCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
 typedef void mDNSServiceCallback(mDNS *const m, ServiceRecordSet *const sr, mStatus result);
 
 // A ServiceRecordSet is basically a convenience structure to group together
 typedef void mDNSServiceCallback(mDNS *const m, ServiceRecordSet *const sr, mStatus result);
 
 // A ServiceRecordSet is basically a convenience structure to group together
@@ -1695,7 +1750,7 @@ typedef struct DomainAuthInfo
        mDNSu8           keydata_opad[HMAC_LEN];        // padded key for outer hash rounds
        } DomainAuthInfo;
 
        mDNSu8           keydata_opad[HMAC_LEN];        // padded key for outer hash rounds
        } DomainAuthInfo;
 
-// Note: Within an mDNSQuestionCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Close(), mDNS_Execute()
+// Note: Within an mDNSQuestionCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
 typedef enum { QC_rmv = 0, QC_add = 1, QC_addnocache = 2 } QC_result;
 typedef void mDNSQuestionCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord);
 struct DNSQuestion_struct
 typedef enum { QC_rmv = 0, QC_add = 1, QC_addnocache = 2 } QC_result;
 typedef void mDNSQuestionCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord);
 struct DNSQuestion_struct
@@ -1738,7 +1793,7 @@ struct DNSQuestion_struct
 
        // LLQ-specific fields. These fields are only meaningful when LongLived flag is set
        LLQ_State             state;
 
        // LLQ-specific fields. These fields are only meaningful when LongLived flag is set
        LLQ_State             state;
-       mDNSu32               origLease;                // seconds (relative)
+       mDNSu32               ReqLease;         // seconds (relative)
        mDNSs32               expire;                   // ticks (absolute)
        mDNSs16               ntries;
        mDNSOpaque64          id;
        mDNSs32               expire;                   // ticks (absolute)
        mDNSs16               ntries;
        mDNSOpaque64          id;
@@ -1771,7 +1826,7 @@ typedef struct
        mDNSu8          TXTinfo[2048];          // Additional demultiplexing information (e.g. LPR queue name)
        } ServiceInfo;
 
        mDNSu8          TXTinfo[2048];          // Additional demultiplexing information (e.g. LPR queue name)
        } ServiceInfo;
 
-// Note: Within an mDNSServiceInfoQueryCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Close(), mDNS_Execute()
+// Note: Within an mDNSServiceInfoQueryCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
 typedef struct ServiceInfoQuery_struct ServiceInfoQuery;
 typedef void mDNSServiceInfoQueryCallback(mDNS *const m, ServiceInfoQuery *query);
 struct ServiceInfoQuery_struct
 typedef struct ServiceInfoQuery_struct ServiceInfoQuery;
 typedef void mDNSServiceInfoQueryCallback(mDNS *const m, ServiceInfoQuery *query);
 struct ServiceInfoQuery_struct
@@ -1830,7 +1885,7 @@ typedef struct ClientTunnel
        {
        struct ClientTunnel *next;
        domainname dstname;
        {
        struct ClientTunnel *next;
        domainname dstname;
-       mDNSBool   markedForDeletion;
+       mDNSBool   MarkedForDeletion;
        mDNSv6Addr loc_inner;
        mDNSv4Addr loc_outer;
        mDNSv6Addr rmt_inner;
        mDNSv6Addr loc_inner;
        mDNSv4Addr loc_outer;
        mDNSv6Addr rmt_inner;
@@ -1875,7 +1930,6 @@ struct mDNS_struct
        // For debugging: To catch and report locking failures
        mDNSu32 mDNS_busy;                                      // Incremented between mDNS_Lock/mDNS_Unlock section
        mDNSu32 mDNS_reentrancy;                        // Incremented when calling a client callback
        // For debugging: To catch and report locking failures
        mDNSu32 mDNS_busy;                                      // Incremented between mDNS_Lock/mDNS_Unlock section
        mDNSu32 mDNS_reentrancy;                        // Incremented when calling a client callback
-       mDNSu8  mDNS_shutdown;                          // Set when we're shutting down, allows us to skip some unnecessary steps
        mDNSu8  lock_rrcache;                           // For debugging: Set at times when these lists may not be modified
        mDNSu8  lock_Questions;
        mDNSu8  lock_Records;
        mDNSu8  lock_rrcache;                           // For debugging: Set at times when these lists may not be modified
        mDNSu8  lock_Questions;
        mDNSu8  lock_Records;
@@ -1887,6 +1941,7 @@ struct mDNS_struct
        mDNSs32  timenow;                                       // The time that this particular activation of the mDNS code started
        mDNSs32  timenow_last;                          // The time the last time we ran
        mDNSs32  NextScheduledEvent;            // Derived from values below
        mDNSs32  timenow;                                       // The time that this particular activation of the mDNS code started
        mDNSs32  timenow_last;                          // The time the last time we ran
        mDNSs32  NextScheduledEvent;            // Derived from values below
+       mDNSs32  ShutdownTime;                          // Set when we're shutting down, allows us to skip some unnecessary steps
        mDNSs32  SuppressSending;                       // Don't send *any* packets during this time
        mDNSs32  NextCacheCheck;                        // Next time to refresh cache record before it expires
        mDNSs32  NextScheduledQuery;            // Next time to send query in its exponential backoff sequence
        mDNSs32  SuppressSending;                       // Don't send *any* packets during this time
        mDNSs32  NextCacheCheck;                        // Next time to refresh cache record before it expires
        mDNSs32  NextScheduledQuery;            // Next time to send query in its exponential backoff sequence
@@ -1972,6 +2027,7 @@ struct mDNS_struct
        tcpLNTInfo        tcpDeviceInfo;                        // legacy NAT traversal TCP connection info for device info
        tcpLNTInfo       *tcpInfoUnmapList;                     // list of pending unmap requests
        mDNSInterfaceID   UPnPInterfaceID;
        tcpLNTInfo        tcpDeviceInfo;                        // legacy NAT traversal TCP connection info for device info
        tcpLNTInfo       *tcpInfoUnmapList;                     // list of pending unmap requests
        mDNSInterfaceID   UPnPInterfaceID;
+       UDPSocket        *SSDPSocket;               // For SSDP request/response
        mDNSIPPort        UPnPRouterPort;                       // port we send discovery messages to
        mDNSIPPort        UPnPSOAPPort;                         // port we send SOAP messages to
        mDNSu8           *UPnPRouterURL;                        // router's URL string
        mDNSIPPort        UPnPRouterPort;                       // port we send discovery messages to
        mDNSIPPort        UPnPSOAPPort;                         // port we send SOAP messages to
        mDNSu8           *UPnPRouterURL;                        // router's URL string
@@ -2109,7 +2165,9 @@ mDNSinline mDNSOpaque16 mDNSOpaque16fromIntVal(mDNSu16 v)
 // When mDNS has finished setting up the client's callback is called
 // A client can also spin and poll the mDNSPlatformStatus field to see when it changes from mStatus_Waiting to mStatus_NoError
 //
 // When mDNS has finished setting up the client's callback is called
 // A client can also spin and poll the mDNSPlatformStatus field to see when it changes from mStatus_Waiting to mStatus_NoError
 //
-// Call mDNS_Close to tidy up before exiting
+// Call mDNS_StartExit to tidy up before exiting
+// Because exiting may be an asynchronous process (e.g. if unicast records need to be deregistered)
+// client layer may choose to wait until mDNS_ExitNow() returns true before calling mDNS_FinalExit().
 //
 // Call mDNS_Register with a completed AuthRecord object to register a resource record
 // If the resource record type is kDNSRecordTypeUnique (or kDNSknownunique) then if a conflicting resource record is discovered,
 //
 // Call mDNS_Register with a completed AuthRecord object to register a resource record
 // If the resource record type is kDNSRecordTypeUnique (or kDNSknownunique) then if a conflicting resource record is discovered,
@@ -2143,7 +2201,11 @@ extern mStatus mDNS_Init      (mDNS *const m, mDNS_PlatformSupport *const p,
 #define mDNS_Init_NoInitCallbackContext       mDNSNULL
 
 extern void    mDNS_GrowCache (mDNS *const m, CacheEntity *storage, mDNSu32 numrecords);
 #define mDNS_Init_NoInitCallbackContext       mDNSNULL
 
 extern void    mDNS_GrowCache (mDNS *const m, CacheEntity *storage, mDNSu32 numrecords);
-extern void    mDNS_Close     (mDNS *const m);
+extern void    mDNS_StartExit (mDNS *const m);
+extern void    mDNS_FinalExit (mDNS *const m);
+#define mDNS_Close(m) do { mDNS_StartExit(m); mDNS_FinalExit(m); } while(0)
+#define mDNS_ExitNow(m, now) ((now) - (m)->ShutdownTime >= 0 || (!(m)->ResourceRecords && !(m)->ServiceRegistrations))
+
 extern mDNSs32 mDNS_Execute   (mDNS *const m);
 
 extern mStatus mDNS_Register  (mDNS *const m, AuthRecord *const rr);
 extern mDNSs32 mDNS_Execute   (mDNS *const m);
 
 extern mStatus mDNS_Register  (mDNS *const m, AuthRecord *const rr);
@@ -2261,8 +2323,8 @@ extern mDNSOpaque16 mDNS_NewMessageID(mDNS *const m);
 // A simple C structure assignment of a domainname can cause a protection fault by accessing unmapped memory,
 // because that object is defined to be 256 bytes long, but not all domainname objects are truly the full size.
 // This macro uses mDNSPlatformMemCopy() to make sure it only touches the actual bytes that are valid.
 // A simple C structure assignment of a domainname can cause a protection fault by accessing unmapped memory,
 // because that object is defined to be 256 bytes long, but not all domainname objects are truly the full size.
 // This macro uses mDNSPlatformMemCopy() to make sure it only touches the actual bytes that are valid.
-#define AssignDomainName(DST, SRC) do { mDNSu16 len = DomainNameLength((SRC)); \
-       if (len <= MAX_DOMAIN_NAME) mDNSPlatformMemCopy((DST)->c, (SRC)->c, len); else (DST)->c[0] = 0; } while(0)
+#define AssignDomainName(DST, SRC) do { mDNSu16 len__ = DomainNameLength((SRC)); \
+       if (len__ <= MAX_DOMAIN_NAME) mDNSPlatformMemCopy((DST)->c, (SRC)->c, len__); else (DST)->c[0] = 0; } while(0)
 
 // Comparison functions
 #define SameDomainLabelCS(A,B) ((A)[0] == (B)[0] && mDNSPlatformMemSame((A)+1, (B)+1, (A)[0]))
 
 // Comparison functions
 #define SameDomainLabelCS(A,B) ((A)[0] == (B)[0] && mDNSPlatformMemSame((A)+1, (B)+1, (A)[0]))
@@ -2432,7 +2494,7 @@ extern DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mD
 extern void mDNS_AddSearchDomain(const domainname *const domain);
 
 #define mDNS_AddSearchDomain_CString(X) \
 extern void mDNS_AddSearchDomain(const domainname *const domain);
 
 #define mDNS_AddSearchDomain_CString(X) \
-       do { domainname d; if ((X) && MakeDomainNameFromDNSNameString(&d, (X)) && d.c[0]) mDNS_AddSearchDomain(&d); } while(0)
+       do { domainname d__; if ((X) && MakeDomainNameFromDNSNameString(&d__, (X)) && d__.c[0]) mDNS_AddSearchDomain(&d__); } while(0)
 
 // Routines called by the core, exported by DNSDigest.c
 
 
 // Routines called by the core, exported by DNSDigest.c
 
@@ -2443,7 +2505,17 @@ extern mDNSs32 DNSDigest_ConstructHMACKeyfromBase64(DomainAuthInfo *info, const
 // of the message, and is modified by this routine.  numAdditionals is a pointer to the number of additional
 // records in HOST byte order, which is incremented upon successful completion of this routine.  The function returns
 // the new end pointer on success, and NULL on failure.
 // of the message, and is modified by this routine.  numAdditionals is a pointer to the number of additional
 // records in HOST byte order, which is incremented upon successful completion of this routine.  The function returns
 // the new end pointer on success, and NULL on failure.
-extern mDNSu8 *DNSDigest_SignMessage(DNSMessage *msg, mDNSu8 **end, DomainAuthInfo *info, mDNSu16 tcode);
+extern void DNSDigest_SignMessage(DNSMessage *msg, mDNSu8 **end, DomainAuthInfo *info, mDNSu16 tcode);
+
+#define SwapDNSHeaderBytes(M) do { \
+    (M)->h.numQuestions   = (mDNSu16)((mDNSu8 *)&(M)->h.numQuestions  )[0] << 8 | ((mDNSu8 *)&(M)->h.numQuestions  )[1]; \
+    (M)->h.numAnswers     = (mDNSu16)((mDNSu8 *)&(M)->h.numAnswers    )[0] << 8 | ((mDNSu8 *)&(M)->h.numAnswers    )[1]; \
+    (M)->h.numAuthorities = (mDNSu16)((mDNSu8 *)&(M)->h.numAuthorities)[0] << 8 | ((mDNSu8 *)&(M)->h.numAuthorities)[1]; \
+    (M)->h.numAdditionals = (mDNSu16)((mDNSu8 *)&(M)->h.numAdditionals)[0] << 8 | ((mDNSu8 *)&(M)->h.numAdditionals)[1]; \
+    } while (0)
+
+#define DNSDigest_SignMessageHostByteOrder(M,E,INFO) \
+       do { SwapDNSHeaderBytes(M); DNSDigest_SignMessage((M), (E), (INFO), 0); SwapDNSHeaderBytes(M); } while (0)
 
 // verify a DNS message.  The message must be complete, with all values in network byte order.  end points to the
 // end of the record.  tsig is a pointer to the resource record that contains the TSIG OPT record.  info is
 
 // verify a DNS message.  The message must be complete, with all values in network byte order.  end points to the
 // end of the record.  tsig is a pointer to the resource record that contains the TSIG OPT record.  info is
@@ -2510,10 +2582,15 @@ extern mDNSs32  mDNSPlatformRawTime     (void);
 extern mDNSs32  mDNSPlatformUTC         (void);
 #define mDNS_TimeNow_NoLock(m) (mDNSPlatformRawTime() + m->timenow_adjust)
 
 extern mDNSs32  mDNSPlatformUTC         (void);
 #define mDNS_TimeNow_NoLock(m) (mDNSPlatformRawTime() + m->timenow_adjust)
 
+#if MDNS_DEBUGMSGS
+extern void    mDNSPlatformWriteDebugMsg(const char *msg);
+#endif
+extern void    mDNSPlatformWriteLogMsg(const char *ident, const char *msg, int flags);
+
 // Platform support modules should provide the following functions to map between opaque interface IDs
 // and interface indexes in order to support the DNS-SD API. If your target platform does not support
 // multiple interfaces and/or does not support the DNS-SD API, these functions can be empty.
 // Platform support modules should provide the following functions to map between opaque interface IDs
 // and interface indexes in order to support the DNS-SD API. If your target platform does not support
 // multiple interfaces and/or does not support the DNS-SD API, these functions can be empty.
-extern mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 index);
+extern mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 ifindex);
 extern mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id);
 
 // Every platform support module must provide the following functions if it is to support unicast DNS
 extern mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id);
 
 // Every platform support module must provide the following functions if it is to support unicast DNS
index d6fddfa1b4a4e8b439c0652c398d6129aa0b47c4..bcf8ddffae6c1c7c44da7c7454a24ef31a75bfe8 100755 (executable)
        Change History (most recent first):
 
 $Log: uDNS.c,v $
        Change History (most recent first):
 
 $Log: uDNS.c,v $
+Revision 1.545  2007/12/22 02:25:29  cheshire
+<rdar://problem/5661128> Records and Services sometimes not re-registering on wake from sleep
+
+Revision 1.544  2007/12/18 00:40:11  cheshire
+<rdar://problem/5526796> Need to remove active LLQs from server upon question cancellation, on sleep, and on shutdown
+Reordered code to avoid double-TSIGs in some cases
+
+Revision 1.543  2007/12/17 23:57:43  cheshire
+<rdar://problem/5526796> Need to remove active LLQs from server upon question cancellation, on sleep, and on shutdown
+Need to include TSIG signature when sending LLQ cancellations over TLS
+
+Revision 1.542  2007/12/15 01:12:27  cheshire
+<rdar://problem/5526796> Need to remove active LLQs from server upon question cancellation, on sleep, and on shutdown
+
+Revision 1.541  2007/12/15 00:18:51  cheshire
+Renamed question->origLease to question->ReqLease
+
+Revision 1.540  2007/12/14 23:55:28  cheshire
+Moved "struct tcpInfo_t" definition from uDNS.c to mDNSEmbeddedAPI.h
+
+Revision 1.539  2007/12/14 20:44:24  cheshire
+<rdar://problem/5526800> BTMM: Need to deregister records and services on shutdown/sleep
+SleepRecordRegistrations/WakeRecordRegistrations should only operate on uDNS records
+
+Revision 1.538  2007/12/14 01:13:40  cheshire
+<rdar://problem/5526800> BTMM: Need to deregister records and services on shutdown/sleep
+Additional fixes (existing code to deregister private records and services didn't work at all)
+
+Revision 1.537  2007/12/11 00:18:25  cheshire
+<rdar://problem/5569316> BTMM: My iMac has a "ghost" ID associated with it
+There were cases where the code was incorrectly clearing the "uselease" flag, and never resetting it.
+
+Revision 1.536  2007/12/10 23:07:00  cheshire
+Removed some unnecessary log messages
+
+Revision 1.535  2007/12/06 00:22:27  mcguire
+<rdar://problem/5604567> BTMM: Doesn't work with Linksys WAG300N 1.01.06 (sending from 1026/udp)
+
+Revision 1.534  2007/12/04 00:49:37  cheshire
+<rdar://problem/5607082> BTMM: mDNSResponder taking 100 percent CPU after upgrading to 10.5.1
+
+Revision 1.533  2007/12/01 01:21:27  jgraessley
+<rdar://problem/5623140> mDNSResponder unicast DNS improvements
+
+Revision 1.532  2007/11/30 20:16:44  cheshire
+Fixed compile warning: declaration of 'end' shadows a previous local
+
+Revision 1.531  2007/11/28 22:00:09  cheshire
+In StartSRVNatMap, change "mDNSu8 *p" to "const mDNSu8 *p"
+
+Revision 1.530  2007/11/16 22:19:40  cheshire
+<rdar://problem/5547474> mDNSResponder leaks on network changes
+The "connection failed" code path in MakeTCPConn was not disposing of the TCPSocket it had created
+
+Revision 1.529  2007/11/15 22:52:29  cheshire
+<rdar://problem/5589039> ERROR: mDNSPlatformWriteTCP - send Broken pipe
+
 Revision 1.528  2007/11/02 21:32:30  cheshire
 <rdar://problem/5575593> BTMM: Deferring deregistration of record log messages on sleep/wake
 
 Revision 1.528  2007/11/02 21:32:30  cheshire
 <rdar://problem/5575593> BTMM: Deferring deregistration of record log messages on sleep/wake
 
@@ -1044,23 +1101,6 @@ Revision 1.227  2006/01/09 20:47:05  cheshire
        #pragma warning(disable:4706)
 #endif
 
        #pragma warning(disable:4706)
 #endif
 
-typedef struct tcpInfo_t
-       {
-       mDNS             *m;
-       TCPSocket        *sock;
-       DNSMessage        request;
-       int               requestLen;
-       DNSQuestion      *question;   // For queries
-       ServiceRecordSet *srs;        // For service record updates
-       AuthRecord       *rr;         // For record updates
-       mDNSAddr          Addr;
-       mDNSIPPort        Port;
-       DNSMessage       *reply;
-       mDNSu16           replylen;
-       unsigned long     nread;
-       int               numReplies;
-       } tcpInfo_t;
-
 typedef struct SearchListElem
        {
        struct SearchListElem *next;
 typedef struct SearchListElem
        {
        struct SearchListElem *next;
@@ -1086,7 +1126,7 @@ static SearchListElem *SearchList = mDNSNULL;
 // -- it should just be a grouping of records that are treated the same as any other registered records.
 // In that case it may no longer be necessary to keep an explicit list of ServiceRecordSets, which in turn
 // would avoid the perils of modifying that list cleanly while some other piece of code is iterating through it.
 // -- it should just be a grouping of records that are treated the same as any other registered records.
 // In that case it may no longer be necessary to keep an explicit list of ServiceRecordSets, which in turn
 // would avoid the perils of modifying that list cleanly while some other piece of code is iterating through it.
-static ServiceRecordSet *CurrentServiceRecordSet = mDNSNULL;
+ServiceRecordSet *CurrentServiceRecordSet = mDNSNULL;
 
 // ***************************************************************************
 #if COMPILER_LIKES_PRAGMA_MARK
 
 // ***************************************************************************
 #if COMPILER_LIKES_PRAGMA_MARK
@@ -1175,6 +1215,7 @@ mDNSlocal void SetRecordRetry(mDNS *const m, AuthRecord *rr, mStatus SendErr)
        if (rr->ThisAPInterval / 2 <= elapsed) rr->ThisAPInterval *= 2;
        if (rr->ThisAPInterval < INIT_UCAST_POLL_INTERVAL || SendErr == mStatus_TransientErr)
                rr->ThisAPInterval = INIT_UCAST_POLL_INTERVAL;
        if (rr->ThisAPInterval / 2 <= elapsed) rr->ThisAPInterval *= 2;
        if (rr->ThisAPInterval < INIT_UCAST_POLL_INTERVAL || SendErr == mStatus_TransientErr)
                rr->ThisAPInterval = INIT_UCAST_POLL_INTERVAL;
+       rr->ThisAPInterval += mDNSRandom(rr->ThisAPInterval/20);
        if (rr->ThisAPInterval > 30 * 60 * mDNSPlatformOneSecond)
                rr->ThisAPInterval = 30 * 60 * mDNSPlatformOneSecond;
 
        if (rr->ThisAPInterval > 30 * 60 * mDNSPlatformOneSecond)
                rr->ThisAPInterval = 30 * 60 * mDNSPlatformOneSecond;
 
@@ -1201,8 +1242,8 @@ mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, cons
                if ((*p)->interface == interface && (*p)->teststate != DNSServer_Disabled &&
                        mDNSSameAddress(&(*p)->addr, addr) && mDNSSameIPPort((*p)->port, port) && SameDomainName(&(*p)->domain, d))
                        {
                if ((*p)->interface == interface && (*p)->teststate != DNSServer_Disabled &&
                        mDNSSameAddress(&(*p)->addr, addr) && mDNSSameIPPort((*p)->port, port) && SameDomainName(&(*p)->domain, d))
                        {
-                       if (!(*p)->del) LogMsg("Note: DNS Server %#a for domain %##s registered more than once", addr, d->c);
-                       (*p)->del = mDNSfalse;
+                       if (!((*p)->flags & DNSServer_FlagDelete)) LogMsg("Note: DNS Server %#a for domain %##s registered more than once", addr, d->c);
+                       (*p)->flags &= ~DNSServer_FlagDelete;
                        return(*p);
                        }
                p=&(*p)->next;
                        return(*p);
                        }
                p=&(*p)->next;
@@ -1216,7 +1257,7 @@ mDNSexport DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, cons
                (*p)->interface = interface;
                (*p)->addr      = *addr;
                (*p)->port      = port;
                (*p)->interface = interface;
                (*p)->addr      = *addr;
                (*p)->port      = port;
-               (*p)->del       = mDNSfalse;
+               (*p)->flags     = DNSServer_FlagNew;
                (*p)->teststate = DNSServer_Untested;
                (*p)->lasttest  = m->timenow - INIT_UCAST_POLL_INTERVAL;
                AssignDomainName(&(*p)->domain, d);
                (*p)->teststate = DNSServer_Untested;
                (*p)->lasttest  = m->timenow - INIT_UCAST_POLL_INTERVAL;
                AssignDomainName(&(*p)->domain, d);
@@ -1662,7 +1703,7 @@ mDNSlocal void sendChallengeResponse(mDNS *const m, DNSQuestion *const q, const
                llqBuf.llqOp    = kLLQOp_Setup;
                llqBuf.err      = LLQErr_NoError;       // Don't need to tell server UDP notification port when sending over UDP
                llqBuf.id       = q->id;
                llqBuf.llqOp    = kLLQOp_Setup;
                llqBuf.err      = LLQErr_NoError;       // Don't need to tell server UDP notification port when sending over UDP
                llqBuf.id       = q->id;
-               llqBuf.llqlease = q->origLease;
+               llqBuf.llqlease = q->ReqLease;
                llq = &llqBuf;
                }
 
                llq = &llqBuf;
                }
 
@@ -1676,14 +1717,22 @@ mDNSlocal void sendChallengeResponse(mDNS *const m, DNSQuestion *const q, const
        InitializeDNSMessage(&m->omsg.h, q->TargetQID, uQueryFlags);
        responsePtr = putQuestion(&m->omsg, responsePtr, m->omsg.data + AbsoluteMaxDNSMessageData, &q->qname, q->qtype, q->qclass);
        if (responsePtr) responsePtr = putLLQ(&m->omsg, responsePtr, q, llq, mDNSfalse);
        InitializeDNSMessage(&m->omsg.h, q->TargetQID, uQueryFlags);
        responsePtr = putQuestion(&m->omsg, responsePtr, m->omsg.data + AbsoluteMaxDNSMessageData, &q->qname, q->qtype, q->qclass);
        if (responsePtr) responsePtr = putLLQ(&m->omsg, responsePtr, q, llq, mDNSfalse);
-       if (responsePtr) mDNSSendDNSMessage(m, &m->omsg, responsePtr, mDNSInterface_Any, &q->servAddr, q->servPort, q->tcp ? q->tcp->sock : mDNSNULL, q->AuthInfo);
+       if (responsePtr)
+               {
+               mStatus err = mDNSSendDNSMessage(m, &m->omsg, responsePtr, mDNSInterface_Any, &q->servAddr, q->servPort, q->tcp ? q->tcp->sock : mDNSNULL, q->AuthInfo);
+               if (err)
+                       {
+                       LogMsg("sendChallengeResponse: mDNSSendDNSMessage%s failed: %d", q->tcp ? " (TCP)" : "", err);
+                       if (q->tcp) { DisposeTCPConn(q->tcp); q->tcp = mDNSNULL; }
+                       }
+               }
        else StartLLQPolling(m,q);
        }
 
 mDNSlocal void SetLLQTimer(mDNS *const m, DNSQuestion *const q, const LLQOptData *const llq)
        {
        mDNSs32 lease = (mDNSs32)llq->llqlease * mDNSPlatformOneSecond;
        else StartLLQPolling(m,q);
        }
 
 mDNSlocal void SetLLQTimer(mDNS *const m, DNSQuestion *const q, const LLQOptData *const llq)
        {
        mDNSs32 lease = (mDNSs32)llq->llqlease * mDNSPlatformOneSecond;
-       q->origLease     = llq->llqlease;
+       q->ReqLease      = llq->llqlease;
        q->LastQTime     = m->timenow;
        q->expire        = m->timenow + lease;
        q->ThisQInterval = lease/2 + mDNSRandom(lease/10);
        q->LastQTime     = m->timenow;
        q->expire        = m->timenow + lease;
        q->ThisQInterval = lease/2 + mDNSRandom(lease/10);
@@ -1707,11 +1756,11 @@ mDNSlocal void recvSetupResponse(mDNS *const m, mDNSu8 rcode, DNSQuestion *const
 
                if (llq->err) { LogMsg("recvSetupResponse - received llq->err %d from server", llq->err); StartLLQPolling(m,q); return; }
        
 
                if (llq->err) { LogMsg("recvSetupResponse - received llq->err %d from server", llq->err); StartLLQPolling(m,q); return; }
        
-               if (q->origLease != llq->llqlease)
-                       debugf("recvSetupResponse: requested lease %lu, granted lease %lu", q->origLease, llq->llqlease);
+               if (q->ReqLease != llq->llqlease)
+                       debugf("recvSetupResponse: requested lease %lu, granted lease %lu", q->ReqLease, llq->llqlease);
        
                // cache expiration in case we go to sleep before finishing setup
        
                // cache expiration in case we go to sleep before finishing setup
-               q->origLease = llq->llqlease;
+               q->ReqLease = llq->llqlease;
                q->expire = m->timenow + ((mDNSs32)llq->llqlease * mDNSPlatformOneSecond);
        
                // update state
                q->expire = m->timenow + ((mDNSs32)llq->llqlease * mDNSPlatformOneSecond);
        
                // update state
@@ -1825,33 +1874,43 @@ mDNSlocal void tcpCallback(TCPSocket *sock, void *context, mDNSBool ConnectionEs
        {
        tcpInfo_t *tcpInfo = (tcpInfo_t *)context;
        mDNSBool   closed  = mDNSfalse;
        {
        tcpInfo_t *tcpInfo = (tcpInfo_t *)context;
        mDNSBool   closed  = mDNSfalse;
-       mDNSu8    *end;
        mDNS      *m       = tcpInfo->m;
        mDNS      *m       = tcpInfo->m;
-
+       DNSQuestion *const q = tcpInfo->question;
        tcpInfo_t **backpointer =
        tcpInfo_t **backpointer =
-               tcpInfo->question ? &tcpInfo->question->tcp :
+               q                 ? &q           ->tcp :
                tcpInfo->srs      ? &tcpInfo->srs->tcp :
                tcpInfo->srs      ? &tcpInfo->srs->tcp :
-               tcpInfo->rr       ? &tcpInfo->rr->tcp : mDNSNULL;
-       if (!backpointer) LogMsg("tcpCallback: Purpose of connection unidentified");
-       else if (*backpointer != tcpInfo)
+               tcpInfo->rr       ? &tcpInfo->rr ->tcp : mDNSNULL;
+       if (backpointer && *backpointer != tcpInfo)
                LogMsg("tcpCallback: %d backpointer %p incorrect tcpInfo %p question %p srs %p rr %p",
                LogMsg("tcpCallback: %d backpointer %p incorrect tcpInfo %p question %p srs %p rr %p",
-                       mDNSPlatformTCPGetFD(tcpInfo->sock), *backpointer, tcpInfo, tcpInfo->question, tcpInfo->srs, tcpInfo->rr);
+                       mDNSPlatformTCPGetFD(tcpInfo->sock), *backpointer, tcpInfo, q, tcpInfo->srs, tcpInfo->rr);
 
        if (err) goto exit;
 
        if (ConnectionEstablished)
                {
 
        if (err) goto exit;
 
        if (ConnectionEstablished)
                {
+               mDNSu8    *end = ((mDNSu8*) &tcpInfo->request) + tcpInfo->requestLen;
                DomainAuthInfo *AuthInfo;
                DomainAuthInfo *AuthInfo;
+
+               // Defensive coding for <rdar://problem/5546824> Crash in mDNSResponder at GetAuthInfoForName_internal + 366
+               // Don't know yet what's causing this, but at least we can be cautious and try to avoid crashing if we find our pointers in an unexpected state
+               if (tcpInfo->srs && tcpInfo->srs->RR_SRV.resrec.name != &tcpInfo->srs->RR_SRV.namestorage)
+                       LogMsg("tcpCallback: ERROR: tcpInfo->srs->RR_SRV.resrec.name %p != &tcpInfo->srs->RR_SRV.namestorage %p",
+                               tcpInfo->srs->RR_SRV.resrec.name, &tcpInfo->srs->RR_SRV.namestorage);
+               if (tcpInfo->rr && tcpInfo->rr->resrec.name != &tcpInfo->rr->namestorage)
+                       LogMsg("tcpCallback: ERROR: tcpInfo->rr->resrec.name %p != &tcpInfo->rr->namestorage %p",
+                               tcpInfo->rr->resrec.name, &tcpInfo->rr->namestorage);
+               if (tcpInfo->srs && tcpInfo->srs->RR_SRV.resrec.name != &tcpInfo->srs->RR_SRV.namestorage) return;
+               if (tcpInfo->rr  && tcpInfo->rr->        resrec.name != &tcpInfo->rr->        namestorage) return;
+
+               AuthInfo =  tcpInfo->srs ? GetAuthInfoForName(m, tcpInfo->srs->RR_SRV.resrec.name) :
+                                       tcpInfo->rr  ? GetAuthInfoForName(m, tcpInfo->rr->resrec.name)         : mDNSNULL;
+
                // connection is established - send the message
                // connection is established - send the message
-               if (tcpInfo->question && tcpInfo->question->LongLived && tcpInfo->question->state == LLQ_Established)
+               if (q && q->LongLived && q->state == LLQ_Established)
                        {
                        {
-                       //LogMsg("tcpCallback calling sendLLQRefresh %##s (%s)", tcpInfo->question->qname.c, DNSTypeName(tcpInfo->question->qtype));
-                       mDNS_Lock(m);
-                       sendLLQRefresh(m, tcpInfo->question, tcpInfo->question->origLease);
-                       mDNS_Unlock(m);
-                       return;
+                       end = ((mDNSu8*) &tcpInfo->request) + tcpInfo->requestLen;
                        }
                        }
-               else if (tcpInfo->question && tcpInfo->question->LongLived && tcpInfo->question->state != LLQ_Poll && !mDNSIPPortIsZero(m->LLQNAT.ExternalPort))
+               else if (q && q->LongLived && q->state != LLQ_Poll && !mDNSIPPortIsZero(m->LLQNAT.ExternalPort))
                        {
                        // Notes:
                        // If we have a NAT port mapping, ExternalPort is the external port
                        {
                        // Notes:
                        // If we have a NAT port mapping, ExternalPort is the external port
@@ -1864,45 +1923,28 @@ mDNSlocal void tcpCallback(TCPSocket *sock, void *context, mDNSBool ConnectionEs
                        LogOperation("tcpCallback: eventPort %d", llqData.err);
                        llqData.id    = zeroOpaque64;
                        llqData.llqlease = kLLQ_DefLease;
                        LogOperation("tcpCallback: eventPort %d", llqData.err);
                        llqData.id    = zeroOpaque64;
                        llqData.llqlease = kLLQ_DefLease;
-                       InitializeDNSMessage(&tcpInfo->request.h, tcpInfo->question->TargetQID, uQueryFlags);
-                       end = putLLQ(&tcpInfo->request, tcpInfo->request.data, tcpInfo->question, &llqData, mDNStrue);
+                       InitializeDNSMessage(&tcpInfo->request.h, q->TargetQID, uQueryFlags);
+                       end = putLLQ(&tcpInfo->request, tcpInfo->request.data, q, &llqData, mDNStrue);
                        if (!end) { LogMsg("ERROR: tcpCallback - putLLQ"); err = mStatus_UnknownErr; goto exit; }
                        if (!end) { LogMsg("ERROR: tcpCallback - putLLQ"); err = mStatus_UnknownErr; goto exit; }
+                       AuthInfo = q->AuthInfo;         // Need to add TSIG to this message
                        }
                        }
-               else if (tcpInfo->question)
+               else if (q)
                        {
                        {
-                       DNSQuestion *q = tcpInfo->question;
                        InitializeDNSMessage(&tcpInfo->request.h, q->TargetQID, uQueryFlags);
                        end = putQuestion(&tcpInfo->request, tcpInfo->request.data, tcpInfo->request.data + AbsoluteMaxDNSMessageData, &q->qname, q->qtype, q->qclass);
                        InitializeDNSMessage(&tcpInfo->request.h, q->TargetQID, uQueryFlags);
                        end = putQuestion(&tcpInfo->request, tcpInfo->request.data, tcpInfo->request.data + AbsoluteMaxDNSMessageData, &q->qname, q->qtype, q->qclass);
+                       AuthInfo = q->AuthInfo;         // Need to add TSIG to this message
                        }
                        }
-               else
-                       end = ((mDNSu8*) &tcpInfo->request) + tcpInfo->requestLen;
-
-               // Defensive coding for <rdar://problem/5546824> Crash in mDNSResponder at GetAuthInfoForName_internal + 366
-               // Don't know yet what's causing this, but at least we can be cautious and try to avoid crashing if we find our pointers in an unexpected state
-               if (tcpInfo->srs && tcpInfo->srs->RR_SRV.resrec.name != &tcpInfo->srs->RR_SRV.namestorage)
-                       LogMsg("tcpCallback: ERROR: tcpInfo->srs->RR_SRV.resrec.name %p != &tcpInfo->srs->RR_SRV.namestorage %p",
-                               tcpInfo->srs->RR_SRV.resrec.name, &tcpInfo->srs->RR_SRV.namestorage);
-               if (tcpInfo->rr && tcpInfo->rr->resrec.name != &tcpInfo->rr->namestorage)
-                       LogMsg("tcpCallback: ERROR: tcpInfo->rr->resrec.name %p != &tcpInfo->rr->namestorage %p",
-                               tcpInfo->rr->resrec.name, &tcpInfo->rr->namestorage);
-               if (tcpInfo->srs && tcpInfo->srs->RR_SRV.resrec.name != &tcpInfo->srs->RR_SRV.namestorage) return;
-               if (tcpInfo->rr  && tcpInfo->rr->        resrec.name != &tcpInfo->rr->        namestorage) return;
-
-               AuthInfo =      tcpInfo->question ? tcpInfo->question->AuthInfo :
-                                       tcpInfo->srs      ? GetAuthInfoForName(m, tcpInfo->srs->RR_SRV.resrec.name) :
-                                       tcpInfo->rr       ? GetAuthInfoForName(m, tcpInfo->rr->resrec.name) : mDNSNULL;
 
                err = mDNSSendDNSMessage(m, &tcpInfo->request, end, mDNSInterface_Any, &tcpInfo->Addr, tcpInfo->Port, sock, AuthInfo);
 
                err = mDNSSendDNSMessage(m, &tcpInfo->request, end, mDNSInterface_Any, &tcpInfo->Addr, tcpInfo->Port, sock, AuthInfo);
-
                if (err) { debugf("ERROR: tcpCallback: mDNSSendDNSMessage - %ld", err); err = mStatus_UnknownErr; goto exit; }
 
                // Record time we sent this question
                if (err) { debugf("ERROR: tcpCallback: mDNSSendDNSMessage - %ld", err); err = mStatus_UnknownErr; goto exit; }
 
                // Record time we sent this question
-               if (tcpInfo->question)
+               if (q)
                        {
                        mDNS_Lock(m);
                        {
                        mDNS_Lock(m);
-                       tcpInfo->question->LastQTime = m->timenow;
-                       tcpInfo->question->ThisQInterval = MAX_UCAST_POLL_INTERVAL;
-                       SetNextQueryTime(m, tcpInfo->question);
+                       q->LastQTime = m->timenow;
+                       q->ThisQInterval = MAX_UCAST_POLL_INTERVAL;
+                       SetNextQueryTime(m, q);
                        mDNS_Unlock(m);
                        }
                }
                        mDNS_Unlock(m);
                        }
                }
@@ -1920,7 +1962,7 @@ mDNSlocal void tcpCallback(TCPSocket *sock, void *context, mDNSBool ConnectionEs
                                // be sending gratuitous replies using UDP and doesn't have a need to leave the TCP socket open.
                                // We'll only log this event if we've never received a reply before.
                                // BIND 9 appears to close an idle connection after 30 seconds.
                                // be sending gratuitous replies using UDP and doesn't have a need to leave the TCP socket open.
                                // We'll only log this event if we've never received a reply before.
                                // BIND 9 appears to close an idle connection after 30 seconds.
-                               if (tcpInfo->numReplies == 0) LogMsg("ERROR: socket closed prematurely %d", tcpInfo->nread);
+                               if (tcpInfo->numReplies == 0) LogMsg("ERROR: socket closed prematurely tcpInfo->nread = %d", tcpInfo->nread);
                                err = mStatus_ConnFailed;
                                goto exit;
                                }
                                err = mStatus_ConnFailed;
                                goto exit;
                                }
@@ -1956,7 +1998,11 @@ mDNSlocal void tcpCallback(TCPSocket *sock, void *context, mDNSBool ConnectionEs
                        tcpInfo->replylen = 0;
                        
                        // If we're going to dispose this connection, do it FIRST, before calling client callback
                        tcpInfo->replylen = 0;
                        
                        // If we're going to dispose this connection, do it FIRST, before calling client callback
-                       if (!tcpInfo->question || !tcpInfo->question->LongLived) { *backpointer = mDNSNULL; DisposeTCPConn(tcpInfo); }
+                       // Note: Sleep code depends on us clearing *backpointer here -- it uses the clearing of rr->tcp and srs->tcp
+                       // as the signal that the DNS deregistration operation with the server has completed, and the machine may now sleep
+                       if (backpointer)
+                               if (!q || !q->LongLived || m->SleepState)
+                                       { *backpointer = mDNSNULL; DisposeTCPConn(tcpInfo); }
                        
                        if (rr && rr->resrec.RecordType == kDNSRecordTypeDeregistering)
                                {
                        
                        if (rr && rr->resrec.RecordType == kDNSRecordTypeDeregistering)
                                {
@@ -1980,13 +2026,12 @@ exit:
                {
                // Clear client backpointer FIRST -- that way if one of the callbacks cancels its operation
                // we won't end up double-disposing our tcpInfo_t
                {
                // Clear client backpointer FIRST -- that way if one of the callbacks cancels its operation
                // we won't end up double-disposing our tcpInfo_t
-               *backpointer = mDNSNULL;
+               if (backpointer) *backpointer = mDNSNULL;
 
                mDNS_Lock(m);           // Need to grab the lock to get m->timenow
 
 
                mDNS_Lock(m);           // Need to grab the lock to get m->timenow
 
-               if (tcpInfo->question)
+               if (q)
                        {
                        {
-                       DNSQuestion *q = tcpInfo->question;
                        if (q->ThisQInterval == 0 || q->LastQTime + q->ThisQInterval - m->timenow > MAX_UCAST_POLL_INTERVAL)
                                {
                                q->LastQTime     = m->timenow;
                        if (q->ThisQInterval == 0 || q->LastQTime + q->ThisQInterval - m->timenow > MAX_UCAST_POLL_INTERVAL)
                                {
                                q->LastQTime     = m->timenow;
@@ -1995,7 +2040,10 @@ exit:
                                }
                        // ConnFailed is actually okay.  It just means that the server closed the connection but the LLQ is still okay.
                        // If the error isn't ConnFailed, then the LLQ is in bad shape.
                                }
                        // ConnFailed is actually okay.  It just means that the server closed the connection but the LLQ is still okay.
                        // If the error isn't ConnFailed, then the LLQ is in bad shape.
-                       if (err != mStatus_ConnFailed) StartLLQPolling(m, tcpInfo->question);
+                       if (err != mStatus_ConnFailed)
+                               {
+                               if (q->LongLived && q->state != LLQ_Poll) StartLLQPolling(m, q);
+                               }
                        }
 
                if (tcpInfo->rr) SetRecordRetry(m, tcpInfo->rr, mStatus_NoError);
                        }
 
                if (tcpInfo->rr) SetRecordRetry(m, tcpInfo->rr, mStatus_NoError);
@@ -2016,21 +2064,27 @@ mDNSlocal tcpInfo_t *MakeTCPConn(mDNS *const m, const DNSMessage *const msg, con
        mDNSIPPort srcport = zeroIPPort;
        tcpInfo_t *info = (tcpInfo_t *)mDNSPlatformMemAllocate(sizeof(tcpInfo_t));
        if (!info) { LogMsg("ERROR: MakeTCP - memallocate failed"); return(mDNSNULL); }
        mDNSIPPort srcport = zeroIPPort;
        tcpInfo_t *info = (tcpInfo_t *)mDNSPlatformMemAllocate(sizeof(tcpInfo_t));
        if (!info) { LogMsg("ERROR: MakeTCP - memallocate failed"); return(mDNSNULL); }
-
        mDNSPlatformMemZero(info, sizeof(tcpInfo_t));
        mDNSPlatformMemZero(info, sizeof(tcpInfo_t));
+
        info->m          = m;
        info->m          = m;
-       if (msg)
-               {
-               info->request    = *msg;
-               info->requestLen = (int) (end - ((mDNSu8*)msg));
-               }
+       info->sock       = mDNSPlatformTCPSocket(m, flags, &srcport);
+       info->requestLen = 0;
        info->question   = question;
        info->srs        = srs;
        info->rr         = rr;
        info->Addr       = *Addr;
        info->Port       = Port;
        info->question   = question;
        info->srs        = srs;
        info->rr         = rr;
        info->Addr       = *Addr;
        info->Port       = Port;
+       info->reply      = mDNSNULL;
+       info->replylen   = 0;
+       info->nread      = 0;
+       info->numReplies = 0;
+
+       if (msg)
+               {
+               info->requestLen = (int) (end - ((mDNSu8*)msg));
+               mDNSPlatformMemCopy(&info->request, msg, info->requestLen);
+               }
 
 
-       info->sock = mDNSPlatformTCPSocket(m, flags, &srcport);
        if (!info->sock) { LogMsg("SendServiceRegistration: uanble to create TCP socket"); mDNSPlatformMemFree(info); return(mDNSNULL); }
        err = mDNSPlatformTCPConnect(info->sock, Addr, Port, 0, tcpCallback, info);
 
        if (!info->sock) { LogMsg("SendServiceRegistration: uanble to create TCP socket"); mDNSPlatformMemFree(info); return(mDNSNULL); }
        err = mDNSPlatformTCPConnect(info->sock, Addr, Port, 0, tcpCallback, info);
 
@@ -2042,7 +2096,7 @@ mDNSlocal tcpInfo_t *MakeTCPConn(mDNS *const m, const DNSMessage *const msg, con
 
        // Don't need to log "connection failed" in customer builds -- it happens quite often during sleep, wake, configuration changes, etc.
        if      (err == mStatus_ConnEstablished) { tcpCallback(info->sock, info, mDNStrue, mStatus_NoError); }
 
        // Don't need to log "connection failed" in customer builds -- it happens quite often during sleep, wake, configuration changes, etc.
        if      (err == mStatus_ConnEstablished) { tcpCallback(info->sock, info, mDNStrue, mStatus_NoError); }
-       else if (err != mStatus_ConnPending    ) { LogOperation("MakeTCPConnection: connection failed"); mDNSPlatformMemFree(info); return(mDNSNULL); }
+       else if (err != mStatus_ConnPending    ) { LogOperation("MakeTCPConnection: connection failed"); DisposeTCPConn(info); return(mDNSNULL); }
        return(info);
        }
 
        return(info);
        }
 
@@ -2095,7 +2149,7 @@ mDNSexport void startLLQHandshake(mDNS *m, DNSQuestion *q)
                else
                        {
                        q->state         = LLQ_SecondaryRequest;                // Right now, for private DNS, we skip the four-way LLQ handshake
                else
                        {
                        q->state         = LLQ_SecondaryRequest;                // Right now, for private DNS, we skip the four-way LLQ handshake
-                       q->origLease     = kLLQ_DefLease;
+                       q->ReqLease      = kLLQ_DefLease;
                        q->ThisQInterval = 0;
                        }
                q->LastQTime     = m->timenow;
                        q->ThisQInterval = 0;
                        }
                q->LastQTime     = m->timenow;
@@ -2133,7 +2187,7 @@ mDNSexport void startLLQHandshake(mDNS *m, DNSQuestion *q)
        
                        // update question state
                        q->state         = LLQ_InitialRequest;
        
                        // update question state
                        q->state         = LLQ_InitialRequest;
-                       q->origLease     = kLLQ_DefLease;
+                       q->ReqLease      = kLLQ_DefLease;
                        q->ThisQInterval = (kLLQ_INIT_RESEND * mDNSPlatformOneSecond);
                        q->LastQTime     = m->timenow;
                        SetNextQueryTime(m, q);
                        q->ThisQInterval = (kLLQ_INIT_RESEND * mDNSPlatformOneSecond);
                        q->LastQTime     = m->timenow;
                        SetNextQueryTime(m, q);
@@ -2303,11 +2357,9 @@ mDNSlocal void SendServiceRegistration(mDNS *m, ServiceRecordSet *srs)
        return;
 
 exit:
        return;
 
 exit:
-
        if (err)
                {
                LogMsg("SendServiceRegistration ERROR formatting message %d!! Permanently abandoning service registration %##s", err, srs->RR_SRV.resrec.name->c);
        if (err)
                {
                LogMsg("SendServiceRegistration ERROR formatting message %d!! Permanently abandoning service registration %##s", err, srs->RR_SRV.resrec.name->c);
-
                unlinkSRS(m, srs);
                srs->state = regState_Unregistered;
 
                unlinkSRS(m, srs);
                srs->state = regState_Unregistered;
 
@@ -2405,6 +2457,16 @@ mDNSlocal void GetZoneData_QuestionCallback(mDNS *const m, DNSQuestion *question
                mDNS_StopQuery(m, question);
                zd->Addr.type  = mDNSAddrType_IPv4;
                zd->Addr.ip.v4 = (answer->rdlength == 4) ? answer->rdata->u.ipv4 : zerov4Addr;
                mDNS_StopQuery(m, question);
                zd->Addr.type  = mDNSAddrType_IPv4;
                zd->Addr.ip.v4 = (answer->rdlength == 4) ? answer->rdata->u.ipv4 : zerov4Addr;
+               // In order to simulate firewalls blocking our outgoing TCP connections, returning immediate ICMP errors or TCP resets,
+               // the code below will make us try to connect to loopback, resulting in an immediate "port unreachable" failure.
+               // This helps us test to make sure we handle this case gracefully
+               // <rdar://problem/5607082> BTMM: mDNSResponder taking 100 percent CPU after upgrading to 10.5.1
+#if 0
+               zd->Addr.ip.v4.b[0] = 127;
+               zd->Addr.ip.v4.b[1] = 0;
+               zd->Addr.ip.v4.b[2] = 0;
+               zd->Addr.ip.v4.b[3] = 1;
+#endif
                zd->ZoneDataCallback(m, mStatus_NoError, zd);
                mDNSPlatformMemFree(zd);
                }
                zd->ZoneDataCallback(m, mStatus_NoError, zd);
                mDNSPlatformMemFree(zd);
                }
@@ -2509,7 +2571,7 @@ mDNSlocal void CompleteSRVNatMap(mDNS *m, NATTraversalInfo *n)
 
 mDNSlocal void StartSRVNatMap(mDNS *m, ServiceRecordSet *srs)
        {
 
 mDNSlocal void StartSRVNatMap(mDNS *m, ServiceRecordSet *srs)
        {
-       mDNSu8 *p = srs->RR_PTR.resrec.name->c;
+       const mDNSu8 *p = srs->RR_PTR.resrec.name->c;
        if (p[0]) p += 1 + p[0];
        if      (SameDomainLabel(p, (mDNSu8 *)"\x4" "_tcp")) srs->NATinfo.Protocol = NATOp_MapTCP;
        else if (SameDomainLabel(p, (mDNSu8 *)"\x4" "_udp")) srs->NATinfo.Protocol = NATOp_MapUDP;
        if (p[0]) p += 1 + p[0];
        if      (SameDomainLabel(p, (mDNSu8 *)"\x4" "_tcp")) srs->NATinfo.Protocol = NATOp_MapTCP;
        else if (SameDomainLabel(p, (mDNSu8 *)"\x4" "_udp")) srs->NATinfo.Protocol = NATOp_MapUDP;
@@ -2528,29 +2590,29 @@ mDNSlocal void StartSRVNatMap(mDNS *m, ServiceRecordSet *srs)
 mDNSexport void ServiceRegistrationGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneData)
        {
        ServiceRecordSet *srs = (ServiceRecordSet *)zoneData->ZoneDataContext;
 mDNSexport void ServiceRegistrationGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneData)
        {
        ServiceRecordSet *srs = (ServiceRecordSet *)zoneData->ZoneDataContext;
-       
+
        if (m->mDNS_busy != m->mDNS_reentrancy)
                LogMsg("ServiceRegistrationGotZoneData: mDNS_busy (%ld) != mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
 
        srs->nta = mDNSNULL;
 
        if (m->mDNS_busy != m->mDNS_reentrancy)
                LogMsg("ServiceRegistrationGotZoneData: mDNS_busy (%ld) != mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
 
        srs->nta = mDNSNULL;
 
+       // Start off assuming we're going to use a lease
+       // If we get an error from the server, and the update port as given in the SRV record is 53, then we'll retry without the lease option
+       srs->srs_uselease = mDNStrue;
+
        if (err || !zoneData) return;
 
        if (err || !zoneData) return;
 
+       if (mDNSIPPortIsZero(zoneData->Port) || mDNSAddressIsZero(&zoneData->Addr)) return;
+
        // cache zone data
        AssignDomainName(&srs->zone, &zoneData->ZoneName);
        srs->SRSUpdateServer.type = mDNSAddrType_IPv4;
        srs->SRSUpdateServer      = zoneData->Addr;
        // cache zone data
        AssignDomainName(&srs->zone, &zoneData->ZoneName);
        srs->SRSUpdateServer.type = mDNSAddrType_IPv4;
        srs->SRSUpdateServer      = zoneData->Addr;
-       if (!mDNSIPPortIsZero(zoneData->Port))
-               {
-               srs->SRSUpdatePort = zoneData->Port;
-               srs->Private       = zoneData->ZonePrivate;
-               }
-       else
-               {
-               debugf("Update port not advertised via SRV - guessing port 53, no lease option");
-               srs->SRSUpdatePort = UnicastDNSPort;
-               srs->srs_uselease = mDNSfalse;
-               }
+       srs->SRSUpdatePort        = zoneData->Port;
+       srs->Private              = zoneData->ZonePrivate;
+
+       srs->RR_SRV.LastAPTime     = m->timenow;
+       srs->RR_SRV.ThisAPInterval = 0;
 
        LogOperation("ServiceRegistrationGotZoneData My IPv4 %#a%s Server %#a:%d%s for %##s",
                &m->AdvertisedV4, mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4) ? " (RFC1918)" : "",
 
        LogOperation("ServiceRegistrationGotZoneData My IPv4 %#a%s Server %#a:%d%s for %##s",
                &m->AdvertisedV4, mDNSv4AddrIsRFC1918(&m->AdvertisedV4.ip.v4) ? " (RFC1918)" : "",
@@ -2603,9 +2665,11 @@ mDNSlocal void SendServiceDeregistration(mDNS *m, ServiceRecordSet *srs)
 
        srs->id    = id;
        srs->state = regState_DeregPending;
 
        srs->id    = id;
        srs->state = regState_DeregPending;
+       srs->RR_SRV.expire = 0;         // Indicate that we have no active registration any more
 
        if (srs->Private)
                {
 
        if (srs->Private)
                {
+               LogOperation("SendServiceDeregistration TCP %p %s", srs->tcp, ARDisplayString(m, &srs->RR_SRV));
                if (srs->tcp) LogOperation("SendServiceDeregistration: Disposing existing TCP connection for %s", ARDisplayString(m, &srs->RR_SRV));
                if (srs->tcp) DisposeTCPConn(srs->tcp);
                srs->tcp = MakeTCPConn(m, &m->omsg, ptr, kTCPSocketFlags_UseTLS, &srs->SRSUpdateServer, srs->SRSUpdatePort, mDNSNULL, srs, mDNSNULL);
                if (srs->tcp) LogOperation("SendServiceDeregistration: Disposing existing TCP connection for %s", ARDisplayString(m, &srs->RR_SRV));
                if (srs->tcp) DisposeTCPConn(srs->tcp);
                srs->tcp = MakeTCPConn(m, &m->omsg, ptr, kTCPSocketFlags_UseTLS, &srs->SRSUpdateServer, srs->SRSUpdatePort, mDNSNULL, srs, mDNSNULL);
@@ -2622,7 +2686,6 @@ mDNSlocal void SendServiceDeregistration(mDNS *m, ServiceRecordSet *srs)
        return;
 
 exit:
        return;
 
 exit:
-
        if (err)
                {
                LogMsg("SendServiceDeregistration ERROR formatting message %d!! Permanently abandoning service registration %##s", err, srs->RR_SRV.resrec.name->c);
        if (err)
                {
                LogMsg("SendServiceDeregistration ERROR formatting message %d!! Permanently abandoning service registration %##s", err, srs->RR_SRV.resrec.name->c);
@@ -2729,6 +2792,9 @@ mDNSlocal void UpdateSRV(mDNS *m, ServiceRecordSet *srs)
 // Called with lock held
 mDNSlocal void UpdateSRVRecords(mDNS *m)
        {
 // Called with lock held
 mDNSlocal void UpdateSRVRecords(mDNS *m)
        {
+       LogOperation("UpdateSRVRecords%s", m->SleepState ? " (ignored due to SleepState)" : "");
+       if (m->SleepState) return;
+
        if (CurrentServiceRecordSet)
                LogMsg("UpdateSRVRecords ERROR CurrentServiceRecordSet already set");
        CurrentServiceRecordSet = m->ServiceRegistrations;
        if (CurrentServiceRecordSet)
                LogMsg("UpdateSRVRecords ERROR CurrentServiceRecordSet already set");
        CurrentServiceRecordSet = m->ServiceRegistrations;
@@ -2763,7 +2829,7 @@ mDNSlocal void hostnameGetPublicAddressCallback(mDNS *m, NATTraversalInfo *n)
                        }
                else
                        {
                        }
                else
                        {
-                       LogMsg("Advertising hostname %##s IPv4 %.4a (NAT gateway's external address)", h->arv4.resrec.name->c, &n->ExternalAddress);
+                       LogOperation("Advertising hostname %##s IPv4 %.4a (NAT gateway's external address)", h->arv4.resrec.name->c, &n->ExternalAddress);
                        h->arv4.resrec.RecordType = kDNSRecordTypeKnownUnique;
                        h->arv4.resrec.rdata->u.ipv4 = n->ExternalAddress;
                        mDNS_Register(m, &h->arv4);
                        h->arv4.resrec.RecordType = kDNSRecordTypeKnownUnique;
                        h->arv4.resrec.rdata->u.ipv4 = n->ExternalAddress;
                        mDNS_Register(m, &h->arv4);
@@ -2794,7 +2860,7 @@ mDNSlocal void AdvertiseHostname(mDNS *m, HostnameInfo *h)
                        }
                else
                        {
                        }
                else
                        {
-                       LogMsg("Advertising hostname %##s IPv4 %.4a", h->arv4.resrec.name->c, &m->AdvertisedV4.ip.v4);
+                       LogOperation("Advertising hostname %##s IPv4 %.4a", h->arv4.resrec.name->c, &m->AdvertisedV4.ip.v4);
                        h->arv4.resrec.RecordType = kDNSRecordTypeKnownUnique;
                        mDNS_Register_internal(m, &h->arv4);
                        }
                        h->arv4.resrec.RecordType = kDNSRecordTypeKnownUnique;
                        mDNS_Register_internal(m, &h->arv4);
                        }
@@ -2806,7 +2872,7 @@ mDNSlocal void AdvertiseHostname(mDNS *m, HostnameInfo *h)
                AssignDomainName(&h->arv6.namestorage, &h->fqdn);
                h->arv6.resrec.rdata->u.ipv6 = m->AdvertisedV6.ip.v6;
                h->arv6.state = regState_Unregistered;
                AssignDomainName(&h->arv6.namestorage, &h->fqdn);
                h->arv6.resrec.rdata->u.ipv6 = m->AdvertisedV6.ip.v6;
                h->arv6.state = regState_Unregistered;
-               LogMsg("Advertising hostname %##s IPv6 %.16a", h->arv6.resrec.name->c, &m->AdvertisedV6.ip.v6);
+               LogOperation("Advertising hostname %##s IPv6 %.16a", h->arv6.resrec.name->c, &m->AdvertisedV6.ip.v6);
                mDNS_Register_internal(m, &h->arv6);
                }
        }
                mDNS_Register_internal(m, &h->arv6);
                }
        }
@@ -2868,9 +2934,9 @@ mDNSlocal void HostnameCallback(mDNS *const m, AuthRecord *const rr, mStatus res
        // Deliver success to client
        if (!hi) { LogMsg("HostnameCallback invoked with orphaned address record"); return; }
        if (rr->resrec.rrtype == kDNSType_A)
        // Deliver success to client
        if (!hi) { LogMsg("HostnameCallback invoked with orphaned address record"); return; }
        if (rr->resrec.rrtype == kDNSType_A)
-               LogMsg("Registered hostname %##s IP %.4a", rr->resrec.name->c, &rr->resrec.rdata->u.ipv4);
+               LogOperation("Registered hostname %##s IP %.4a", rr->resrec.name->c, &rr->resrec.rdata->u.ipv4);
        else
        else
-               LogMsg("Registered hostname %##s IP %.16a", rr->resrec.name->c, &rr->resrec.rdata->u.ipv6);
+               LogOperation("Registered hostname %##s IP %.16a", rr->resrec.name->c, &rr->resrec.rdata->u.ipv6);
 
        rr->RecordContext = (void *)hi->StatusContext;
        if (hi->StatusCallback)
 
        rr->RecordContext = (void *)hi->StatusContext;
        if (hi->StatusCallback)
@@ -2896,7 +2962,7 @@ mDNSlocal void FoundStaticHostname(mDNS *const m, DNSQuestion *question, const R
                                h->arv6.state == regState_FetchingZoneData || h->arv6.state == regState_Pending)
                                {
                                // if we're in the process of registering a dynamic hostname, delay SRV update so we don't have to reregister services if the dynamic name succeeds
                                h->arv6.state == regState_FetchingZoneData || h->arv6.state == regState_Pending)
                                {
                                // if we're in the process of registering a dynamic hostname, delay SRV update so we don't have to reregister services if the dynamic name succeeds
-                               m->NextSRVUpdate = NonZeroTime(m->timenow + (5 * mDNSPlatformOneSecond));
+                               m->NextSRVUpdate = NonZeroTime(m->timenow + 5 * mDNSPlatformOneSecond);
                                return;
                                }
                        h = h->next;
                                return;
                                }
                        h = h->next;
@@ -3268,6 +3334,8 @@ mDNSlocal void hndlServiceUpdateReply(mDNS *const m, ServiceRecordSet *srs,  mSt
        if (m->mDNS_busy != m->mDNS_reentrancy+1)
                LogMsg("hndlServiceUpdateReply: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
 
        if (m->mDNS_busy != m->mDNS_reentrancy+1)
                LogMsg("hndlServiceUpdateReply: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
 
+       LogOperation("hndlServiceUpdateReply: err %d state %d %##s", err, srs->state, srs->RR_SRV.resrec.name->c);
+
        SetRecordRetry(m, &srs->RR_SRV, mStatus_NoError);
 
        switch (srs->state)
        SetRecordRetry(m, &srs->RR_SRV, mStatus_NoError);
 
        switch (srs->state)
@@ -3360,11 +3428,13 @@ mDNSlocal void hndlServiceUpdateReply(mDNS *const m, ServiceRecordSet *srs,  mSt
                                txt->InFlightRData = mDNSNULL;
                                }
                        break;
                                txt->InFlightRData = mDNSNULL;
                                }
                        break;
+               case regState_NoTarget:
+                       // This state is used when using SendServiceDeregistration() when going to sleep -- no further action required
+                       return;
                case regState_FetchingZoneData:
                case regState_Registered:
                case regState_Unregistered:
                case regState_NATMap:
                case regState_FetchingZoneData:
                case regState_Registered:
                case regState_Unregistered:
                case regState_NATMap:
-               case regState_NoTarget:
                case regState_ExtraQueued:
                case regState_NATError:
                        LogMsg("hndlServiceUpdateReply called for service %##s in unexpected state %d with error %ld.  Unlinking.",
                case regState_ExtraQueued:
                case regState_NATError:
                        LogMsg("hndlServiceUpdateReply called for service %##s in unexpected state %d with error %ld.  Unlinking.",
@@ -3457,6 +3527,10 @@ mDNSlocal void hndlRecordUpdateReply(mDNS *m, AuthRecord *rr, mStatus err)
        if (m->mDNS_busy != m->mDNS_reentrancy+1)
                LogMsg("hndlRecordUpdateReply: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
 
        if (m->mDNS_busy != m->mDNS_reentrancy+1)
                LogMsg("hndlRecordUpdateReply: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
 
+       LogOperation("hndlRecordUpdateReply: err %d state %d %s", err, rr->state, ARDisplayString(m, rr));
+
+       if (m->SleepState) return;              // If we just sent a deregister on going to sleep, no further action required
+
        SetRecordRetry(m, rr, mStatus_NoError);
 
        if (rr->state == regState_UpdatePending)
        SetRecordRetry(m, rr, mStatus_NoError);
 
        if (rr->state == regState_UpdatePending)
@@ -3497,8 +3571,8 @@ mDNSlocal void hndlRecordUpdateReply(mDNS *m, AuthRecord *rr, mStatus err)
                {
                if (!err)
                        {
                {
                if (!err)
                        {
-                       rr->state = regState_Registered;
                        if (rr->state == regState_Refresh) InvokeCallback = mDNSfalse;
                        if (rr->state == regState_Refresh) InvokeCallback = mDNSfalse;
+                       rr->state = regState_Registered;
                        }
                else
                        {
                        }
                else
                        {
@@ -3594,6 +3668,9 @@ mDNSexport void uDNS_ReceiveNATPMPPacket(mDNS *m, const mDNSInterfaceID Interfac
                                natTraversalHandlePortMapReply(m, ptr, InterfaceID, PortMapReply->err, PortMapReply->extport, PortMapReply->NATRep_lease);
                }
        else { LogMsg("Received NAT Traversal response with version unknown opcode 0x%X", AddrReply->opcode); return; }
                                natTraversalHandlePortMapReply(m, ptr, InterfaceID, PortMapReply->err, PortMapReply->extport, PortMapReply->NATRep_lease);
                }
        else { LogMsg("Received NAT Traversal response with version unknown opcode 0x%X", AddrReply->opcode); return; }
+
+       // Don't need an SSDP socket if we get a NAT-PMP packet
+       if (m->SSDPSocket) { LogOperation("uDNS_ReceiveNATPMPPacket destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; }
        }
 
 // <rdar://problem/3925163> Shorten DNS-SD queries to avoid NAT bugs
        }
 
 // <rdar://problem/3925163> Shorten DNS-SD queries to avoid NAT bugs
@@ -3647,16 +3724,16 @@ mDNSlocal mDNSBool uDNS_ReceiveTestQuestionResponse(mDNS *const m, DNSMessage *c
        const mDNSAddr *const srcaddr, const mDNSIPPort srcport)
        {
        const mDNSu8 *ptr = msg->data;
        const mDNSAddr *const srcaddr, const mDNSIPPort srcport)
        {
        const mDNSu8 *ptr = msg->data;
-       DNSQuestion q;
+       DNSQuestion pktq;
        DNSServer *s;
        mDNSu32 result = 0;
 
        // 1. Find out if this is an answer to one of our test questions
        if (msg->h.numQuestions != 1) return(mDNSfalse);
        DNSServer *s;
        mDNSu32 result = 0;
 
        // 1. Find out if this is an answer to one of our test questions
        if (msg->h.numQuestions != 1) return(mDNSfalse);
-       ptr = getQuestion(msg, ptr, end, mDNSInterface_Any, &q);
+       ptr = getQuestion(msg, ptr, end, mDNSInterface_Any, &pktq);
        if (!ptr) return(mDNSfalse);
        if (!ptr) return(mDNSfalse);
-       if (q.qtype != kDNSType_PTR || q.qclass != kDNSClass_IN) return(mDNSfalse);
-       if (!SameDomainName(&q.qname, DNSRelayTestQuestion)) return(mDNSfalse);
+       if (pktq.qtype != kDNSType_PTR || pktq.qclass != kDNSClass_IN) return(mDNSfalse);
+       if (!SameDomainName(&pktq.qname, DNSRelayTestQuestion)) return(mDNSfalse);
 
        // 2. If the DNS relay gave us a positive response, then it's got buggy firmware
        // else, if the DNS relay gave us an error or no-answer response, it passed our test
 
        // 2. If the DNS relay gave us a positive response, then it's got buggy firmware
        // else, if the DNS relay gave us an error or no-answer response, it passed our test
@@ -3783,45 +3860,48 @@ mDNSexport void uDNS_ReceiveMsg(mDNS *const m, DNSMessage *const msg, const mDNS
 #pragma mark - Query Routines
 #endif
 
 #pragma mark - Query Routines
 #endif
 
-mDNSexport void sendLLQRefresh(mDNS *m, DNSQuestion *q, mDNSu32 lease)
+mDNSexport void sendLLQRefresh(mDNS *m, DNSQuestion *q)
        {
        mDNSu8 *end;
        LLQOptData llq;
        {
        mDNSu8 *end;
        LLQOptData llq;
-       mStatus err;
 
 
-       // If this is supposed to be a private question and the server dropped the TCP connection,
-       // we don't want to cancel it with a clear-text UDP packet, and and it's not worth the expense of
-       // setting up a new TLS session just to cancel the outstanding LLQ, so we just let it expire naturally
-       if (lease == 0 && q->AuthInfo && !q->tcp) return;
+       if (q->ReqLease)
+               if ((q->state == LLQ_Established && q->ntries >= kLLQ_MAX_TRIES) || q->expire - m->timenow < 0)
+                       {
+                       LogMsg("Unable to refresh LLQ %##s (%s) - will retry in %d minutes", q->qname.c, DNSTypeName(q->qtype), LLQ_POLL_INTERVAL/3600);
+                       StartLLQPolling(m,q);
+                       return;
+                       }
 
 
-       if (q->AuthInfo && !q->tcp)
+       llq.vers     = kLLQ_Vers;
+       llq.llqOp    = kLLQOp_Refresh;
+       llq.err      = q->tcp ? GetLLQEventPort(m, &q->servAddr) : LLQErr_NoError;      // If using TCP tell server what UDP port to send notifications to
+       llq.id       = q->id;
+       llq.llqlease = q->ReqLease;
+
+       InitializeDNSMessage(&m->omsg.h, q->TargetQID, uQueryFlags);
+       end = putLLQ(&m->omsg, m->omsg.data, q, &llq, mDNStrue);
+       if (!end) { LogMsg("sendLLQRefresh: putLLQ failed %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); return; }
+       if (q->AuthInfo)
                {
                {
-               //LogOperation("sendLLQRefresh setting up new TLS session %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-               q->tcp = MakeTCPConn(m, mDNSNULL, mDNSNULL, kTCPSocketFlags_UseTLS, &q->servAddr, q->servPort, q, mDNSNULL, mDNSNULL);
-               q->LastQTime = m->timenow;
-               SetNextQueryTime(m, q);
-               return;
+               DNSDigest_SignMessageHostByteOrder(&m->omsg, &end, q->AuthInfo);
+               if (!end) { LogMsg("sendLLQRefresh: DNSDigest_SignMessage failed %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); return; }
                }
 
                }
 
-       if ((q->state == LLQ_Established && q->ntries >= kLLQ_MAX_TRIES) || q->expire - m->timenow < 0)
+       if (q->AuthInfo && !q->tcp)
                {
                {
-               LogMsg("Unable to refresh LLQ %##s (%s) - will retry in %d minutes", q->qname.c, DNSTypeName(q->qtype), LLQ_POLL_INTERVAL/3600);
-               StartLLQPolling(m,q);
-               return;
+               LogOperation("sendLLQRefresh setting up new TLS session %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
+               q->tcp = MakeTCPConn(m, &m->omsg, end, kTCPSocketFlags_UseTLS, &q->servAddr, q->servPort, q, mDNSNULL, mDNSNULL);
+               }
+       else
+               {
+               mStatus err = mDNSSendDNSMessage(m, &m->omsg, end, mDNSInterface_Any, &q->servAddr, q->servPort, q->tcp ? q->tcp->sock : mDNSNULL, mDNSNULL);
+               if (err)
+                       {
+                       LogMsg("sendLLQRefresh: mDNSSendDNSMessage%s failed: %d", q->tcp ? " (TCP)" : "", err);
+                       if (q->tcp) { DisposeTCPConn(q->tcp); q->tcp = mDNSNULL; }
+                       }
                }
                }
-
-       llq.vers  = kLLQ_Vers;
-       llq.llqOp = kLLQOp_Refresh;
-       llq.err   = q->tcp ? GetLLQEventPort(m, &q->servAddr) : LLQErr_NoError; // If using TCP tell server what UDP port to send notifications to
-       llq.id    = q->id;
-       llq.llqlease = lease;
-
-       InitializeDNSMessage(&m->omsg.h, q->TargetQID, uQueryFlags);
-       end = putLLQ(&m->omsg, m->omsg.data, q, &llq, mDNStrue);
-       if (!end) { LogMsg("ERROR: sendLLQRefresh - putLLQ"); return; }
-
-       err = mDNSSendDNSMessage(m, &m->omsg, end, mDNSInterface_Any, &q->servAddr, q->servPort, q->tcp ? q->tcp->sock : mDNSNULL, q->AuthInfo);
-       if (err) debugf("ERROR: sendLLQRefresh - mDNSSendDNSMessage returned %ld", err);
 
        q->ntries++;
 
 
        q->ntries++;
 
@@ -3844,7 +3924,7 @@ mDNSexport void LLQGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneI
        q->servAddr = zeroAddr;
        q->servPort = zeroIPPort;
 
        q->servAddr = zeroAddr;
        q->servPort = zeroIPPort;
 
-       if (!err && zoneInfo && !mDNSIPPortIsZero(zoneInfo->Port))
+       if (!err && zoneInfo && !mDNSIPPortIsZero(zoneInfo->Port) && !mDNSAddressIsZero(&zoneInfo->Addr))
                {
                q->servAddr = zoneInfo->Addr;
                q->servPort = zoneInfo->Port;
                {
                q->servAddr = zoneInfo->Addr;
                q->servPort = zoneInfo->Port;
@@ -3917,6 +3997,10 @@ mDNSexport void RecordRegistrationGotZoneData(mDNS *const m, mStatus err, const
 
        newRR->nta = mDNSNULL;
 
 
        newRR->nta = mDNSNULL;
 
+       // Start off assuming we're going to use a lease
+       // If we get an error from the server, and the update port as given in the SRV record is 53, then we'll retry without the lease option
+       newRR->uselease = mDNStrue;
+
        // make sure record is still in list (!!!)
        for (ptr = m->ResourceRecords; ptr; ptr = ptr->next) if (ptr == newRR) break;
        if (!ptr) { LogMsg("RecordRegistrationGotZoneData - RR no longer in list.  Discarding."); return; }
        // make sure record is still in list (!!!)
        for (ptr = m->ResourceRecords; ptr; ptr = ptr->next) if (ptr == newRR) break;
        if (!ptr) { LogMsg("RecordRegistrationGotZoneData - RR no longer in list.  Discarding."); return; }
@@ -3959,6 +4043,8 @@ mDNSexport void RecordRegistrationGotZoneData(mDNS *const m, mStatus err, const
                return;
                }
 
                return;
                }
 
+       newRR->ThisAPInterval = 5 * mDNSPlatformOneSecond;              // After doubling, first retry will happen after ten seconds
+
        mDNS_Lock(m);   // SendRecordRegistration expects to be called with the lock held
        SendRecordRegistration(m, newRR);
        mDNS_Unlock(m);
        mDNS_Lock(m);   // SendRecordRegistration expects to be called with the lock held
        SendRecordRegistration(m, newRR);
        mDNS_Unlock(m);
@@ -3988,6 +4074,7 @@ mDNSlocal void SendRecordDeregistration(mDNS *m, AuthRecord *rr)
                }
        else
                {
                }
        else
                {
+               rr->expire = 0;         // Indicate that we have no active registration any more
                if (rr->Private)
                        {
                        LogOperation("SendRecordDeregistration TCP %p %s", rr->tcp, ARDisplayString(m, rr));
                if (rr->Private)
                        {
                        LogOperation("SendRecordDeregistration TCP %p %s", rr->tcp, ARDisplayString(m, rr));
@@ -4201,7 +4288,7 @@ mDNSexport void uDNS_CheckCurrentQuestion(mDNS *const m)
                        {
                        case LLQ_InitialRequest:   startLLQHandshake(m, q); break;
                        case LLQ_SecondaryRequest: sendChallengeResponse(m, q, mDNSNULL); break;
                        {
                        case LLQ_InitialRequest:   startLLQHandshake(m, q); break;
                        case LLQ_SecondaryRequest: sendChallengeResponse(m, q, mDNSNULL); break;
-                       case LLQ_Established:      sendLLQRefresh(m, q, q->origLease); break;
+                       case LLQ_Established:      sendLLQRefresh(m, q); break;
                        case LLQ_Poll:             break;       // Do nothing (handled below)
                        }
                }
                        case LLQ_Poll:             break;       // Do nothing (handled below)
                        }
                }
@@ -4311,6 +4398,7 @@ mDNSlocal void CheckNATMappings(mDNS *m)
                {
                if (m->NATMcastRecvskt) { mDNSPlatformUDPClose(m->NATMcastRecvskt); m->NATMcastRecvskt = mDNSNULL; }
                if (m->NATMcastRecvsk2) { mDNSPlatformUDPClose(m->NATMcastRecvsk2); m->NATMcastRecvsk2 = mDNSNULL; }
                {
                if (m->NATMcastRecvskt) { mDNSPlatformUDPClose(m->NATMcastRecvskt); m->NATMcastRecvskt = mDNSNULL; }
                if (m->NATMcastRecvsk2) { mDNSPlatformUDPClose(m->NATMcastRecvsk2); m->NATMcastRecvsk2 = mDNSNULL; }
+               if (m->SSDPSocket)      { LogOperation("CheckNATMappings destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; }
                }
 
        if (m->NATTraversals)
                }
 
        if (m->NATTraversals)
@@ -4413,13 +4501,20 @@ mDNSlocal mDNSs32 CheckRecordRegistrations(mDNS *m)
 
        for (rr = m->ResourceRecords; rr; rr = rr->next)
                {
 
        for (rr = m->ResourceRecords; rr; rr = rr->next)
                {
-               if (rr->state == regState_Pending || rr->state == regState_DeregPending || rr->state == regState_UpdatePending ||
+               if (rr->state == regState_FetchingZoneData ||
+                       rr->state == regState_Pending || rr->state == regState_DeregPending || rr->state == regState_UpdatePending ||
                        rr->state == regState_DeregDeferred || rr->state == regState_Refresh || rr->state == regState_Registered)
                        {
                        if (rr->LastAPTime + rr->ThisAPInterval - m->timenow < 0)
                                {
                                if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; }
                        rr->state == regState_DeregDeferred || rr->state == regState_Refresh || rr->state == regState_Registered)
                        {
                        if (rr->LastAPTime + rr->ThisAPInterval - m->timenow < 0)
                                {
                                if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; }
-                               if (rr->state == regState_DeregPending) SendRecordDeregistration(m, rr);
+                               if (rr->state == regState_FetchingZoneData)
+                                       {
+                                       if (rr->nta) CancelGetZoneData(m, rr->nta);
+                                       rr->nta = StartGetZoneData(m, rr->resrec.name, ZoneServiceUpdate, RecordRegistrationGotZoneData, rr);
+                                       SetRecordRetry(m, rr, mStatus_NoError);
+                                       }
+                               else if (rr->state == regState_DeregPending) SendRecordDeregistration(m, rr);
                                else SendRecordRegistration(m, rr);
                                }
                        if (nextevent - (rr->LastAPTime + rr->ThisAPInterval) > 0)
                                else SendRecordRegistration(m, rr);
                                }
                        if (nextevent - (rr->LastAPTime + rr->ThisAPInterval) > 0)
@@ -4442,13 +4537,20 @@ mDNSlocal mDNSs32 CheckServiceRegistrations(mDNS *m)
                {
                ServiceRecordSet *srs = CurrentServiceRecordSet;
                CurrentServiceRecordSet = CurrentServiceRecordSet->uDNS_next;
                {
                ServiceRecordSet *srs = CurrentServiceRecordSet;
                CurrentServiceRecordSet = CurrentServiceRecordSet->uDNS_next;
-               if (srs->state == regState_Pending || srs->state == regState_DeregPending  || srs->state == regState_DeregDeferred ||
+               if (srs->state == regState_FetchingZoneData ||
+                       srs->state == regState_Pending || srs->state == regState_DeregPending  || srs->state == regState_DeregDeferred ||
                        srs->state == regState_Refresh || srs->state == regState_UpdatePending || srs->state == regState_Registered)
                        {
                        if (srs->RR_SRV.LastAPTime + srs->RR_SRV.ThisAPInterval - m->timenow <= 0)
                                {
                                if (srs->tcp) { DisposeTCPConn(srs->tcp); srs->tcp = mDNSNULL; }
                        srs->state == regState_Refresh || srs->state == regState_UpdatePending || srs->state == regState_Registered)
                        {
                        if (srs->RR_SRV.LastAPTime + srs->RR_SRV.ThisAPInterval - m->timenow <= 0)
                                {
                                if (srs->tcp) { DisposeTCPConn(srs->tcp); srs->tcp = mDNSNULL; }
-                               if (srs->state == regState_DeregPending) SendServiceDeregistration(m, srs);
+                               if (srs->state == regState_FetchingZoneData)
+                                       {
+                                       if (srs->nta) CancelGetZoneData(m, srs->nta);
+                                       srs->nta = StartGetZoneData(m, srs->RR_SRV.resrec.name, ZoneServiceUpdate, ServiceRegistrationGotZoneData, srs);
+                                       SetRecordRetry(m, &srs->RR_SRV, mStatus_NoError);
+                                       }
+                               else if (srs->state == regState_DeregPending) SendServiceDeregistration(m, srs);
                                else SendServiceRegistration(m, srs);
                                }
                        if (nextevent - (srs->RR_SRV.LastAPTime + srs->RR_SRV.ThisAPInterval) > 0)
                                else SendServiceRegistration(m, srs);
                                }
                        if (nextevent - (srs->RR_SRV.LastAPTime + srs->RR_SRV.ThisAPInterval) > 0)
@@ -4491,36 +4593,17 @@ mDNSexport void uDNS_Execute(mDNS *const m)
 
 mDNSexport void SleepRecordRegistrations(mDNS *m)
        {
 
 mDNSexport void SleepRecordRegistrations(mDNS *m)
        {
-       AuthRecord *rr = m->ResourceRecords;
-
-       while (rr)
-               {
-               if (rr->state == regState_Registered ||
-                       rr->state == regState_Refresh)
-                       {
-                       SendRecordDeregistration(m, rr);
-                       rr->state = regState_Refresh;
-                       rr->LastAPTime = m->timenow;
-                       rr->ThisAPInterval = 300 * mDNSPlatformOneSecond;
-                       }
-               rr = rr->next;
-               }
-       }
-
-mDNSlocal void WakeRecordRegistrations(mDNS *m)
-       {
-       AuthRecord *rr = m->ResourceRecords;
-
-       while (rr)
-               {
-               if (rr->state == regState_Refresh)
-                       {
-                       // trigger slightly delayed refresh (we usually get this message before kernel is ready to send packets)
-                       rr->LastAPTime = m->timenow;
-                       rr->ThisAPInterval = INIT_UCAST_POLL_INTERVAL;
-                       }
-               rr = rr->next;
-               }
+       AuthRecord *rr;
+       for (rr = m->ResourceRecords; rr; rr=rr->next)
+               if (AuthRecord_uDNS(rr))
+                       if (rr->state == regState_Registered ||
+                               rr->state == regState_Refresh)
+                               {
+                               SendRecordDeregistration(m, rr);
+                               rr->state = regState_Refresh;
+                               rr->LastAPTime = m->timenow;
+                               rr->ThisAPInterval = 300 * mDNSPlatformOneSecond;
+                               }
        }
 
 mDNSexport void SleepServiceRegistrations(mDNS *m)
        }
 
 mDNSexport void SleepServiceRegistrations(mDNS *m)
@@ -4528,6 +4611,7 @@ mDNSexport void SleepServiceRegistrations(mDNS *m)
        ServiceRecordSet *srs = m->ServiceRegistrations;
        while (srs)
                {
        ServiceRecordSet *srs = m->ServiceRegistrations;
        while (srs)
                {
+               LogOperation("SleepServiceRegistrations: state %d %s", srs->state, ARDisplayString(m, &srs->RR_SRV));
                if (srs->nta) { CancelGetZoneData(m, srs->nta); srs->nta = mDNSNULL; }
 
                if (srs->NATinfo.clientContext)
                if (srs->nta) { CancelGetZoneData(m, srs->nta); srs->nta = mDNSNULL; }
 
                if (srs->NATinfo.clientContext)
@@ -4549,29 +4633,13 @@ mDNSexport void SleepServiceRegistrations(mDNS *m)
                        }
 
                if (srs->state == regState_Registered || srs->state == regState_Refresh)
                        }
 
                if (srs->state == regState_Registered || srs->state == regState_Refresh)
-                       {
-                       mDNSOpaque16 origid = srs->id;
-                       srs->state = regState_DeregPending;     // state expected by SendDereg()
                        SendServiceDeregistration(m, srs);
                        SendServiceDeregistration(m, srs);
-                       srs->id = origid;
-                       srs->state = regState_NoTarget; // when we wake, we'll re-register (and optionally nat-map) once our address record completes
-                       srs->RR_SRV.resrec.rdata->u.srv.target.c[0] = 0;
-                       }
-               srs = srs->uDNS_next;
-               }
-       }
 
 
-mDNSlocal void WakeServiceRegistrations(mDNS *m)
-       {
-       ServiceRecordSet *srs = m->ServiceRegistrations;
-       while (srs)
-               {
-               if (srs->state == regState_Refresh)
-                       {
-                       // trigger slightly delayed refresh (we usually get this message before kernel is ready to send packets)
-                       srs->RR_SRV.LastAPTime = m->timenow;
-                       srs->RR_SRV.ThisAPInterval = INIT_UCAST_POLL_INTERVAL;
-                       }
+               srs->state = regState_NoTarget; // when we wake, we'll re-register (and optionally nat-map) once our address record completes
+               srs->RR_SRV.resrec.rdata->u.srv.target.c[0] = 0;
+               srs->SRSUpdateServer = zeroAddr;                // This will cause UpdateSRV to do a new StartGetZoneData
+               srs->RR_SRV.ThisAPInterval = 5 * mDNSPlatformOneSecond;         // After doubling, first retry will happen after ten seconds
+
                srs = srs->uDNS_next;
                }
        }
                srs = srs->uDNS_next;
                }
        }
@@ -4777,12 +4845,6 @@ mDNSexport mStatus uDNS_RegisterSearchDomains(mDNS *const m)
 // 6) client calls to enumerate domains now go over LocalOnly interface
 //    (!!!KRS may add outgoing interface in addition)
 
 // 6) client calls to enumerate domains now go over LocalOnly interface
 //    (!!!KRS may add outgoing interface in addition)
 
-mDNSexport void uDNS_Wake(mDNS *const m)
-       {
-       WakeServiceRegistrations(m);
-       WakeRecordRegistrations(m);
-       }
-
 struct CompileTimeAssertionChecks_uDNS
        {
        // Check our structures are reasonable sizes. Including overly-large buffers, or embedding
 struct CompileTimeAssertionChecks_uDNS
        {
        // Check our structures are reasonable sizes. Including overly-large buffers, or embedding
index c61e05c444cd9083d44d4baf6ce217d6f7920fe0..2676a2c19f130990141fd1954247b33cd31bb1b9 100755 (executable)
     Change History (most recent first):
 
 $Log: uDNS.h,v $
     Change History (most recent first):
 
 $Log: uDNS.h,v $
+Revision 1.90  2007/12/22 02:25:30  cheshire
+<rdar://problem/5661128> Records and Services sometimes not re-registering on wake from sleep
+
+Revision 1.89  2007/12/15 01:12:27  cheshire
+<rdar://problem/5526796> Need to remove active LLQs from server upon question cancellation, on sleep, and on shutdown
+
 Revision 1.88  2007/10/25 20:06:13  cheshire
 Don't try to do SOA queries using private DNS (TLS over TCP) queries
 
 Revision 1.88  2007/10/25 20:06:13  cheshire
 Don't try to do SOA queries using private DNS (TLS over TCP) queries
 
@@ -231,9 +237,7 @@ Revision 1.33  2006/07/05 22:53:28  cheshire
 
 extern void LLQGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneInfo);
 extern void startLLQHandshake(mDNS *m, DNSQuestion *q);
 
 extern void LLQGotZoneData(mDNS *const m, mStatus err, const ZoneData *zoneInfo);
 extern void startLLQHandshake(mDNS *m, DNSQuestion *q);
-extern void sendLLQRefresh(mDNS *m, DNSQuestion *q, mDNSu32 lease);
-
-extern void uDNS_Wake(mDNS *const m);
+extern void sendLLQRefresh(mDNS *m, DNSQuestion *q);
 
 extern void SleepServiceRegistrations(mDNS *m);
 extern void SleepRecordRegistrations(mDNS *m);
 
 extern void SleepServiceRegistrations(mDNS *m);
 extern void SleepRecordRegistrations(mDNS *m);
index 2be3dd4aff65712d037fa7cc66347571446203de..b1a23b6c3e09315dc4427ef72bf923bc8bfb6ea1 100644 (file)
@@ -17,6 +17,9 @@
     Change History (most recent first):
 
 $Log: LegacyNATTraversal.c,v $
     Change History (most recent first):
 
 $Log: LegacyNATTraversal.c,v $
+Revision 1.45  2007/12/06 00:22:27  mcguire
+<rdar://problem/5604567> BTMM: Doesn't work with Linksys WAG300N 1.01.06 (sending from 1026/udp)
+
 Revision 1.44  2007/11/02 20:45:40  cheshire
 Don't log "connection failed" in customer builds
 
 Revision 1.44  2007/11/02 20:45:40  cheshire
 Don't log "connection failed" in customer builds
 
@@ -806,6 +809,9 @@ mDNSexport void LNT_ConfigureRouterInfo(mDNS *m, const mDNSInterfaceID Interface
 
        if (ptr == mDNSNULL || ptr == end) return;      // not a valid message
        LogOperation("Router port %d, URL set to [%s]...", mDNSVal16(m->UPnPRouterPort), m->UPnPRouterURL);
 
        if (ptr == mDNSNULL || ptr == end) return;      // not a valid message
        LogOperation("Router port %d, URL set to [%s]...", mDNSVal16(m->UPnPRouterPort), m->UPnPRouterURL);
+       
+       // Don't need the SSDP socket anymore
+       if (m->SSDPSocket) { LogOperation("LNT_ConfigureRouterInfo destroying SSDPSocket %p", &m->SSDPSocket); mDNSPlatformUDPClose(m->SSDPSocket); m->SSDPSocket = mDNSNULL; }
 
        // now send message to get the device description
        GetDeviceDescription(m, &m->tcpDeviceInfo);
 
        // now send message to get the device description
        GetDeviceDescription(m, &m->tcpDeviceInfo);
@@ -823,7 +829,10 @@ mDNSexport void LNT_SendDiscoveryMsg(mDNS *m)
        LogOperation("LNT_SendDiscoveryMsg Router %.4a Current External Address %.4a", &m->Router.ip.v4, &m->ExternalAddress);
 
        if (!mDNSIPv4AddressIsZero(m->Router.ip.v4) && mDNSIPv4AddressIsZero(m->ExternalAddress))
        LogOperation("LNT_SendDiscoveryMsg Router %.4a Current External Address %.4a", &m->Router.ip.v4, &m->ExternalAddress);
 
        if (!mDNSIPv4AddressIsZero(m->Router.ip.v4) && mDNSIPv4AddressIsZero(m->ExternalAddress))
+               {
+               if (!m->SSDPSocket) { m->SSDPSocket = mDNSPlatformUDPSocket(m, zeroIPPort); LogOperation("LNT_SendDiscoveryMsg created SSDPSocket %p", &m->SSDPSocket); }
                mDNSPlatformSendUDP(m, msg, msg + sizeof(msg) - 1, 0, &m->Router, SSDPPort);
                mDNSPlatformSendUDP(m, msg, msg + sizeof(msg) - 1, 0, &m->Router, SSDPPort);
+               }
        }
 
 #endif /* _LEGACY_NAT_TRAVERSAL_ */
        }
 
 #endif /* _LEGACY_NAT_TRAVERSAL_ */
index 8e666109e9f595ff22cc0d04e7e39f6b2c68065f..412da6d315bd84cb55ed944e0742478f78cdef5e 100644 (file)
@@ -43,6 +43,9 @@
     Change History (most recent first):
 
 $Log: DNSServiceDiscoveryPref.m,v $
     Change History (most recent first):
 
 $Log: DNSServiceDiscoveryPref.m,v $
+Revision 1.11  2007/11/30 23:42:09  cheshire
+Fixed compile warning: declaration of 'index' shadows a global declaration
+
 Revision 1.10  2007/09/18 19:09:02  cheshire
 <rdar://problem/5489549> mDNSResponderHelper (and other binaries) missing SCCS version strings
 
 Revision 1.10  2007/09/18 19:09:02  cheshire
 <rdar://problem/5489549> mDNSResponderHelper (and other binaries) missing SCCS version strings
 
@@ -777,11 +780,11 @@ MyDNSServiceAddServiceToRunLoop(MyDNSServiceState * query)
 }
 
 
 }
 
 
-- (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(int)index
+- (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(int)ind
 {
     NSString *domain = nil;
 {
     NSString *domain = nil;
-    if      ([aComboBox isEqualTo:browseDomainsComboBox]) domain = [browseDataSource objectAtIndex:index];
-    else if ([aComboBox isEqualTo:regDomainsComboBox])    domain = [registrationDataSource objectAtIndex:index];
+    if      ([aComboBox isEqualTo:browseDomainsComboBox]) domain = [browseDataSource objectAtIndex:ind];
+    else if ([aComboBox isEqualTo:regDomainsComboBox])    domain = [registrationDataSource objectAtIndex:ind];
     return domain;
 }
 
     return domain;
 }
 
index 13552f6c5b933dde123b62ead8852ff066e463ce..01f09c5f0a0868ec9aea39d3f06a86ca285d3d36 100644 (file)
@@ -43,6 +43,9 @@
     Change History (most recent first):
 
 $Log: PrivilegedOperations.c,v $
     Change History (most recent first):
 
 $Log: PrivilegedOperations.c,v $
+Revision 1.8  2007/11/30 23:42:33  cheshire
+Fixed compile warning: declaration of 'status' shadows a previous local
+
 Revision 1.7  2007/02/09 00:39:06  cheshire
 Fix compile warnings
 
 Revision 1.7  2007/02/09 00:39:06  cheshire
 Fix compile warnings
 
@@ -146,7 +149,6 @@ OSStatus EnsureToolInstalled(void)
                        char *installerargs[] = { toolSourcePath, NULL };
                        err = AuthorizationExecuteWithPrivileges(authRef, toolInstallerPath, 0, installerargs, (FILE**) NULL);
                        if (err == noErr) {
                        char *installerargs[] = { toolSourcePath, NULL };
                        err = AuthorizationExecuteWithPrivileges(authRef, toolInstallerPath, 0, installerargs, (FILE**) NULL);
                        if (err == noErr) {
-                               int status;
                                int pid = wait(&status);
                                if (pid > 0 && WIFEXITED(status)) {
                                        err = WEXITSTATUS(status);
                                int pid = wait(&status);
                                if (pid > 0 && WIFEXITED(status)) {
                                        err = WEXITSTATUS(status);
index 3f2fbbf5e78af422f755c849c2332df954cfb9db..f415180dbfc1e3e76357cadcf30b616d34444a67 100644 (file)
@@ -45,6 +45,9 @@
     Change History (most recent first):
 
 $Log: ddnswriteconfig.m,v $
     Change History (most recent first):
 
 $Log: ddnswriteconfig.m,v $
+Revision 1.10  2007/11/30 23:43:04  cheshire
+Fixed compile warning: declaration of 'access' shadows a global declaration
+
 Revision 1.9  2007/09/18 19:09:02  cheshire
 <rdar://problem/5489549> mDNSResponderHelper (and other binaries) missing SCCS version strings
 
 Revision 1.9  2007/09/18 19:09:02  cheshire
 <rdar://problem/5489549> mDNSResponderHelper (and other binaries) missing SCCS version strings
 
@@ -313,14 +316,14 @@ MyMakeUidAccess(uid_t uid)
                0
                };
 
                0
                };
 
-       SecAccessRef access = NULL;
-       (void) SecAccessCreateFromOwnerAndACL(&owner, 1, &acls, &access);
-       return access;
+       SecAccessRef a = NULL;
+       (void) SecAccessCreateFromOwnerAndACL(&owner, 1, &acls, &a);
+       return a;
 }
 
 
 static OSStatus
 }
 
 
 static OSStatus
-MyAddDynamicDNSPassword(SecKeychainRef keychain, SecAccessRef access, UInt32 serviceNameLength, const char *serviceName,
+MyAddDynamicDNSPassword(SecKeychainRef keychain, SecAccessRef a, UInt32 serviceNameLength, const char *serviceName,
     UInt32 accountNameLength, const char *accountName, UInt32 passwordLength, const void *passwordData)
 {
        char * description       = DYNDNS_KEYCHAIN_DESCRIPTION;
     UInt32 accountNameLength, const char *accountName, UInt32 passwordLength, const void *passwordData)
 {
        char * description       = DYNDNS_KEYCHAIN_DESCRIPTION;
@@ -340,7 +343,7 @@ MyAddDynamicDNSPassword(SecKeychainRef keychain, SecAccessRef access, UInt32 ser
                                      { kSecCreatorItemAttr,         creatorLength, (UInt32 *)&creator    } };
        SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
 
                                      { kSecCreatorItemAttr,         creatorLength, (UInt32 *)&creator    } };
        SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
 
-       err = SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass, &attributes, passwordLength, passwordData, keychain, access, NULL);
+       err = SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass, &attributes, passwordLength, passwordData, keychain, a, NULL);
     return err;
 }
 
     return err;
 }
 
index c44edc8bd13abaad157c3a4b7861f7061f669aae..6497498b307f0e0a72952259809ec86f9afff651 100644 (file)
@@ -30,6 +30,9 @@
        Change History (most recent first):
 
 $Log: SamplemDNSClient.c,v $
        Change History (most recent first):
 
 $Log: SamplemDNSClient.c,v $
+Revision 1.54  2007/11/30 23:39:55  cheshire
+Fixed compile warning: declaration of 'client' shadows a global declaration
+
 Revision 1.53  2007/09/18 19:09:02  cheshire
 <rdar://problem/5489549> mDNSResponderHelper (and other binaries) missing SCCS version strings
 
 Revision 1.53  2007/09/18 19:09:02  cheshire
 <rdar://problem/5489549> mDNSResponderHelper (and other binaries) missing SCCS version strings
 
@@ -111,9 +114,9 @@ static void MyHandleMachMessage(CFMachPortRef port, void *msg, CFIndex size, voi
        DNSServiceDiscovery_handleReply(msg);
        }
 
        DNSServiceDiscovery_handleReply(msg);
        }
 
-static int AddDNSServiceClientToRunLoop(dns_service_discovery_ref client)
+static int AddDNSServiceClientToRunLoop(dns_service_discovery_ref c)
        {
        {
-       mach_port_t port = DNSServiceDiscoveryMachPort(client);
+       mach_port_t port = DNSServiceDiscoveryMachPort(c);
        if (!port)
                return(-1);
        else
        if (!port)
                return(-1);
        else
@@ -316,7 +319,7 @@ static void reg_reply(DNSServiceRegistrationReplyErrorType errorCode, void *cont
 int main(int argc, char **argv)
        {
        const char *progname = strrchr(argv[0], '/') ? strrchr(argv[0], '/') + 1 : argv[0];
 int main(int argc, char **argv)
        {
        const char *progname = strrchr(argv[0], '/') ? strrchr(argv[0], '/') + 1 : argv[0];
-       char *dom;
+       char *d;
        setlinebuf(stdout);                             // Want to see lines as they appear, not block buffered
 
        if (argc < 2) goto Fail;                // Minimum command line is the command name and one argument
        setlinebuf(stdout);                             // Want to see lines as they appear, not block buffered
 
        if (argc < 2) goto Fail;                // Minimum command line is the command name and one argument
@@ -334,17 +337,17 @@ int main(int argc, char **argv)
                                        break;
 
                case 'B':       if (argc < optind+1) goto Fail;
                                        break;
 
                case 'B':       if (argc < optind+1) goto Fail;
-                                       dom = (argc < optind+2) ? "" : argv[optind+1];  // Missing domain argument is the same as empty string i.e. use system default(s)
-                                       if (dom[0] == '.' && dom[1] == 0) dom[0] = 0;   // We allow '.' on the command line as a synonym for empty string
-                                       printf("Browsing for %s%s\n", argv[optind+0], dom);
-                                       client = DNSServiceBrowserCreate(argv[optind+0], dom, browse_reply, nil);
+                                       d = (argc < optind+2) ? "" : argv[optind+1];    // Missing domain argument is the same as empty string i.e. use system default(s)
+                                       if (d[0] == '.' && d[1] == 0) d[0] = 0; // We allow '.' on the command line as a synonym for empty string
+                                       printf("Browsing for %s%s\n", argv[optind+0], d);
+                                       client = DNSServiceBrowserCreate(argv[optind+0], d, browse_reply, nil);
                                        break;
 
                case 'L':       if (argc < optind+2) goto Fail;
                                        break;
 
                case 'L':       if (argc < optind+2) goto Fail;
-                                       dom = (argc < optind+3) ? "" : argv[optind+2];
-                                       if (dom[0] == '.' && dom[1] == 0) dom = "local";   // We allow '.' on the command line as a synonym for "local"
-                                       printf("Lookup %s.%s%s\n", argv[optind+0], argv[optind+1], dom);
-                                       client = DNSServiceResolverResolve(argv[optind+0], argv[optind+1], dom, resolve_reply, nil);
+                                       d = (argc < optind+3) ? "" : argv[optind+2];
+                                       if (d[0] == '.' && d[1] == 0) d = "local";   // We allow '.' on the command line as a synonym for "local"
+                                       printf("Lookup %s.%s%s\n", argv[optind+0], argv[optind+1], d);
+                                       client = DNSServiceResolverResolve(argv[optind+0], argv[optind+1], d, resolve_reply, nil);
                                        break;
 
                case 'R':       if (argc < optind+4) goto Fail;
                                        break;
 
                case 'R':       if (argc < optind+4) goto Fail;
index e7b7b9d0232b7ae72cd38068321e8e56d5478870..8acaf295b776a647fc5ea1539660b6bde4e1f297 100644 (file)
     Change History (most recent first):
 
 $Log: daemon.c,v $
     Change History (most recent first):
 
 $Log: daemon.c,v $
+Revision 1.356  2007/12/18 00:28:56  cheshire
+<rdar://problem/5526800> BTMM: Need to deregister records and services on shutdown/sleep
+Error in ReadyForSleep() logic -- missing "not" in "!mDNSOpaque16IsZero(q->TargetQID)"
+
+Revision 1.355  2007/12/17 22:29:22  cheshire
+<rdar://problem/5526800> BTMM: Need to deregister records and services on shutdown/sleep
+Log message indicating when we make IOAllowPowerChange call; make sure nextTimerEvent is set appropriately
+
+Revision 1.354  2007/12/15 01:12:28  cheshire
+<rdar://problem/5526796> Need to remove active LLQs from server upon question cancellation, on sleep, and on shutdown
+
+Revision 1.353  2007/12/14 19:14:02  cheshire
+Added (commented out) code for testing sleep/wake
+
+Revision 1.352  2007/12/14 00:58:29  cheshire
+<rdar://problem/5526800> BTMM: Need to deregister records and services on shutdown/sleep
+Additional fixes: When going to sleep, mDNSResponder needs to postpone sleep
+until TLS/TCP deregistrations have completed (up to five seconds maximum)
+
+Revision 1.351  2007/12/12 21:34:18  cheshire
+Now that <rdar://problem/5124399> "Not getting Keychain events" is apparently fixed,
+it makes sense to reduce our workaround retry count from 5 to 2 retries. Once we've
+confirmed that the bug is definitely fixed we'll remove the workaround altogether.
+
+Revision 1.350  2007/12/07 00:45:58  cheshire
+<rdar://problem/5526800> BTMM: Need to clean up registrations on shutdown
+
+Revision 1.349  2007/12/04 22:00:54  cheshire
+Fixed mistake in comment
+
+Revision 1.348  2007/12/01 00:27:43  cheshire
+Fixed compile warning: declaration of 'r' shadows a previous local
+
 Revision 1.347  2007/11/02 22:00:13  cheshire
 <rdar://problem/5575583> BTMM: Work around keychain notification bug <rdar://problem/5124399>
 Need to hold the lock while calling SetDomainSecrets
 Revision 1.347  2007/11/02 22:00:13  cheshire
 <rdar://problem/5575583> BTMM: Work around keychain notification bug <rdar://problem/5124399>
 Need to hold the lock while calling SetDomainSecrets
@@ -709,9 +742,9 @@ mDNSlocal void AbortClient(mach_port_t ClientMachPort, void *m)
                        }
                while (x->results)
                        {
                        }
                while (x->results)
                        {
-                       DNSServiceBrowserResult *r = x->results;
+                       DNSServiceBrowserResult *t = x->results;
                        x->results = x->results->next;
                        x->results = x->results->next;
-                       freeL("DNSServiceBrowserResult", r);
+                       freeL("DNSServiceBrowserResult", t);
                        }
                freeL("DNSServiceBrowser", x);
                return;
                        }
                freeL("DNSServiceBrowser", x);
                return;
@@ -999,10 +1032,10 @@ mDNSexport void machserver_automatic_browse_domain_changed(const domainname *d,
                                        {
                                        if (SameDomainName(&(*q)->domain, d))
                                                {
                                        {
                                        if (SameDomainName(&(*q)->domain, d))
                                                {
-                                               DNSServiceBrowserQuestion *remove = *q;
+                                               DNSServiceBrowserQuestion *rem = *q;
                                                *q = (*q)->next;
                                                *q = (*q)->next;
-                                               mDNS_StopQueryWithRemoves(&mDNSStorage, &remove->q);
-                                               freeL("DNSServiceBrowserQuestion", remove );
+                                               mDNS_StopQueryWithRemoves(&mDNSStorage, &rem->q);
+                                               freeL("DNSServiceBrowserQuestion", rem);
                                                return;
                                                }
                                        q = &(*q)->next;
                                                return;
                                                }
                                        q = &(*q)->next;
@@ -1111,11 +1144,11 @@ mDNSlocal void FoundInstanceInfo(mDNS *const m, ServiceInfoQuery *query)
 
        if (ifx && ifx->ifinfo.ip.type == mDNSAddrType_IPv4)
                {
 
        if (ifx && ifx->ifinfo.ip.type == mDNSAddrType_IPv4)
                {
-               struct sockaddr_in *sin = (struct sockaddr_in*)&interface;
-               sin->sin_len         = sizeof(*sin);
-               sin->sin_family      = AF_INET;
-               sin->sin_port        = 0;
-               sin->sin_addr.s_addr = ifx->ifinfo.ip.ip.v4.NotAnInteger;
+               struct sockaddr_in *s = (struct sockaddr_in*)&interface;
+               s->sin_len         = sizeof(*s);
+               s->sin_family      = AF_INET;
+               s->sin_port        = 0;
+               s->sin_addr.s_addr = ifx->ifinfo.ip.ip.v4.NotAnInteger;
                }
        else if (ifx && ifx->ifinfo.ip.type == mDNSAddrType_IPv6)
                {
                }
        else if (ifx && ifx->ifinfo.ip.type == mDNSAddrType_IPv6)
                {
@@ -1130,11 +1163,11 @@ mDNSlocal void FoundInstanceInfo(mDNS *const m, ServiceInfoQuery *query)
 
        if (query->info->ip.type == mDNSAddrType_IPv4)
                {
 
        if (query->info->ip.type == mDNSAddrType_IPv4)
                {
-               struct sockaddr_in *sin = (struct sockaddr_in*)&address;
-               sin->sin_len           = sizeof(*sin);
-               sin->sin_family        = AF_INET;
-               sin->sin_port          = query->info->port.NotAnInteger;
-               sin->sin_addr.s_addr   = query->info->ip.ip.v4.NotAnInteger;
+               struct sockaddr_in *s = (struct sockaddr_in*)&address;
+               s->sin_len         = sizeof(*s);
+               s->sin_family      = AF_INET;
+               s->sin_port        = query->info->port.NotAnInteger;
+               s->sin_addr.s_addr = query->info->ip.ip.v4.NotAnInteger;
                }
        else
                {
                }
        else
                {
@@ -1474,9 +1507,9 @@ mDNSexport kern_return_t provide_DNSServiceRegistrationCreate_rpc(mach_port_t un
 
        if (x->DefaultDomain)
                {
 
        if (x->DefaultDomain)
                {
-               DNameListElem *ptr;
-               for (ptr = AutoRegistrationDomains; ptr; ptr = ptr->next)
-                       AddServiceInstance(x, &ptr->name);
+               DNameListElem *p;
+               for (p = AutoRegistrationDomains; p; p = p->next)
+                       AddServiceInstance(x, &p->name);
                }
 
        // Succeeded: Wrap up and return
                }
 
        // Succeeded: Wrap up and return
@@ -1909,9 +1942,9 @@ mDNSlocal kern_return_t destroyBootstrapService()
        return bootstrap_register(server_priv_port, (char*)kmDNSBootstrapName, MACH_PORT_NULL);
        }
 
        return bootstrap_register(server_priv_port, (char*)kmDNSBootstrapName, MACH_PORT_NULL);
        }
 
-mDNSlocal void ExitCallback(int signal)
+mDNSlocal void ExitCallback(int sig)
        {
        {
-       (void)signal; // Unused
+       (void)sig; // Unused
        LogMsgIdent(mDNSResponderVersionString, "stopping");
 
        debugf("ExitCallback");
        LogMsgIdent(mDNSResponderVersionString, "stopping");
 
        debugf("ExitCallback");
@@ -1928,27 +1961,27 @@ mDNSlocal void ExitCallback(int signal)
        while (DNSServiceRegistrationList)
                AbortClient(DNSServiceRegistrationList     ->ClientMachPort, DNSServiceRegistrationList);
 
        while (DNSServiceRegistrationList)
                AbortClient(DNSServiceRegistrationList     ->ClientMachPort, DNSServiceRegistrationList);
 
-       debugf("ExitCallback: mDNS_Close");
-       mDNS_Close(&mDNSStorage);
        if (udsserver_exit(launchd_fd) < 0) LogMsg("ExitCallback: udsserver_exit failed");
        if (udsserver_exit(launchd_fd) < 0) LogMsg("ExitCallback: udsserver_exit failed");
-       exit(0);
+
+       debugf("ExitCallback: mDNS_StartExit");
+       mDNS_StartExit(&mDNSStorage);
        }
 
 // Send a mach_msg to ourselves (since that is signal safe) telling us to cleanup and exit
        }
 
 // Send a mach_msg to ourselves (since that is signal safe) telling us to cleanup and exit
-mDNSlocal void HandleSIG(int signal)
+mDNSlocal void HandleSIG(int sig)
        {
        debugf(" ");
        {
        debugf(" ");
-       debugf("HandleSIG %d", signal);
+       debugf("HandleSIG %d", sig);
        mach_msg_header_t header;
        header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
        header.msgh_remote_port = signal_port;
        header.msgh_local_port = MACH_PORT_NULL;
        header.msgh_size = sizeof(header);
        mach_msg_header_t header;
        header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
        header.msgh_remote_port = signal_port;
        header.msgh_local_port = MACH_PORT_NULL;
        header.msgh_size = sizeof(header);
-       header.msgh_id = signal;
+       header.msgh_id = sig;
        if (mach_msg_send(&header) != MACH_MSG_SUCCESS)
                {
        if (mach_msg_send(&header) != MACH_MSG_SUCCESS)
                {
-               LogMsg("HandleSIG %d: mach_msg_send failed", signal);
-               if (signal == SIGTERM || signal == SIGINT) exit(-1);
+               LogMsg("HandleSIG %d: mach_msg_send failed", sig);
+               if (sig == SIGTERM || sig == SIGINT) exit(-1);
                }
        }
 
                }
        }
 
@@ -2068,7 +2101,8 @@ mDNSlocal void SignalCallback(CFMachPortRef port, void *msg, CFIndex size, void
                case SIGINT:
                case SIGTERM:   ExitCallback(msg_header->msgh_id); break;
                case SIGINFO:   INFOCallback(); break;
                case SIGINT:
                case SIGTERM:   ExitCallback(msg_header->msgh_id); break;
                case SIGINFO:   INFOCallback(); break;
-               case SIGUSR1:   LogMsg("SIGUSR1: Simulate Network Configuration Change Event");
+               case SIGUSR1:   // mDNSCoreMachineSleep(m, !m->SleepState); break;
+                                               LogMsg("SIGUSR1: Simulate Network Configuration Change Event");
                                                mDNSMacOSXNetworkChanged(m);
 
                                                // Simulate KeychainChanged
                                                mDNSMacOSXNetworkChanged(m);
 
                                                // Simulate KeychainChanged
@@ -2156,9 +2190,9 @@ mDNSlocal mDNSs32 mDNSDaemonIdle(mDNS *const m)
        // See <rdar://problem/5124399> Not getting Keychain Changed events when enabling BTMM
        if (m->p->KeyChainBugTimer && now - m->p->KeyChainBugTimer >= 0)
                {
        // See <rdar://problem/5124399> Not getting Keychain Changed events when enabling BTMM
        if (m->p->KeyChainBugTimer && now - m->p->KeyChainBugTimer >= 0)
                {
-               m->p->KeyChainBugTimer = NonZeroTime(now + m->p->KeyChainBugInterval);
                m->p->KeyChainBugInterval *= 2;
                m->p->KeyChainBugInterval *= 2;
-               if (m->p->KeyChainBugInterval > 16 * mDNSPlatformOneSecond) m->p->KeyChainBugTimer = 0;
+               m->p->KeyChainBugTimer = NonZeroTime(now + m->p->KeyChainBugInterval);
+               if (m->p->KeyChainBugInterval > 2 * mDNSPlatformOneSecond) m->p->KeyChainBugTimer = 0;
                mDNS_Lock(m);
                SetDomainSecrets(m);
                mDNS_Unlock(m);
                mDNS_Lock(m);
                SetDomainSecrets(m);
                mDNS_Unlock(m);
@@ -2263,7 +2297,7 @@ mDNSlocal void ShowTaskSchedulingError(mDNS *const m)
 
        LogMsg("Task Scheduling Error: Continuously busy for more than a second");
        
 
        LogMsg("Task Scheduling Error: Continuously busy for more than a second");
        
-       // NOTE: To accurately diagnose *why* we're busy, the debugging code here to show needs to mirror the logic in GetNextScheduledEvent
+       // NOTE: To accurately diagnose *why* we're busy, the debugging code here needs to mirror the logic in GetNextScheduledEvent
 
        if (m->NewQuestions && (!m->NewQuestions->DelayAnswering || m->timenow - m->NewQuestions->DelayAnswering >= 0))
                LogMsg("Task Scheduling Error: NewQuestion %##s (%s)",
 
        if (m->NewQuestions && (!m->NewQuestions->DelayAnswering || m->timenow - m->NewQuestions->DelayAnswering >= 0))
                LogMsg("Task Scheduling Error: NewQuestion %##s (%s)",
@@ -2293,12 +2327,33 @@ mDNSlocal void ShowTaskSchedulingError(mDNS *const m)
        mDNS_Unlock(&mDNSStorage);
        }
 
        mDNS_Unlock(&mDNSStorage);
        }
 
+mDNSlocal mDNSBool ReadyForSleep(mDNS *m)
+       {
+       (void)m;
+
+       // 1. Scan list of private LLQs, and make sure they've all completed their handshake with the server
+       DNSQuestion *q;
+       for (q = m->Questions; q; q = q->next)
+               if (!mDNSOpaque16IsZero(q->TargetQID) && q->LongLived && q->ReqLease == 0 && q->tcp) return(mDNSfalse);
+
+       // 2. Scan list of registered records
+       AuthRecord *rr;
+       for (rr = m->ResourceRecords; rr; rr = rr->next)
+               if (rr->state == regState_Refresh && rr->tcp) return(mDNSfalse);
+
+       // 2. Scan list of registered services
+       ServiceRecordSet *srs;
+       for (srs = m->ServiceRegistrations; srs; srs = srs->uDNS_next)
+               if (srs->state == regState_NoTarget && srs->tcp) return(mDNSfalse);
+
+       return(mDNStrue);
+       }
+
 mDNSlocal void KQWokenFlushBytes(int fd, __unused short filter, __unused void *context)
        {
        // Read all of the bytes so we won't wake again.
        char    buffer[100];
 mDNSlocal void KQWokenFlushBytes(int fd, __unused short filter, __unused void *context)
        {
        // Read all of the bytes so we won't wake again.
        char    buffer[100];
-       ssize_t read = sizeof(buffer);
-       while (read > 0) read = recv(fd, buffer, sizeof(buffer), MSG_DONTWAIT);
+       while (recv(fd, buffer, sizeof(buffer), MSG_DONTWAIT) > 0) continue;
        }
 
 mDNSlocal void * KQueueLoop(void *m_param)
        }
 
 mDNSlocal void * KQueueLoop(void *m_param)
@@ -2334,9 +2389,39 @@ mDNSlocal void * KQueueLoop(void *m_param)
                mDNSs32 end            = mDNSPlatformRawTime();
                if (end - start >= WatchDogReportingThreshold)
                        LogOperation("WARNING: Idle task took %dms to complete", end - start);
                mDNSs32 end            = mDNSPlatformRawTime();
                if (end - start >= WatchDogReportingThreshold)
                        LogOperation("WARNING: Idle task took %dms to complete", end - start);
-               
+
+               mDNSs32 now = mDNS_TimeNow(m);
+
+               if (m->ShutdownTime)
+                       {
+                       if (mDNS_ExitNow(m, now))
+                               {
+                               LogOperation("mDNS_FinalExit");
+                               mDNS_FinalExit(&mDNSStorage);
+                               usleep(1000);           // Little 1ms pause before exiting, so we don't lose our final syslog messages
+                               exit(0);
+                               }
+                       if (nextTimerEvent - m->ShutdownTime >= 0)
+                               nextTimerEvent = m->ShutdownTime;
+                       }
+
+               if (m->p->SleepLimit)
+                       {
+                       mDNSBool ready = ReadyForSleep(m);
+                       if (ready || now - m->p->SleepLimit >= 0)
+                               {
+                               LogOperation("IOAllowPowerChange(%lX) %s at %ld (%d ticks remaining)", m->p->SleepCookie,
+                                       ready ? "ready for sleep" : "giving up", now, m->p->SleepLimit - now);
+                               m->p->SleepLimit = 0;
+                               IOAllowPowerChange(m->p->PowerConnection, m->p->SleepCookie);
+                               }
+                       else
+                               if (nextTimerEvent - m->p->SleepLimit >= 0)
+                                       nextTimerEvent = m->p->SleepLimit;
+                       }
+
                // Convert absolute wakeup time to a relative time from now
                // Convert absolute wakeup time to a relative time from now
-               mDNSs32 ticks = nextTimerEvent - mDNS_TimeNow(m);
+               mDNSs32 ticks = nextTimerEvent - now;
                if (ticks < 1) ticks = 1;
                
                static mDNSs32 RepeatedBusy = 0;        // Debugging sanity check, to guard against CPU spins
                if (ticks < 1) ticks = 1;
                
                static mDNSs32 RepeatedBusy = 0;        // Debugging sanity check, to guard against CPU spins
@@ -2401,14 +2486,14 @@ mDNSlocal void * KQueueLoop(void *m_param)
                        for (i = 0; i < events_found; i++)
                                {
                                const KQueueEntry *const kqentry = new_events[i].udata;
                        for (i = 0; i < events_found; i++)
                                {
                                const KQueueEntry *const kqentry = new_events[i].udata;
-                               mDNSs32 start = mDNSPlatformRawTime();
+                               mDNSs32 stime = mDNSPlatformRawTime();
 #if LogAllOperations || MDNS_DEBUGMSGS
                                const char *const KQtask = kqentry->KQtask;     // Grab a copy in case KQcallback deletes the task
 #endif
                                kqentry->KQcallback(new_events[i].ident, new_events[i].filter, kqentry->KQcontext);
 #if LogAllOperations || MDNS_DEBUGMSGS
                                const char *const KQtask = kqentry->KQtask;     // Grab a copy in case KQcallback deletes the task
 #endif
                                kqentry->KQcallback(new_events[i].ident, new_events[i].filter, kqentry->KQcontext);
-                               mDNSs32 end   = mDNSPlatformRawTime();
-                               if (end - start >= WatchDogReportingThreshold)
-                                       LogOperation("WARNING: %s took %dms to complete", KQtask, end - start);
+                               mDNSs32 etime = mDNSPlatformRawTime();
+                               if (etime - stime >= WatchDogReportingThreshold)
+                                       LogOperation("WARNING: %s took %dms to complete", KQtask, etime - stime);
                                }
                        }
                }
                                }
                        }
                }
index 767b1674f252509dfaef4f50373df0c612eb2124..3552c8acbca76b27009ff1734da9db50fb8cfa84 100644 (file)
     Change History (most recent first):
 
 $Log: helper-error.h,v $
     Change History (most recent first):
 
 $Log: helper-error.h,v $
+Revision 1.8  2007/11/07 00:22:30  jgraessley
+Bug #: <rdar://problem/5573573> mDNSResponder doesn't build without IPSec
+Reviewed by: Stuart Cheshire
+
 Revision 1.7  2007/09/12 00:42:47  mcguire
 <rdar://problem/5468236> BTMM: Need to clean up security associations
 
 Revision 1.7  2007/09/12 00:42:47  mcguire
 <rdar://problem/5468236> BTMM: Need to clean up security associations
 
@@ -73,3 +77,4 @@ ERROR(kmDNSHelperIPsecPolicyCreationFailed,       "Could not create IPsec policy
 ERROR(kmDNSHelperIPsecPolicySetFailed,            "Could not set IPsec policy")
 ERROR(kmDNSHelperIPsecRemoveSAFailed,             "Could not remove IPsec SA")
 ERROR(kmDNSHelperIPsecPolicySocketCreationFailed, "Could not create IPsec policy socket")
 ERROR(kmDNSHelperIPsecPolicySetFailed,            "Could not set IPsec policy")
 ERROR(kmDNSHelperIPsecRemoveSAFailed,             "Could not remove IPsec SA")
 ERROR(kmDNSHelperIPsecPolicySocketCreationFailed, "Could not create IPsec policy socket")
+ERROR(kmDNSHelperIPsecDisabled,                   "IPSec support was not compiled in to the helper")
index 3d625ca379f5fd91175db8a2567b367f91f81b0d..e2084e08e30a23d524a8fb26d85a78b9386cee20 100644 (file)
@@ -16,6 +16,9 @@
     Change History (most recent first):
 
 $Log: helper-stubs.c,v $
     Change History (most recent first):
 
 $Log: helper-stubs.c,v $
+Revision 1.6  2007/12/10 23:23:48  cheshire
+Removed unnecessary log message ("mDNSKeychainGetSecrets failed 0 00000000" because mDNSKeychainGetSecrets was failing to return a valid array)
+
 Revision 1.5  2007/09/07 22:44:03  mcguire
 <rdar://problem/5448420> Move CFUserNotification code to mDNSResponderHelper
 
 Revision 1.5  2007/09/07 22:44:03  mcguire
 <rdar://problem/5448420> Move CFUserNotification code to mDNSResponderHelper
 
@@ -72,7 +75,6 @@ mDNSHelperError(int err)
        return p;
        }
 
        return p;
        }
 
-
 /* Ugly but handy. */
 #define MACHRETRYLOOP_BEGIN(kr, retry, err, fin) for (;;) {
 
 /* Ugly but handy. */
 #define MACHRETRYLOOP_BEGIN(kr, retry, err, fin) for (;;) {
 
@@ -171,13 +173,11 @@ mDNSKeychainGetSecrets(CFArrayRef *result)
        int retry = 0;
        int err = 0;
 
        int retry = 0;
        int err = 0;
 
-
        MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
        kr = proxy_mDNSKeychainGetSecrets(getHelperPort(retry),
            &numsecrets, (vm_offset_t *)&secrets, &secretsCnt, &err);
        MACHRETRYLOOP_END(kr, retry, err, fin);
        MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
        kr = proxy_mDNSKeychainGetSecrets(getHelperPort(retry),
            &numsecrets, (vm_offset_t *)&secrets, &secretsCnt, &err);
        MACHRETRYLOOP_END(kr, retry, err, fin);
-       if (0 == numsecrets)
-               goto fin;
+
        if (NULL == (bytes = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
            secrets, secretsCnt, kCFAllocatorNull)))
                {
        if (NULL == (bytes = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
            secrets, secretsCnt, kCFAllocatorNull)))
                {
index 72257422fe4c5113dc150366b18e1adf8c1c65ee..8f4b8f8566b14a64cee4776a1e42f234f9bbc79a 100644 (file)
     Change History (most recent first):
 
 $Log: helper.c,v $
     Change History (most recent first):
 
 $Log: helper.c,v $
+Revision 1.23  2007/11/30 23:21:51  cheshire
+Rename variables to eliminate "declaration of 'sin_loc' shadows a previous local" warning
+
+Revision 1.22  2007/11/27 00:08:49  jgraessley
+<rdar://problem/5613538> Interface specific resolvers not setup correctly
+
+Revision 1.21  2007/11/07 00:22:30  jgraessley
+Bug #: <rdar://problem/5573573> mDNSResponder doesn't build without IPSec
+Reviewed by: Stuart Cheshire
+
 Revision 1.20  2007/09/12 18:07:44  cheshire
 Fix compile errors ("passing argument from incompatible pointer type")
 
 Revision 1.20  2007/09/12 18:07:44  cheshire
 Fix compile errors ("passing argument from incompatible pointer type")
 
@@ -103,6 +113,7 @@ Revision 1.1  2007/08/08 22:34:58  mcguire
 #include <SystemConfiguration/SCDynamicStore.h>
 #include <SystemConfiguration/SCPreferencesSetSpecific.h>
 #include <SystemConfiguration/SCDynamicStoreCopySpecific.h>
 #include <SystemConfiguration/SCDynamicStore.h>
 #include <SystemConfiguration/SCPreferencesSetSpecific.h>
 #include <SystemConfiguration/SCDynamicStoreCopySpecific.h>
+#include <TargetConditionals.h>
 #include "mDNSEmbeddedAPI.h"
 #include "dns_sd.h"
 #include "dnssd_ipc.h"
 #include "mDNSEmbeddedAPI.h"
 #include "dns_sd.h"
 #include "dnssd_ipc.h"
@@ -110,8 +121,10 @@ Revision 1.1  2007/08/08 22:34:58  mcguire
 #include "helper.h"
 #include "helpermsgServer.h"
 #include "helper-server.h"
 #include "helper.h"
 #include "helpermsgServer.h"
 #include "helper-server.h"
+#include "ipsec_options.h"
 
 #if TARGET_OS_EMBEDDED
 
 #if TARGET_OS_EMBEDDED
+#define NO_CFUSERNOTIFICATION 1
 #define NO_SECURITYFRAMEWORK 1
 #endif
 
 #define NO_SECURITYFRAMEWORK 1
 #endif
 
@@ -153,6 +166,7 @@ authorized(audit_token_t *token)
        return ok;
        }
 
        return ok;
        }
 
+#ifndef MDNS_NO_IPSEC
 static void
 closefds(int from)
        {
 static void
 closefds(int from)
        {
@@ -175,6 +189,7 @@ closefds(int from)
                }
        closedir(dirp);
        }
                }
        closedir(dirp);
        }
+#endif
 
 kern_return_t
 do_mDNSIdleExit(__unused mach_port_t port, audit_token_t token)
 
 kern_return_t
 do_mDNSIdleExit(__unused mach_port_t port, audit_token_t token)
@@ -272,6 +287,7 @@ char userhostname[MAX_DOMAIN_LABEL+1] = {0}; // the last local host name the use
 char lastcompname[MAX_DOMAIN_LABEL+1] = {0}; // the last computer name saved to preferences
 char lasthostname[MAX_DOMAIN_LABEL+1] = {0}; // the last local host name saved to preferences
 
 char lastcompname[MAX_DOMAIN_LABEL+1] = {0}; // the last computer name saved to preferences
 char lasthostname[MAX_DOMAIN_LABEL+1] = {0}; // the last local host name saved to preferences
 
+#ifndef NO_CFUSERNOTIFICATION
 static CFStringRef CFS_OQ = NULL;
 static CFStringRef CFS_CQ = NULL;
 static CFStringRef CFS_Format = NULL;
 static CFStringRef CFS_OQ = NULL;
 static CFStringRef CFS_CQ = NULL;
 static CFStringRef CFS_Format = NULL;
@@ -400,9 +416,11 @@ static CFMutableArrayRef GetHeader(const char* oldname, const char* newname, con
 
        return alertHeader;
        }
 
        return alertHeader;
        }
+#endif /* ndef NO_CFUSERNOTIFICATION */
 
 static void update_notification(void)
        {
 
 static void update_notification(void)
        {
+#ifndef NO_CFUSERNOTIFICATION
        debug("entry ucn=%s, uhn=%s, lcn=%s, lhn=%s", usercompname, userhostname, lastcompname, lasthostname);
        if (!CFS_OQ)
                {
        debug("entry ucn=%s, uhn=%s, lcn=%s, lhn=%s", usercompname, userhostname, lastcompname, lasthostname);
        if (!CFS_OQ)
                {
@@ -453,6 +471,7 @@ static void update_notification(void)
                ShowNameConflictNotification(header, *subtext);
                CFRelease(header);
                }
                ShowNameConflictNotification(header, *subtext);
                CFRelease(header);
                }
+#endif
        }
 
 kern_return_t
        }
 
 kern_return_t
@@ -874,6 +893,7 @@ fin:
 #endif
        }
 
 #endif
        }
 
+#ifndef MDNS_NO_IPSEC
 typedef enum _mDNSTunnelPolicyWhich
        {
        kmDNSTunnelPolicySetup,
 typedef enum _mDNSTunnelPolicyWhich
        {
        kmDNSTunnelPolicySetup,
@@ -981,11 +1001,13 @@ fin:
                close(s);
        return err;
        }
                close(s);
        return err;
        }
+#endif /* ifndef MDNS_NO_IPSEC */
 
 int
 do_mDNSAutoTunnelInterfaceUpDown(__unused mach_port_t port, int updown,
     v6addr_t address, int *err, audit_token_t token)
        {
 
 int
 do_mDNSAutoTunnelInterfaceUpDown(__unused mach_port_t port, int updown,
     v6addr_t address, int *err, audit_token_t token)
        {
+#ifndef MDNS_NO_IPSEC
        debug("entry");
        *err = 0;
        if (!authorized(&token))
        debug("entry");
        *err = 0;
        if (!authorized(&token))
@@ -1008,10 +1030,15 @@ do_mDNSAutoTunnelInterfaceUpDown(__unused mach_port_t port, int updown,
        debug("succeeded");
 
 fin:
        debug("succeeded");
 
 fin:
+#else
+       (void)port; (void)updown; (void)address; (void)token;
+       *err = kmDNSHelperIPsecDisabled;
+#endif
        update_idle_timer();
        return KERN_SUCCESS;
        }
 
        update_idle_timer();
        return KERN_SUCCESS;
        }
 
+#ifndef MDNS_NO_IPSEC
 static const char racoon_config_path[] = "/etc/racoon/remote/anonymous.conf";
 static const char racoon_config_path_orig[] = "/etc/racoon/remote/anonymous.conf.orig";
 
 static const char racoon_config_path[] = "/etc/racoon/remote/anonymous.conf";
 static const char racoon_config_path_orig[] = "/etc/racoon/remote/anonymous.conf.orig";
 
@@ -1237,9 +1264,12 @@ kickRacoon(void)
        return startRacoon();
        }
 
        return startRacoon();
        }
 
+#endif /* ndef MDNS_NO_IPSEC */
+
 int
 do_mDNSConfigureServer(__unused mach_port_t port, int updown, const char *keydata, int *err, audit_token_t token)
        {
 int
 do_mDNSConfigureServer(__unused mach_port_t port, int updown, const char *keydata, int *err, audit_token_t token)
        {
+#ifndef MDNS_NO_IPSEC
        debug("entry");
        *err = 0;
 
        debug("entry");
        *err = 0;
 
@@ -1271,10 +1301,16 @@ do_mDNSConfigureServer(__unused mach_port_t port, int updown, const char *keydat
        debug("succeeded");
 
 fin:
        debug("succeeded");
 
 fin:
+#else
+       (void)port; (void)updown; (void)keydata; (void)token;
+       *err = kmDNSHelperIPsecDisabled;
+#endif
        update_idle_timer();
        return KERN_SUCCESS;
        }
 
        update_idle_timer();
        return KERN_SUCCESS;
        }
 
+#ifndef MDNS_NO_IPSEC
+
 static unsigned int routeSeq = 1;
 
 static int
 static unsigned int routeSeq = 1;
 
 static int
@@ -1532,8 +1568,8 @@ doTunnelPolicy(mDNSTunnelPolicyWhich which,
               v6addr_t rmt_inner, uint8_t rmt_bits,
               v4addr_t rmt_outer, uint16_t rmt_port)
        {
               v6addr_t rmt_inner, uint8_t rmt_bits,
               v4addr_t rmt_outer, uint16_t rmt_port)
        {
-       struct sockaddr_in6 sin_loc;
-       struct sockaddr_in6 sin_rmt;
+       struct sockaddr_in6 sin6_loc;
+       struct sockaddr_in6 sin6_rmt;
        ipsec_policy_t policy = NULL;
        size_t len = 0;
        int s = -1;
        ipsec_policy_t policy = NULL;
        size_t len = 0;
        int s = -1;
@@ -1549,17 +1585,17 @@ doTunnelPolicy(mDNSTunnelPolicyWhich which,
                goto fin;
                }
 
                goto fin;
                }
 
-       memset(&sin_loc, 0, sizeof(sin_loc));
-       sin_loc.sin6_len = sizeof(sin_loc);
-       sin_loc.sin6_family = AF_INET6;
-       sin_loc.sin6_port = htons(0);
-       memcpy(&sin_loc.sin6_addr, loc_inner, sizeof(sin_loc.sin6_addr));
+       memset(&sin6_loc, 0, sizeof(sin6_loc));
+       sin6_loc.sin6_len = sizeof(sin6_loc);
+       sin6_loc.sin6_family = AF_INET6;
+       sin6_loc.sin6_port = htons(0);
+       memcpy(&sin6_loc.sin6_addr, loc_inner, sizeof(sin6_loc.sin6_addr));
 
 
-       memset(&sin_rmt, 0, sizeof(sin_rmt));
-       sin_rmt.sin6_len = sizeof(sin_rmt);
-       sin_rmt.sin6_family = AF_INET6;
-       sin_rmt.sin6_port = htons(0);
-       memcpy(&sin_rmt.sin6_addr, rmt_inner, sizeof(sin_rmt.sin6_addr));
+       memset(&sin6_rmt, 0, sizeof(sin6_rmt));
+       sin6_rmt.sin6_len = sizeof(sin6_rmt);
+       sin6_rmt.sin6_family = AF_INET6;
+       sin6_rmt.sin6_port = htons(0);
+       memcpy(&sin6_rmt.sin6_addr, rmt_inner, sizeof(sin6_rmt.sin6_addr));
 
        int setup = which != kmDNSTunnelPolicyTeardown;
 
 
        int setup = which != kmDNSTunnelPolicyTeardown;
 
@@ -1569,8 +1605,8 @@ doTunnelPolicy(mDNSTunnelPolicyWhich which,
            &policy, &len)))
                goto fin;
        if (0 != (err = sendPolicy(s, setup,
            &policy, &len)))
                goto fin;
        if (0 != (err = sendPolicy(s, setup,
-           (struct sockaddr *)&sin_rmt, rmt_bits,
-           (struct sockaddr *)&sin_loc, loc_bits,
+           (struct sockaddr *)&sin6_rmt, rmt_bits,
+           (struct sockaddr *)&sin6_loc, loc_bits,
            policy, len)))
                goto fin;
        if (NULL != policy)
            policy, len)))
                goto fin;
        if (NULL != policy)
@@ -1584,8 +1620,8 @@ doTunnelPolicy(mDNSTunnelPolicyWhich which,
            &policy, &len)))
                goto fin;
        if (0 != (err = sendPolicy(s, setup,
            &policy, &len)))
                goto fin;
        if (0 != (err = sendPolicy(s, setup,
-           (struct sockaddr *)&sin_loc, loc_bits,
-           (struct sockaddr *)&sin_rmt, rmt_bits,
+           (struct sockaddr *)&sin6_loc, loc_bits,
+           (struct sockaddr *)&sin6_rmt, rmt_bits,
            policy, len)))
                goto fin;
 
            policy, len)))
                goto fin;
 
@@ -1620,12 +1656,15 @@ fin:
        return err;
        }
 
        return err;
        }
 
+#endif /* ndef MDNS_NO_IPSEC */
+
 int
 do_mDNSAutoTunnelSetKeys(__unused mach_port_t port, int replacedelete,
     v6addr_t loc_inner, v4addr_t loc_outer, uint16_t loc_port,
     v6addr_t rmt_inner, v4addr_t rmt_outer, uint16_t rmt_port,
     const char *keydata, int *err, audit_token_t token)
        {
 int
 do_mDNSAutoTunnelSetKeys(__unused mach_port_t port, int replacedelete,
     v6addr_t loc_inner, v4addr_t loc_outer, uint16_t loc_port,
     v6addr_t rmt_inner, v4addr_t rmt_outer, uint16_t rmt_port,
     const char *keydata, int *err, audit_token_t token)
        {
+#ifndef MDNS_NO_IPSEC
        static const char config[] =
          "%s"
          "remote %s [%u] {\n"
        static const char config[] =
          "%s"
          "remote %s [%u] {\n"
@@ -1773,6 +1812,12 @@ fin:
        if (0 <= fd)
                close(fd);
        unlink(tmp_path);
        if (0 <= fd)
                close(fd);
        unlink(tmp_path);
+#else
+       (void)replacedelete; (void)loc_inner; (void)loc_outer; (void)loc_port; (void)rmt_inner;
+       (void)rmt_outer; (void)rmt_port; (void)keydata; (void)token;
+       
+       *err = kmDNSHelperIPsecDisabled;
+#endif /* MDNS_NO_IPSEC */
        update_idle_timer();
        return KERN_SUCCESS;
        }
        update_idle_timer();
        return KERN_SUCCESS;
        }
index 5cba5efa009f222f02f9b8b22dd6f20732baca68..a1987412c20b3dfb54e7ac32b9b6a96e309a4566 100644 (file)
     Change History (most recent first):
 
 $Log: mDNSMacOSX.c,v $
     Change History (most recent first):
 
 $Log: mDNSMacOSX.c,v $
+Revision 1.521  2007/12/14 00:58:28  cheshire
+<rdar://problem/5526800> BTMM: Need to deregister records and services on shutdown/sleep
+Additional fixes: When going to sleep, mDNSResponder needs to postpone sleep
+until TLS/TCP deregistrations have completed (up to five seconds maximum)
+
+Revision 1.520  2007/12/10 23:01:01  cheshire
+Remove some unnecessary log messages
+
+Revision 1.519  2007/12/06 00:22:27  mcguire
+<rdar://problem/5604567> BTMM: Doesn't work with Linksys WAG300N 1.01.06 (sending from 1026/udp)
+
+Revision 1.518  2007/12/05 01:52:30  cheshire
+<rdar://problem/5624763> BTMM: getaddrinfo_async_start returns EAI_NONAME when resolving BTMM hostname
+Delay returning IPv4 address ("A") results for autotunnel names until after we've set up the tunnel (or tried to)
+
+Revision 1.517  2007/12/03 18:37:26  cheshire
+Moved mDNSPlatformWriteLogMsg & mDNSPlatformWriteDebugMsg
+from mDNSMacOSX.c to PlatformCommon.c, so that Posix build can use them
+
+Revision 1.516  2007/12/01 01:21:27  jgraessley
+<rdar://problem/5623140> mDNSResponder unicast DNS improvements
+
+Revision 1.515  2007/12/01 00:40:00  cheshire
+Add mDNSPlatformWriteLogMsg & mDNSPlatformWriteDebugMsg abstractions, to facilitate EFI conversion
+
+Revision 1.514  2007/12/01 00:38:32  cheshire
+Fixed compile warning: declaration of 'index' shadows a global declaration
+
+Revision 1.513  2007/11/27 00:08:49  jgraessley
+<rdar://problem/5613538> Interface-specific resolvers not setup correctly
+
+Revision 1.512  2007/11/16 22:09:26  cheshire
+Added missing type information in mDNSPlatformTCPCloseConnection debugging log message
+
+Revision 1.511  2007/11/14 23:06:13  cheshire
+<rdar://problem/5585972> IP_ADD_MEMBERSHIP fails for previously-connected removable interfaces
+
+Revision 1.510  2007/11/14 22:29:19  cheshire
+Updated comments and debugging log messages
+
+Revision 1.509  2007/11/14 01:07:53  cheshire
+Updated comments
+
 Revision 1.508  2007/11/02 21:59:37  cheshire
 Added comment about locking
 
 Revision 1.508  2007/11/02 21:59:37  cheshire
 Added comment about locking
 
@@ -62,7 +105,7 @@ Revision 1.496  2007/10/04 20:33:05  mcguire
 <rdar://problem/5518845> BTMM: Racoon configuration removed when network changes
 
 Revision 1.495  2007/10/02 05:03:38  cheshire
 <rdar://problem/5518845> BTMM: Racoon configuration removed when network changes
 
 Revision 1.495  2007/10/02 05:03:38  cheshire
-Fix bugus indentation in mDNSPlatformDynDNSHostNameStatusChanged
+Fix bogus indentation in mDNSPlatformDynDNSHostNameStatusChanged
 
 Revision 1.494  2007/09/29 20:40:19  cheshire
 <rdar://problem/5513378> Crash in ReissueBlockedQuestions
 
 Revision 1.494  2007/09/29 20:40:19  cheshire
 <rdar://problem/5513378> Crash in ReissueBlockedQuestions
@@ -670,7 +713,6 @@ Add (commented out) trigger value for testing "mach_absolute_time went backwards
 #include "../mDNSShared/uds_daemon.h" // Defines communication interface from platform layer up to UDS daemon
 #include "PlatformCommon.h"
 
 #include "../mDNSShared/uds_daemon.h" // Defines communication interface from platform layer up to UDS daemon
 #include "PlatformCommon.h"
 
-
 #include <stdio.h>
 #include <stdarg.h>                 // For va_list support
 #include <net/if.h>
 #include <stdio.h>
 #include <stdarg.h>                 // For va_list support
 #include <net/if.h>
@@ -699,6 +741,7 @@ Add (commented out) trigger value for testing "mach_absolute_time went backwards
 
 #if TARGET_OS_EMBEDDED
 #define NO_SECURITYFRAMEWORK 1
 
 #if TARGET_OS_EMBEDDED
 #define NO_SECURITYFRAMEWORK 1
+#define NO_CFUSERNOTIFICATION 1
 #endif
 
 #ifndef NO_SECURITYFRAMEWORK
 #endif
 
 #ifndef NO_SECURITYFRAMEWORK
@@ -821,42 +864,43 @@ mDNSlocal struct ifaddrs *myGetIfAddrs(int refresh)
        return ifa;
        }
 
        return ifa;
        }
 
+// To match *either* a v4 or v6 instance of this interface name, pass AF_UNSPEC for type
 mDNSlocal NetworkInterfaceInfoOSX *SearchForInterfaceByName(mDNS *const m, const char *ifname, int type)
        {
        NetworkInterfaceInfoOSX *i;
        for (i = m->p->InterfaceList; i; i = i->next)
                if (i->Exists && !strcmp(i->ifa_name, ifname) &&
 mDNSlocal NetworkInterfaceInfoOSX *SearchForInterfaceByName(mDNS *const m, const char *ifname, int type)
        {
        NetworkInterfaceInfoOSX *i;
        for (i = m->p->InterfaceList; i; i = i->next)
                if (i->Exists && !strcmp(i->ifa_name, ifname) &&
-                       ((AAAA_OVER_V4                                              ) ||
+                       ((type == AF_UNSPEC                                         ) ||
                         (type == AF_INET  && i->ifinfo.ip.type == mDNSAddrType_IPv4) ||
                         (type == AF_INET6 && i->ifinfo.ip.type == mDNSAddrType_IPv6))) return(i);
        return(NULL);
        }
 
                         (type == AF_INET  && i->ifinfo.ip.type == mDNSAddrType_IPv4) ||
                         (type == AF_INET6 && i->ifinfo.ip.type == mDNSAddrType_IPv6))) return(i);
        return(NULL);
        }
 
-mDNSlocal int myIfIndexToName(u_short index, char *name)
+mDNSlocal int myIfIndexToName(u_short ifindex, char *name)
        {
        struct ifaddrs *ifa;
        for (ifa = myGetIfAddrs(0); ifa; ifa = ifa->ifa_next)
                if (ifa->ifa_addr->sa_family == AF_LINK)
        {
        struct ifaddrs *ifa;
        for (ifa = myGetIfAddrs(0); ifa; ifa = ifa->ifa_next)
                if (ifa->ifa_addr->sa_family == AF_LINK)
-                       if (((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index == index)
+                       if (((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index == ifindex)
                                { strlcpy(name, ifa->ifa_name, IF_NAMESIZE); return 0; }
        return -1;
        }
 
                                { strlcpy(name, ifa->ifa_name, IF_NAMESIZE); return 0; }
        return -1;
        }
 
-mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 index)
+mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 ifindex)
        {
        NetworkInterfaceInfoOSX *i;
        {
        NetworkInterfaceInfoOSX *i;
-       if (index == kDNSServiceInterfaceIndexLocalOnly) return(mDNSInterface_LocalOnly);
-       if (index == kDNSServiceInterfaceIndexAny      ) return(mDNSNULL);
+       if (ifindex == kDNSServiceInterfaceIndexLocalOnly) return(mDNSInterface_LocalOnly);
+       if (ifindex == kDNSServiceInterfaceIndexAny      ) return(mDNSNULL);
 
        // Don't get tricked by inactive interfaces with no InterfaceID set
        for (i = m->p->InterfaceList; i; i = i->next)
 
        // Don't get tricked by inactive interfaces with no InterfaceID set
        for (i = m->p->InterfaceList; i; i = i->next)
-               if (i->ifinfo.InterfaceID && i->scope_id == index) return(i->ifinfo.InterfaceID);
+               if (i->ifinfo.InterfaceID && i->scope_id == ifindex) return(i->ifinfo.InterfaceID);
 
        // Not found. Make sure our interface list is up to date, then try again.
 
        // Not found. Make sure our interface list is up to date, then try again.
-       LogOperation("InterfaceID for interface index %d not found; Updating interface list", index);
+       LogOperation("InterfaceID for interface index %d not found; Updating interface list", ifindex);
        mDNSMacOSXNetworkChanged(m);
        for (i = m->p->InterfaceList; i; i = i->next)
        mDNSMacOSXNetworkChanged(m);
        for (i = m->p->InterfaceList; i; i = i->next)
-               if (i->ifinfo.InterfaceID && i->scope_id == index) return(i->ifinfo.InterfaceID);
+               if (i->ifinfo.InterfaceID && i->scope_id == ifindex) return(i->ifinfo.InterfaceID);
 
        return(mDNSNULL);
        }
 
        return(mDNSNULL);
        }
@@ -901,6 +945,12 @@ mDNSlocal mDNSBool AddrRequiresPPPConnection(const struct sockaddr *addr)
        return result;
        }
 
        return result;
        }
 
+struct UDPSocket_struct
+       {
+       mDNSIPPort port; // MUST BE FIRST FIELD -- mDNSCore expects every UDPSocket_struct to begin with mDNSIPPort port
+       KQSocketSet ss;
+       };
+
 // NOTE: If InterfaceID is NULL, it means, "send this packet through our anonymous unicast socket"
 // NOTE: If InterfaceID is non-NULL it means, "send this packet through our port 5353 socket on the specified interface"
 // OR send via our primary v4 unicast socket
 // NOTE: If InterfaceID is NULL, it means, "send this packet through our anonymous unicast socket"
 // NOTE: If InterfaceID is non-NULL it means, "send this packet through our port 5353 socket on the specified interface"
 // OR send via our primary v4 unicast socket
@@ -920,11 +970,8 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms
        // anonymous socket created for this purpose, so that we'll receive the response.
        // If we use one of the many multicast sockets bound to port 5353 then we may not receive responses reliably.
        if (InterfaceID && !mDNSAddrIsDNSMulticast(dst))
        // anonymous socket created for this purpose, so that we'll receive the response.
        // If we use one of the many multicast sockets bound to port 5353 then we may not receive responses reliably.
        if (InterfaceID && !mDNSAddrIsDNSMulticast(dst))
-               {
-               const DNSMessage *const m = (DNSMessage *)msg;
-               if ((m->h.flags.b[0] & kDNSFlag0_QR_Mask) == kDNSFlag0_QR_Query)
+               if ((((DNSMessage *)msg)->h.flags.b[0] & kDNSFlag0_QR_Mask) == kDNSFlag0_QR_Query)
                        LogMsg("mDNSPlatformSendUDP: ERROR: Sending query OP from mDNS port to non-mDNS destination %#a:%d", dst, mDNSVal16(dstPort));
                        LogMsg("mDNSPlatformSendUDP: ERROR: Sending query OP from mDNS port to non-mDNS destination %#a:%d", dst, mDNSVal16(dstPort));
-               }
 
        if (dst->type == mDNSAddrType_IPv4)
                {
 
        if (dst->type == mDNSAddrType_IPv4)
                {
@@ -934,6 +981,12 @@ mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const void *const ms
                sin_to->sin_port           = dstPort.NotAnInteger;
                sin_to->sin_addr.s_addr    = dst->ip.v4.NotAnInteger;
                s = m->p->permanentsockets.sktv4;
                sin_to->sin_port           = dstPort.NotAnInteger;
                sin_to->sin_addr.s_addr    = dst->ip.v4.NotAnInteger;
                s = m->p->permanentsockets.sktv4;
+
+#ifdef _LEGACY_NAT_TRAVERSAL_
+               if (m->SSDPSocket && mDNSSameIPPort(dstPort, SSDPPort))
+                       s = m->SSDPSocket->ss.sktv4;
+#endif _LEGACY_NAT_TRAVERSAL_
+
                if (info)       // Specify outgoing interface
                        {
                        if (!mDNSAddrIsDNSMulticast(dst))
                if (info)       // Specify outgoing interface
                        {
                        if (!mDNSAddrIsDNSMulticast(dst))
@@ -1083,6 +1136,7 @@ mDNSlocal ssize_t myrecvfrom(const int s, void *const buffer, const size_t max,
                        {
                        dstaddr->type = mDNSAddrType_IPv4;
                        dstaddr->ip.v4 = *(mDNSv4Addr*)CMSG_DATA(cmPtr);
                        {
                        dstaddr->type = mDNSAddrType_IPv4;
                        dstaddr->ip.v4 = *(mDNSv4Addr*)CMSG_DATA(cmPtr);
+                       //LogMsg("mDNSMacOSX.c: recvmsg IP_RECVDSTADDR %.4a", &dstaddr->ip.v4);
                        }
                if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVIF)
                        {
                        }
                if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVIF)
                        {
@@ -1129,7 +1183,7 @@ mDNSlocal void myKQSocketCallBack(int s1, short filter, void *context)
        while (1)
                {
                mDNSAddr senderAddr, destAddr;
        while (1)
                {
                mDNSAddr senderAddr, destAddr;
-               mDNSIPPort senderPort, destPort = MulticastDNSPort;
+               mDNSIPPort senderPort, destPort = (m->SSDPSocket && ss == &m->SSDPSocket->ss ? m->SSDPSocket->port : MulticastDNSPort);
                struct sockaddr_storage from;
                size_t fromlen = sizeof(from);
                char packetifname[IF_NAMESIZE] = "";
                struct sockaddr_storage from;
                size_t fromlen = sizeof(from);
                char packetifname[IF_NAMESIZE] = "";
@@ -1140,10 +1194,10 @@ mDNSlocal void myKQSocketCallBack(int s1, short filter, void *context)
                count++;
                if (from.ss_family == AF_INET)
                        {
                count++;
                if (from.ss_family == AF_INET)
                        {
-                       struct sockaddr_in *sin = (struct sockaddr_in*)&from;
+                       struct sockaddr_in *s = (struct sockaddr_in*)&from;
                        senderAddr.type = mDNSAddrType_IPv4;
                        senderAddr.type = mDNSAddrType_IPv4;
-                       senderAddr.ip.v4.NotAnInteger = sin->sin_addr.s_addr;
-                       senderPort.NotAnInteger = sin->sin_port;
+                       senderAddr.ip.v4.NotAnInteger = s->sin_addr.s_addr;
+                       senderPort.NotAnInteger = s->sin_port;
                        //LogOperation("myKQSocketCallBack received IPv4 packet from %#-15a to %#-15a on skt %d %s", &senderAddr, &destAddr, s1, packetifname);
                        }
                else if (from.ss_family == AF_INET6)
                        //LogOperation("myKQSocketCallBack received IPv4 packet from %#-15a to %#-15a on skt %d %s", &senderAddr, &destAddr, s1, packetifname);
                        }
                else if (from.ss_family == AF_INET6)
@@ -1318,9 +1372,9 @@ mDNSlocal void tcpKQSocketCallback(__unused int fd, short filter, void *context)
 #endif /* NO_SECURITYFRAMEWORK */
                }
 
 #endif /* NO_SECURITYFRAMEWORK */
                }
 
-       mDNSBool connect = !sock->connected;
+       mDNSBool c = !sock->connected;
        sock->connected = mDNStrue;
        sock->connected = mDNStrue;
-       sock->callback(sock, sock->context, connect, err);
+       sock->callback(sock, sock->context, c, err);
        // NOTE: the callback may call CloseConnection here, which frees the context structure!
        }
 
        // NOTE: the callback may call CloseConnection here, which frees the context structure!
        }
 
@@ -1532,7 +1586,7 @@ mDNSexport void mDNSPlatformTCPCloseConnection(TCPSocket *sock)
                        sock->fd = -1;
                        }
 
                        sock->fd = -1;
                        }
 
-               freeL("mDNSPlatformTCPCloseConnection", sock);
+               freeL("TCPSocket/mDNSPlatformTCPCloseConnection", sock);
                }
        }
 
                }
        }
 
@@ -1627,7 +1681,7 @@ mDNSexport int mDNSPlatformTCPGetFD(TCPSocket *sock)
 
 // If mDNSIPPort port is non-zero, then it's a multicast socket on the specified interface
 // If mDNSIPPort port is zero, then it's a randomly assigned port number, used for sending unicast queries
 
 // If mDNSIPPort port is non-zero, then it's a multicast socket on the specified interface
 // If mDNSIPPort port is zero, then it's a randomly assigned port number, used for sending unicast queries
-mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa_family)
+mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa_family, mDNSIPPort *const outport)
        {
        const int ip_tosbits = IPTOS_LOWDELAY | IPTOS_THROUGHPUT;
        int         *s        = (sa_family == AF_INET) ? &cp->sktv4 : &cp->sktv6;
        {
        const int ip_tosbits = IPTOS_LOWDELAY | IPTOS_THROUGHPUT;
        int         *s        = (sa_family == AF_INET) ? &cp->sktv4 : &cp->sktv6;
@@ -1677,6 +1731,7 @@ mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa
                listening_sockaddr.sin_addr.s_addr = 0; // Want to receive multicasts AND unicasts on this socket
                err = bind(skt, (struct sockaddr *) &listening_sockaddr, sizeof(listening_sockaddr));
                if (err) { errstr = "bind"; goto fail; }
                listening_sockaddr.sin_addr.s_addr = 0; // Want to receive multicasts AND unicasts on this socket
                err = bind(skt, (struct sockaddr *) &listening_sockaddr, sizeof(listening_sockaddr));
                if (err) { errstr = "bind"; goto fail; }
+               if (outport) outport->NotAnInteger = listening_sockaddr.sin_port;
                }
        else if (sa_family == AF_INET6)
                {
                }
        else if (sa_family == AF_INET6)
                {
@@ -1724,6 +1779,7 @@ mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa
                listening_sockaddr6.sin6_scope_id    = 0;
                err = bind(skt, (struct sockaddr *) &listening_sockaddr6, sizeof(listening_sockaddr6));
                if (err) { errstr = "bind"; goto fail; }
                listening_sockaddr6.sin6_scope_id    = 0;
                err = bind(skt, (struct sockaddr *) &listening_sockaddr6, sizeof(listening_sockaddr6));
                if (err) { errstr = "bind"; goto fail; }
+               if (outport) outport->NotAnInteger = listening_sockaddr6.sin6_port;
                }
 
        fcntl(skt, F_SETFL, fcntl(skt, F_GETFL, 0) | O_NONBLOCK); // set non-blocking
                }
 
        fcntl(skt, F_SETFL, fcntl(skt, F_GETFL, 0) | O_NONBLOCK); // set non-blocking
@@ -1753,11 +1809,6 @@ mDNSlocal mStatus SetupSocket(KQSocketSet *cp, const mDNSIPPort port, u_short sa
        return(err);
        }
 
        return(err);
        }
 
-struct UDPSocket_struct
-       {
-       KQSocketSet ss;
-       };
-
 mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort port)
        {
        mStatus err;
 mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort port)
        {
        mStatus err;
@@ -1767,7 +1818,8 @@ mDNSexport UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort port
        p->ss.m     = m;
        p->ss.sktv4 = -1;
        p->ss.sktv6 = -1;
        p->ss.m     = m;
        p->ss.sktv4 = -1;
        p->ss.sktv6 = -1;
-       err = SetupSocket(&p->ss, port, AF_INET);
+       p->port = zeroIPPort;
+       err = SetupSocket(&p->ss, port, AF_INET, &p->port);
        if (err)
                {
                // In customer builds we don't want to log failures with port 5351, because this is a known issue
        if (err)
                {
                // In customer builds we don't want to log failures with port 5351, because this is a known issue
@@ -2148,7 +2200,7 @@ mDNSlocal void RegisterAutoTunnelRecords(mDNS *m, DomainAuthInfo *info)
                err = mDNS_Register(m, &info->AutoTunnelService);
                if (err) LogMsg("RegisterAutoTunnelRecords error %d registering AutoTunnelService %##s", err, info->AutoTunnelService.namestorage.c);
 
                err = mDNS_Register(m, &info->AutoTunnelService);
                if (err) LogMsg("RegisterAutoTunnelRecords error %d registering AutoTunnelService %##s", err, info->AutoTunnelService.namestorage.c);
 
-               LogMsg("AutoTunnel server listening for connections on %##s[%.4a]:%d:%##s[%.16a]",
+               LogOperation("AutoTunnel server listening for connections on %##s[%.4a]:%d:%##s[%.16a]",
                        info->AutoTunnelTarget.namestorage.c,     &m->AdvertisedV4.ip.v4, mDNSVal16(info->AutoTunnelNAT.IntPort),
                        info->AutoTunnelHostRecord.namestorage.c, &m->AutoTunnelHostAddr);
                }
                        info->AutoTunnelTarget.namestorage.c,     &m->AdvertisedV4.ip.v4, mDNSVal16(info->AutoTunnelNAT.IntPort),
                        info->AutoTunnelHostRecord.namestorage.c, &m->AutoTunnelHostAddr);
                }
@@ -2208,7 +2260,7 @@ mDNSlocal void AutoTunnelNATCallback(mDNS *m, NATTraversalInfo *n)
        LogOperation("AutoTunnelNATCallback Result %d %.4a Internal %d External %d %#s.%##s",
                n->Result, &n->ExternalAddress, mDNSVal16(n->IntPort), mDNSVal16(n->ExternalPort), m->hostlabel.c, info->domain.c);
 
        LogOperation("AutoTunnelNATCallback Result %d %.4a Internal %d External %d %#s.%##s",
                n->Result, &n->ExternalAddress, mDNSVal16(n->IntPort), mDNSVal16(n->ExternalPort), m->hostlabel.c, info->domain.c);
 
-       m->NextSRVUpdate = m->timenow;
+       m->NextSRVUpdate = NonZeroTime(m->timenow);
        DeregisterAutoTunnelRecords(m,info);
        RegisterAutoTunnelRecords(m,info);
 
        DeregisterAutoTunnelRecords(m,info);
        RegisterAutoTunnelRecords(m,info);
 
@@ -2247,7 +2299,7 @@ mDNSexport void SetupLocalAutoTunnelInterface_internal(mDNS *const m)
        if (!m->AutoTunnelHostAddrActive)
                {
                m->AutoTunnelHostAddrActive = mDNStrue;
        if (!m->AutoTunnelHostAddrActive)
                {
                m->AutoTunnelHostAddrActive = mDNStrue;
-               LogMsg("Setting up AutoTunnel address %.16a", &m->AutoTunnelHostAddr);
+               LogOperation("Setting up AutoTunnel address %.16a", &m->AutoTunnelHostAddr);
                (void)mDNSAutoTunnelInterfaceUpDown(kmDNSUp, m->AutoTunnelHostAddr.b);
                }
 
                (void)mDNSAutoTunnelInterfaceUpDown(kmDNSUp, m->AutoTunnelHostAddr.b);
                }
 
@@ -2291,14 +2343,14 @@ mDNSlocal mStatus AutoTunnelSetKeys(ClientTunnel *tun, mDNSBool AddNew)
 // If the EUI-64 part of the IPv6 ULA matches, then that means the two addresses point to the same machine
 #define mDNSSameClientTunnel(A,B) ((A)->l[2] == (B)->l[2] && (A)->l[3] == (B)->l[3])
 
 // If the EUI-64 part of the IPv6 ULA matches, then that means the two addresses point to the same machine
 #define mDNSSameClientTunnel(A,B) ((A)->l[2] == (B)->l[2] && (A)->l[3] == (B)->l[3])
 
-mDNSlocal void ReissueBlockedQuestions(mDNS *const m, domainname *d, mDNSBool success)
+mDNSlocal void ReissueBlockedQuestionWithType(mDNS *const m, domainname *d, mDNSBool success, mDNSu16 qtype)
        {
        DNSQuestion *q = m->Questions;
        while (q)
                {
        {
        DNSQuestion *q = m->Questions;
        while (q)
                {
-               if (q->NoAnswer == NoAnswer_Suspended && q->qtype == kDNSType_AAAA && q->AuthInfo && q->AuthInfo->AutoTunnel && SameDomainName(&q->qname, d))
+               if (q->NoAnswer == NoAnswer_Suspended && q->qtype == qtype && q->AuthInfo && q->AuthInfo->AutoTunnel && SameDomainName(&q->qname, d))
                        {
                        {
-                       LogOperation("Restart %##s", q->qname.c);
+                       LogOperation("Restart %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
                        mDNSQuestionCallback *tmp = q->QuestionCallback;
                        q->QuestionCallback = AutoTunnelCallback;       // Set QuestionCallback to suppress another call back to AddNewClientTunnel
                        mDNS_StopQuery(m, q);
                        mDNSQuestionCallback *tmp = q->QuestionCallback;
                        q->QuestionCallback = AutoTunnelCallback;       // Set QuestionCallback to suppress another call back to AddNewClientTunnel
                        mDNS_StopQuery(m, q);
@@ -2318,12 +2370,24 @@ mDNSlocal void ReissueBlockedQuestions(mDNS *const m, domainname *d, mDNSBool su
                }
        }
 
                }
        }
 
+mDNSlocal void ReissueBlockedQuestions(mDNS *const m, domainname *d, mDNSBool success)
+       {
+       // 1. We deliberately restart AAAA queries before A queries, because in the common case where a BTTM host has
+       //    a v6 address but no v4 address, we prefer the caller to get the positive AAAA response before the A NXDOMAIN.
+       // 2. In the case of AAAA queries, if our tunnel setup failed, then we return a deliberate failure indication to the caller --
+       //    even if the name does have a valid AAAA record, we don't want clients trying to connect to it without a properly encrypted tunnel.
+       // 3. For A queries we never fabricate failures -- if a BTTM service is really using raw IPv4, then it doesn't need the IPv6 tunnel.
+       ReissueBlockedQuestionWithType(m, d, success, kDNSType_AAAA);
+       ReissueBlockedQuestionWithType(m, d, mDNStrue, kDNSType_A);
+       }
+
 mDNSlocal void UnlinkAndReissueBlockedQuestions(mDNS *const m, ClientTunnel *tun, mDNSBool success)
        {
        ClientTunnel **p = &m->TunnelClients;
        while (*p != tun && *p) p = &(*p)->next;
        if (*p) *p = tun->next;
        ReissueBlockedQuestions(m, &tun->dstname, success);
 mDNSlocal void UnlinkAndReissueBlockedQuestions(mDNS *const m, ClientTunnel *tun, mDNSBool success)
        {
        ClientTunnel **p = &m->TunnelClients;
        while (*p != tun && *p) p = &(*p)->next;
        if (*p) *p = tun->next;
        ReissueBlockedQuestions(m, &tun->dstname, success);
+       LogOperation("UnlinkAndReissueBlockedQuestions: Disposing ClientTunnel %p", tun);
        freeL("ClientTunnel", tun);
        }
 
        freeL("ClientTunnel", tun);
        }
 
@@ -2337,7 +2401,7 @@ mDNSexport void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const R
 
        if (!answer->rdlength)
                {
 
        if (!answer->rdlength)
                {
-               LogOperation("AutoTunnelCallback NXDOMAIN %##s", question->qname.c);
+               LogOperation("AutoTunnelCallback NXDOMAIN %##s (%s)", question->qname.c, DNSTypeName(question->qtype));
                UnlinkAndReissueBlockedQuestions(m, tun, mDNSfalse);
                return;
                }
                UnlinkAndReissueBlockedQuestions(m, tun, mDNSfalse);
                return;
                }
@@ -2346,7 +2410,7 @@ mDNSexport void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const R
                {
                if (mDNSSameIPv6Address(answer->rdata->u.ipv6, m->AutoTunnelHostAddr))
                        {
                {
                if (mDNSSameIPv6Address(answer->rdata->u.ipv6, m->AutoTunnelHostAddr))
                        {
-                       LogOperation("AutoTunnelCallback: supressing tunnel to self %.16a", &answer->rdata->u.ipv6);
+                       LogOperation("AutoTunnelCallback: suppressing tunnel to self %.16a", &answer->rdata->u.ipv6);
                        UnlinkAndReissueBlockedQuestions(m, tun, mDNStrue);
                        return;
                        }
                        UnlinkAndReissueBlockedQuestions(m, tun, mDNStrue);
                        return;
                        }
@@ -2402,6 +2466,7 @@ mDNSexport void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const R
                                        }
                                else needSetKeys = mDNSfalse;
 
                                        }
                                else needSetKeys = mDNSfalse;
 
+                               LogOperation("AutoTunnelCallback: Disposing ClientTunnel %p", tun);
                                freeL("ClientTunnel", old);
                                }
                        }
                                freeL("ClientTunnel", old);
                                }
                        }
@@ -2424,7 +2489,7 @@ mDNSexport void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q)
        ClientTunnel *p = mallocL("ClientTunnel", sizeof(ClientTunnel));
        if (!p) return;
        AssignDomainName(&p->dstname, &q->qname);
        ClientTunnel *p = mallocL("ClientTunnel", sizeof(ClientTunnel));
        if (!p) return;
        AssignDomainName(&p->dstname, &q->qname);
-       p->markedForDeletion = mDNSfalse;
+       p->MarkedForDeletion = mDNSfalse;
        p->loc_inner      = zerov6Addr;
        p->loc_outer      = zerov4Addr;
        p->rmt_inner      = zerov6Addr;
        p->loc_inner      = zerov6Addr;
        p->loc_outer      = zerov4Addr;
        p->rmt_inner      = zerov6Addr;
@@ -2432,7 +2497,7 @@ mDNSexport void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q)
        p->rmt_outer_port = zeroIPPort;
        mDNS_snprintf(p->b64keydata, sizeof(p->b64keydata), "%s", q->AuthInfo->b64keydata);
        p->next = m->TunnelClients;
        p->rmt_outer_port = zeroIPPort;
        mDNS_snprintf(p->b64keydata, sizeof(p->b64keydata), "%s", q->AuthInfo->b64keydata);
        p->next = m->TunnelClients;
-       m->TunnelClients = p;           // Intentionally build list in reverse order
+       m->TunnelClients = p;           // We intentionally build list in reverse order
 
        p->q.InterfaceID      = mDNSInterface_Any;
        p->q.Target           = zeroAddr;
 
        p->q.InterfaceID      = mDNSInterface_Any;
        p->q.Target           = zeroAddr;
@@ -2446,7 +2511,7 @@ mDNSexport void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q)
        p->q.QuestionCallback = AutoTunnelCallback;
        p->q.QuestionContext  = p;
 
        p->q.QuestionCallback = AutoTunnelCallback;
        p->q.QuestionContext  = p;
 
-       LogOperation("AddNewClientTunnel start  %##s (%s)%s", &p->q.qname.c, DNSTypeName(p->q.qtype), q->LongLived ? " LongLived" : "");
+       LogOperation("AddNewClientTunnel start tun %p %##s (%s)%s", p, &q->qname.c, DNSTypeName(q->qtype), q->LongLived ? " LongLived" : "");
        mDNS_StartQuery_internal(m, &p->q);
        }
 
        mDNS_StartQuery_internal(m, &p->q);
        }
 
@@ -2701,8 +2766,8 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
        for (i = m->p->InterfaceList; i; i = i->next)
                if (i->Exists)
                        {
        for (i = m->p->InterfaceList; i; i = i->next)
                if (i->Exists)
                        {
-                       NetworkInterfaceInfo *n = &i->ifinfo;
-                       NetworkInterfaceInfoOSX *primary = SearchForInterfaceByName(m, i->ifa_name, i->sa_family);
+                       NetworkInterfaceInfo *const n = &i->ifinfo;
+                       NetworkInterfaceInfoOSX *primary = SearchForInterfaceByName(m, i->ifa_name, AAAA_OVER_V4 ? AF_UNSPEC : i->sa_family);
                        if (!primary) LogMsg("SetupActiveInterfaces ERROR! SearchForInterfaceByName didn't find %s", i->ifa_name);
 
                        if (n->InterfaceID && n->InterfaceID != (mDNSInterfaceID)primary)       // Sanity check
                        if (!primary) LogMsg("SetupActiveInterfaces ERROR! SearchForInterfaceByName didn't find %s", i->ifa_name);
 
                        if (n->InterfaceID && n->InterfaceID != (mDNSInterfaceID)primary)       // Sanity check
@@ -2717,10 +2782,12 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
                                // so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
                                // If n->InterfaceID is NOT set, then we haven't registered it and we should not try to deregister it
                                n->InterfaceID = (mDNSInterfaceID)primary;
                                // so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
                                // If n->InterfaceID is NOT set, then we haven't registered it and we should not try to deregister it
                                n->InterfaceID = (mDNSInterfaceID)primary;
+
                                // If i->LastSeen == utc, then this is a brand-new interface, just created, or an interface that never went away.
                                // If i->LastSeen != utc, then this is an old interface, previously seen, that went away for (utc - i->LastSeen) seconds.
                                // If the interface is an old one that went away and came back in less than a minute, then we're in a flapping scenario.
                                i->Occulting = !(i->ifa_flags & IFF_LOOPBACK) && (utc - i->LastSeen > 0 && utc - i->LastSeen < 60);
                                // If i->LastSeen == utc, then this is a brand-new interface, just created, or an interface that never went away.
                                // If i->LastSeen != utc, then this is an old interface, previously seen, that went away for (utc - i->LastSeen) seconds.
                                // If the interface is an old one that went away and came back in less than a minute, then we're in a flapping scenario.
                                i->Occulting = !(i->ifa_flags & IFF_LOOPBACK) && (utc - i->LastSeen > 0 && utc - i->LastSeen < 60);
+
                                mDNS_RegisterInterface(m, n, i->Flashing && i->Occulting);
                                if (!mDNSAddressIsLinkLocal(&i->ifinfo.ip)) count++;
                                LogOperation("SetupActiveInterfaces:   Registered    %5s(%lu) %.6a InterfaceID %p %#a/%d%s%s%s",
                                mDNS_RegisterInterface(m, n, i->Flashing && i->Occulting);
                                if (!mDNSAddressIsLinkLocal(&i->ifinfo.ip)) count++;
                                LogOperation("SetupActiveInterfaces:   Registered    %5s(%lu) %.6a InterfaceID %p %#a/%d%s%s%s",
@@ -2728,35 +2795,65 @@ mDNSlocal int SetupActiveInterfaces(mDNS *const m, mDNSs32 utc)
                                        i->Flashing        ? " (Flashing)"  : "",
                                        i->Occulting       ? " (Occulting)" : "",
                                        n->InterfaceActive ? " (Primary)"   : "");
                                        i->Flashing        ? " (Flashing)"  : "",
                                        i->Occulting       ? " (Occulting)" : "",
                                        n->InterfaceActive ? " (Primary)"   : "");
-                               }
 
 
-                       if (!n->McastTxRx)
-                               debugf("SetupActiveInterfaces:   No Tx/Rx on   %5s(%lu) %.6a InterfaceID %p %#a", i->ifa_name, i->scope_id, &i->BSSID, primary, &n->ip);
-                       else
-                               {
-                               if (i->sa_family == AF_INET)
+                               if (!n->McastTxRx)
+                                       debugf("SetupActiveInterfaces:   No Tx/Rx on   %5s(%lu) %.6a InterfaceID %p %#a", i->ifa_name, i->scope_id, &i->BSSID, primary, &n->ip);
+                               else
                                        {
                                        {
-                                       struct ip_mreq imr;
-                                       primary->ifa_v4addr.s_addr = i->ifinfo.ip.ip.v4.NotAnInteger;
-                                       imr.imr_multiaddr.s_addr = AllDNSLinkGroup_v4.ip.v4.NotAnInteger;
-                                       imr.imr_interface        = primary->ifa_v4addr;
-                                       mStatus err = setsockopt(m->p->permanentsockets.sktv4, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr));
-                                       // Joining same group twice can give "Address already in use" error -- no need to report that
-                                       if (err < 0 && errno != EADDRINUSE)
-                                               LogMsg("setsockopt - IP_ADD_MEMBERSHIP error %ld errno %d (%s)", err, errno, strerror(errno));
-                                       }
+                                       if (i->sa_family == AF_INET)
+                                               {
+                                               struct ip_mreq imr;
+                                               primary->ifa_v4addr.s_addr = i->ifinfo.ip.ip.v4.NotAnInteger;
+                                               imr.imr_multiaddr.s_addr = AllDNSLinkGroup_v4.ip.v4.NotAnInteger;
+                                               imr.imr_interface        = primary->ifa_v4addr;
+       
+                                               // If this is our *first* IPv4 instance for this interface name, we need to do a IP_DROP_MEMBERSHIP first,
+                                               // before trying to join the group, to clear out stale kernel state which may be lingering.
+                                               // In particular, this happens with removable network interfaces like USB Ethernet adapters -- the kernel has stale state
+                                               // from the last time the USB Ethernet adapter was connected, and part of the kernel thinks we've already joined the group
+                                               // on that interface (so we get EADDRINUSE when we try to join again) but a different part of the kernel thinks we haven't
+                                               // joined the group (so we receive no multicasts). Doing an IP_DROP_MEMBERSHIP before joining seems to flush the stale state.
+                                               // Also, trying to make the code leave the group when the adapter is removed doesn't work either,
+                                               // because by the time we get the configuration change notification, the interface is already gone,
+                                               // so attempts to unsubscribe fail with EADDRNOTAVAIL (errno 49 "Can't assign requested address").
+                                               // <rdar://problem/5585972> IP_ADD_MEMBERSHIP fails for previously-connected removable interfaces
+                                               if (SearchForInterfaceByName(m, i->ifa_name, AF_INET) == i)
+                                                       {
+                                                       LogOperation("SetupActiveInterfaces: %5s(%lu) Doing precautionary IP_DROP_MEMBERSHIP for %.4a on %.4a", i->ifa_name, i->scope_id, &imr.imr_multiaddr, &imr.imr_interface);
+                                                       mStatus err = setsockopt(m->p->permanentsockets.sktv4, IPPROTO_IP, IP_DROP_MEMBERSHIP, &imr, sizeof(imr));
+                                                       if (err < 0 && (errno != EADDRNOTAVAIL || LogAllOperations))
+                                                               LogMsg("setsockopt - IP_DROP_MEMBERSHIP error %ld errno %d (%s)", err, errno, strerror(errno));
+                                                       }
+       
+                                               LogOperation("SetupActiveInterfaces: %5s(%lu) joining IPv4 mcast group %.4a on %.4a", i->ifa_name, i->scope_id, &imr.imr_multiaddr, &imr.imr_interface);
+                                               mStatus err = setsockopt(m->p->permanentsockets.sktv4, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr));
+                                               // Joining same group twice can give "Address already in use" error -- no need to report that
+                                               if (err < 0 && (errno != EADDRINUSE || LogAllOperations))
+                                                       LogMsg("setsockopt - IP_ADD_MEMBERSHIP error %ld errno %d (%s) group %.4a on %.4a", err, errno, strerror(errno), &imr.imr_multiaddr, &imr.imr_interface);
+                                               }
 #ifndef NO_IPV6
 #ifndef NO_IPV6
-                               if (i->sa_family == AF_INET6)
-                                       {
-                                       struct ipv6_mreq i6mr;
-                                       i6mr.ipv6mr_interface = primary->scope_id;
-                                       i6mr.ipv6mr_multiaddr = *(struct in6_addr*)&AllDNSLinkGroup_v6.ip.v6;
-                                       mStatus err = setsockopt(m->p->permanentsockets.sktv6, IPPROTO_IPV6, IPV6_JOIN_GROUP, &i6mr, sizeof(i6mr));
-                                       // Joining same group twice can give "Address already in use" error -- no need to report that
-                                       if (err < 0 && errno != EADDRINUSE)
-                                               LogMsg("setsockopt - IPV6_JOIN_GROUP error %ld errno %d (%s)", err, errno, strerror(errno));
-                                       }
+                                       if (i->sa_family == AF_INET6)
+                                               {
+                                               struct ipv6_mreq i6mr;
+                                               i6mr.ipv6mr_interface = primary->scope_id;
+                                               i6mr.ipv6mr_multiaddr = *(struct in6_addr*)&AllDNSLinkGroup_v6.ip.v6;
+       
+                                               if (SearchForInterfaceByName(m, i->ifa_name, AF_INET6) == i)
+                                                       {
+                                                       LogOperation("SetupActiveInterfaces: %5s(%lu) Doing precautionary IPV6_LEAVE_GROUP for %.16a on %u", i->ifa_name, i->scope_id, &i6mr.ipv6mr_multiaddr, i6mr.ipv6mr_interface);
+                                                       mStatus err = setsockopt(m->p->permanentsockets.sktv6, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &i6mr, sizeof(i6mr));
+                                                       if (err < 0 && (errno != EADDRNOTAVAIL || LogAllOperations))
+                                                               LogMsg("setsockopt - IPV6_LEAVE_GROUP error %ld errno %d (%s) group %.16a on %u", err, errno, strerror(errno), &i6mr.ipv6mr_multiaddr, i6mr.ipv6mr_interface);
+                                                       }
+       
+                                               LogOperation("SetupActiveInterfaces: %5s(%lu) joining IPv6 mcast group %.16a on %u", i->ifa_name, i->scope_id, &i6mr.ipv6mr_multiaddr, i6mr.ipv6mr_interface);
+                                               mStatus err = setsockopt(m->p->permanentsockets.sktv6, IPPROTO_IPV6, IPV6_JOIN_GROUP, &i6mr, sizeof(i6mr));
+                                               // Joining same group twice can give "Address already in use" error -- no need to report that
+                                               if (err < 0 && (errno != EADDRINUSE || LogAllOperations))
+                                                       LogMsg("setsockopt - IPV6_JOIN_GROUP error %ld errno %d (%s) group %.16a on %u", err, errno, strerror(errno), &i6mr.ipv6mr_multiaddr, i6mr.ipv6mr_interface);
+                                               }
 #endif
 #endif
+                                       }
                                }
                        }
        return count;
                                }
                        }
        return count;
@@ -2780,14 +2877,12 @@ mDNSlocal int ClearInactiveInterfaces(mDNS *const m, mDNSs32 utc)
        // We also have to deregister it if the primary interface that it's using for its InterfaceID is going away.
        // We have to do this because mDNSCore will use that InterfaceID when sending packets, and if the memory
        // it refers to has gone away we'll crash.
        // We also have to deregister it if the primary interface that it's using for its InterfaceID is going away.
        // We have to do this because mDNSCore will use that InterfaceID when sending packets, and if the memory
        // it refers to has gone away we'll crash.
-       // Don't actually close the sockets or free the memory yet: When the last representative of an interface goes away
-       // mDNSCore may want to send goodbye packets on that interface. (Not yet implemented, but a good idea anyway.)
        NetworkInterfaceInfoOSX *i;
        int count = 0;
        for (i = m->p->InterfaceList; i; i = i->next)
                {
                // If this interface is no longer active, or its InterfaceID is changing, deregister it
        NetworkInterfaceInfoOSX *i;
        int count = 0;
        for (i = m->p->InterfaceList; i; i = i->next)
                {
                // If this interface is no longer active, or its InterfaceID is changing, deregister it
-               NetworkInterfaceInfoOSX *primary = SearchForInterfaceByName(m, i->ifa_name, i->sa_family);
+               NetworkInterfaceInfoOSX *primary = SearchForInterfaceByName(m, i->ifa_name, AAAA_OVER_V4 ? AF_UNSPEC : i->sa_family);
                if (i->ifinfo.InterfaceID)
                        if (i->Exists == 0 || i->Exists == 2 || i->ifinfo.InterfaceID != (mDNSInterfaceID)primary)
                                {
                if (i->ifinfo.InterfaceID)
                        if (i->Exists == 0 || i->Exists == 2 || i->ifinfo.InterfaceID != (mDNSInterfaceID)primary)
                                {
@@ -2801,14 +2896,17 @@ mDNSlocal int ClearInactiveInterfaces(mDNS *const m, mDNSs32 utc)
                                mDNS_DeregisterInterface(m, &i->ifinfo, i->Flashing && i->Occulting);
                                if (!mDNSAddressIsLinkLocal(&i->ifinfo.ip)) count++;
                                i->ifinfo.InterfaceID = mDNSNULL;
                                mDNS_DeregisterInterface(m, &i->ifinfo, i->Flashing && i->Occulting);
                                if (!mDNSAddressIsLinkLocal(&i->ifinfo.ip)) count++;
                                i->ifinfo.InterfaceID = mDNSNULL;
-                               // NOTE: If n->InterfaceID is set, that means we've called mDNS_RegisterInterface() for this interface,
+                               // NOTE: If i->ifinfo.InterfaceID is set, that means we've called mDNS_RegisterInterface() for this interface,
                                // so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
                                // so we need to make sure we call mDNS_DeregisterInterface() before disposing it.
-                               // If n->InterfaceID is NOT set, then it's not registered and we should not call mDNS_DeregisterInterface() on it.
+                               // If i->ifinfo.InterfaceID is NOT set, then it's not registered and we should not call mDNS_DeregisterInterface() on it.
+
+                               // Caution: If we ever decide to add code here to leave the multicast group, we need to make sure that this
+                               // is the LAST representative of this physical interface, or we'll unsubscribe from the group prematurely.
                                }
                }
 
        // Second pass:
                                }
                }
 
        // Second pass:
-       // Now that everything that's going to deregister has done so, we can close sockets and free the memory
+       // Now that everything that's going to deregister has done so, we can clean up and free the memory
        NetworkInterfaceInfoOSX **p = &m->p->InterfaceList;
        while (*p)
                {
        NetworkInterfaceInfoOSX **p = &m->p->InterfaceList;
        while (*p)
                {
@@ -2953,7 +3051,7 @@ mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDN
                                                                // The option may be in the form of interface=xxx where xxx is an interface name.
                                                                if (strncmp(currentOption, kInterfaceSpecificOption, sizeof(kInterfaceSpecificOption) - 1) == 0)
                                                                        {
                                                                // The option may be in the form of interface=xxx where xxx is an interface name.
                                                                if (strncmp(currentOption, kInterfaceSpecificOption, sizeof(kInterfaceSpecificOption) - 1) == 0)
                                                                        {
-                                                                       NetworkInterfaceInfoOSX *i;
+                                                                       NetworkInterfaceInfoOSX *ni;
                                                                        char    ifname[IF_NAMESIZE+1];
                                                                        mDNSu32 ifindex = 0;
                                                                        // If something goes wrong finding the interface, create the server entry anyhow but mark it as disabled.
                                                                        char    ifname[IF_NAMESIZE+1];
                                                                        mDNSu32 ifindex = 0;
                                                                        // If something goes wrong finding the interface, create the server entry anyhow but mark it as disabled.
@@ -2961,12 +3059,12 @@ mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDN
                                                                        strlcpy(ifname, currentOption + sizeof(kInterfaceSpecificOption)-1, sizeof(ifname));
                                                                        ifindex = if_nametoindex(ifname);
                                                                        if (ifindex == 0) { disabled = 1; LogMsg("RegisterSplitDNS: interfaceSpecific - interface %s not found", ifname); continue; }
                                                                        strlcpy(ifname, currentOption + sizeof(kInterfaceSpecificOption)-1, sizeof(ifname));
                                                                        ifindex = if_nametoindex(ifname);
                                                                        if (ifindex == 0) { disabled = 1; LogMsg("RegisterSplitDNS: interfaceSpecific - interface %s not found", ifname); continue; }
-                                                                       LogOperation("%s: Interface specific entry: %s on %s (%d)", __FUNCTION__, r->domain, ifname, ifindex);
+                                                                       LogOperation("%s: Interface-specific entry: %s on %s (%d)", __FUNCTION__, r->domain, ifname, ifindex);
                                                                        // Find the interface, can't use mDNSPlatformInterfaceIDFromInterfaceIndex
                                                                        // because that will call mDNSMacOSXNetworkChanged if the interface doesn't exist
                                                                        // Find the interface, can't use mDNSPlatformInterfaceIDFromInterfaceIndex
                                                                        // because that will call mDNSMacOSXNetworkChanged if the interface doesn't exist
-                                                                       for (i = m->p->InterfaceList; i; i = i->next)
-                                                                               if (i->ifinfo.InterfaceID && i->scope_id == ifindex) break;
-                                                                       if (i != NULL) interface = i->ifinfo.InterfaceID;
+                                                                       for (ni = m->p->InterfaceList; ni; ni = ni->next)
+                                                                               if (ni->ifinfo.InterfaceID && ni->scope_id == ifindex) break;
+                                                                       if (ni != NULL) interface = ni->ifinfo.InterfaceID;
                                                                        if (interface == mDNSNULL) { disabled = 1; LogMsg("RegisterSplitDNS: interfaceSpecific - index %d (%s) not found", ifindex, ifname); continue; }
                                                                        }
                                                                }
                                                                        if (interface == mDNSNULL) { disabled = 1; LogMsg("RegisterSplitDNS: interfaceSpecific - index %d (%s) not found", ifindex, ifname); continue; }
                                                                        }
                                                                }
@@ -2980,7 +3078,7 @@ mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDN
                                                                if (SetupAddr(&saddr, r->nameserver[n])) LogMsg("RegisterSplitDNS: bad IP address");
                                                                else
                                                                        {
                                                                if (SetupAddr(&saddr, r->nameserver[n])) LogMsg("RegisterSplitDNS: bad IP address");
                                                                else
                                                                        {
-                                                                       DNSServer *s = mDNS_AddDNSServer(m, &d, mDNSInterface_Any, &saddr, r->port ? mDNSOpaque16fromIntVal(r->port) : UnicastDNSPort);
+                                                                       DNSServer *s = mDNS_AddDNSServer(m, &d, interface, &saddr, r->port ? mDNSOpaque16fromIntVal(r->port) : UnicastDNSPort);
                                                                        if (s && disabled) s->teststate = DNSServer_Disabled;
                                                                        }
                                                                }
                                                                        if (s && disabled) s->teststate = DNSServer_Disabled;
                                                                        }
                                                                }
@@ -3009,12 +3107,12 @@ mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDN
        SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:mDNSPlatformSetDNSConfig"), NULL, NULL);
        if (store)
                {
        SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:mDNSPlatformSetDNSConfig"), NULL, NULL);
        if (store)
                {
-               CFDictionaryRef dict = SCDynamicStoreCopyValue(store, NetworkChangedKey_DynamicDNS);
-               if (dict)
+               CFDictionaryRef ddnsdict = SCDynamicStoreCopyValue(store, NetworkChangedKey_DynamicDNS);
+               if (ddnsdict)
                        {
                        if (fqdn)
                                {
                        {
                        if (fqdn)
                                {
-                               CFArrayRef fqdnArray = CFDictionaryGetValue(dict, CFSTR("HostNames"));
+                               CFArrayRef fqdnArray = CFDictionaryGetValue(ddnsdict, CFSTR("HostNames"));
                                if (fqdnArray && CFArrayGetCount(fqdnArray) > 0)
                                        {
                                        // for now, we only look at the first array element.  if we ever support multiple configurations, we will walk the list
                                if (fqdnArray && CFArrayGetCount(fqdnArray) > 0)
                                        {
                                        // for now, we only look at the first array element.  if we ever support multiple configurations, we will walk the list
@@ -3035,7 +3133,7 @@ mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDN
 
                        if (RegDomains)
                                {
 
                        if (RegDomains)
                                {
-                               CFArrayRef regArray = CFDictionaryGetValue(dict, CFSTR("RegistrationDomains"));
+                               CFArrayRef regArray = CFDictionaryGetValue(ddnsdict, CFSTR("RegistrationDomains"));
                                if (regArray && CFArrayGetCount(regArray) > 0)
                                        {
                                        CFDictionaryRef regDict = CFArrayGetValueAtIndex(regArray, 0);
                                if (regArray && CFArrayGetCount(regArray) > 0)
                                        {
                                        CFDictionaryRef regDict = CFArrayGetValueAtIndex(regArray, 0);
@@ -3059,7 +3157,7 @@ mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDN
 
                        if (BrowseDomains)
                                {
 
                        if (BrowseDomains)
                                {
-                               CFArrayRef browseArray = CFDictionaryGetValue(dict, CFSTR("BrowseDomains"));
+                               CFArrayRef browseArray = CFDictionaryGetValue(ddnsdict, CFSTR("BrowseDomains"));
                                if (browseArray)
                                        {
                                        for (i = 0; i < CFArrayGetCount(browseArray); i++)
                                if (browseArray)
                                        {
                                        for (i = 0; i < CFArrayGetCount(browseArray); i++)
@@ -3083,7 +3181,7 @@ mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDN
                                                }
                                        }
                                }
                                                }
                                        }
                                }
-                       CFRelease(dict);
+                       CFRelease(ddnsdict);
                        }
 
                if (RegDomains)
                        }
 
                if (RegDomains)
@@ -3118,56 +3216,50 @@ mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDN
 
                if (setservers || setsearch)
                        {
 
                if (setservers || setsearch)
                        {
-                       CFStringRef key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetDNS);
-                       if (key)
+                       CFDictionaryRef dict = SCDynamicStoreCopyValue(store, NetworkChangedKey_DNS);
+                       if (dict)
                                {
                                {
-                               CFDictionaryRef dict = SCDynamicStoreCopyValue(store, key);
-                               if (dict)
+                               if (setservers)
                                        {
                                        {
-                                       if (setservers)
+                                       CFArrayRef values = CFDictionaryGetValue(dict, kSCPropNetDNSServerAddresses);
+                                       if (values)
                                                {
                                                {
-                                               CFArrayRef values = CFDictionaryGetValue(dict, kSCPropNetDNSServerAddresses);
-                                               if (values)
+                                               for (i = 0; i < CFArrayGetCount(values); i++)
                                                        {
                                                        {
-                                                       for (i = 0; i < CFArrayGetCount(values); i++)
-                                                               {
-                                                               CFStringRef s = CFArrayGetValueAtIndex(values, i);
-                                                               char buf[256];
-                                                               mDNSAddr addr = { mDNSAddrType_IPv4, { { { 0 } } } };
-                                                               if (s && CFStringGetCString(s, buf, 256, kCFStringEncodingUTF8) &&
-                                                                       inet_aton(buf, (struct in_addr *) &addr.ip.v4))
-                                                                       mDNS_AddDNSServer(m, mDNSNULL, mDNSInterface_Any, &addr, UnicastDNSPort);
-                                                               }
+                                                       CFStringRef s = CFArrayGetValueAtIndex(values, i);
+                                                       mDNSAddr addr = { mDNSAddrType_IPv4, { { { 0 } } } };
+                                                       if (s && CFStringGetCString(s, buf, 256, kCFStringEncodingUTF8) &&
+                                                               inet_aton(buf, (struct in_addr *) &addr.ip.v4))
+                                                               mDNS_AddDNSServer(m, mDNSNULL, mDNSInterface_Any, &addr, UnicastDNSPort);
                                                        }
                                                }
                                                        }
                                                }
-                                       if (setsearch)
+                                       }
+                               if (setsearch)
+                                       {
+                                       // Add the manual and/or DHCP-dicovered search domains
+                                       CFArrayRef searchDomains = CFDictionaryGetValue(dict, kSCPropNetDNSSearchDomains);
+                                       if (searchDomains)
                                                {
                                                {
-                                               // Add the manual and/or DHCP-dicovered search domains
-                                               CFArrayRef searchDomains = CFDictionaryGetValue(dict, kSCPropNetDNSSearchDomains);
-                                               if (searchDomains)
+                                               for (i = 0; i < CFArrayGetCount(searchDomains); i++)
                                                        {
                                                        {
-                                                       for (i = 0; i < CFArrayGetCount(searchDomains); i++)
-                                                               {
-                                                               CFStringRef s = CFArrayGetValueAtIndex(searchDomains, i);
-                                                               if (s && CFStringGetCString(s, buf, sizeof(buf), kCFStringEncodingUTF8))
-                                                                       mDNS_AddSearchDomain_CString(buf);
-                                                               }
-                                                       }
-                                               else    // No kSCPropNetDNSSearchDomains, so use kSCPropNetDNSDomainName
-                                                       {
-                                                       // Due to the vagaries of Apple's SystemConfiguration and dnsinfo.h APIs, if there are no search domains
-                                                       // listed, then you're supposed to interpret the "domain" field as also being the search domain, but if
-                                                       // there *are* search domains listed, then you're supposed to ignore the "domain" field completely and
-                                                       // instead use the search domain list as the sole authority for what domains to search and in what order
-                                                       // (and the domain from the "domain" field will also appear somewhere in that list).
-                                                       CFStringRef string = CFDictionaryGetValue(dict, kSCPropNetDNSDomainName);
-                                                       if (string && CFStringGetCString(string, buf, sizeof(buf), kCFStringEncodingUTF8))
+                                                       CFStringRef s = CFArrayGetValueAtIndex(searchDomains, i);
+                                                       if (s && CFStringGetCString(s, buf, sizeof(buf), kCFStringEncodingUTF8))
                                                                mDNS_AddSearchDomain_CString(buf);
                                                        }
                                                }
                                                                mDNS_AddSearchDomain_CString(buf);
                                                        }
                                                }
-                                       CFRelease(dict);
+                                       else    // No kSCPropNetDNSSearchDomains, so use kSCPropNetDNSDomainName
+                                               {
+                                               // Due to the vagaries of Apple's SystemConfiguration and dnsinfo.h APIs, if there are no search domains
+                                               // listed, then you're supposed to interpret the "domain" field as also being the search domain, but if
+                                               // there *are* search domains listed, then you're supposed to ignore the "domain" field completely and
+                                               // instead use the search domain list as the sole authority for what domains to search and in what order
+                                               // (and the domain from the "domain" field will also appear somewhere in that list).
+                                               CFStringRef string = CFDictionaryGetValue(dict, kSCPropNetDNSDomainName);
+                                               if (string && CFStringGetCString(string, buf, sizeof(buf), kCFStringEncodingUTF8))
+                                                       mDNS_AddSearchDomain_CString(buf);
+                                               }
                                        }
                                        }
-                               CFRelease(key);
+                               CFRelease(dict);
                                }
                        }
                CFRelease(store);
                                }
                        }
                CFRelease(store);
@@ -3176,103 +3268,85 @@ mDNSexport void mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDN
 
 mDNSexport mStatus mDNSPlatformGetPrimaryInterface(mDNS *const m, mDNSAddr *v4, mDNSAddr *v6, mDNSAddr *r)
        {
 
 mDNSexport mStatus mDNSPlatformGetPrimaryInterface(mDNS *const m, mDNSAddr *v4, mDNSAddr *v6, mDNSAddr *r)
        {
-       SCDynamicStoreRef       store   = NULL;
-       CFDictionaryRef         dict    = NULL;
-       CFStringRef                     key             = NULL;
-       CFStringRef                     string  = NULL;
-       int                                     nAdditions = 0;
-       int                                     nDeletions = 0;
        char                            buf[256];
        mStatus                         err             = 0;
        char                            buf[256];
        mStatus                         err             = 0;
+       (void)m; // Unused
 
 
-       // get IPv4 settings
-
-       store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:mDNSPlatformGetPrimaryInterface"), NULL, NULL);
-       require_action(store, exit, err = mStatus_UnknownErr);
-
-       key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4);
-       require_action(key, exit, err = mStatus_UnknownErr);
-
-       dict = SCDynamicStoreCopyValue(store, key);
-       require_action(dict, exit, err = mStatus_UnknownErr);
-
-       // handle router changes
-
-       r->type  = mDNSAddrType_IPv4;
-       r->ip.v4 = zerov4Addr;
-        
-       string = CFDictionaryGetValue(dict, kSCPropNetIPv4Router);
-
-       if (string)
-               {
-               struct sockaddr_in saddr;
-
-               if (!CFStringGetCString(string, buf, 256, kCFStringEncodingUTF8))
-                       LogMsg("Could not convert router to CString");
-               else
-                       {
-                       saddr.sin_len = sizeof(saddr);
-                       saddr.sin_family = AF_INET;
-                       saddr.sin_port = 0;
-                       inet_aton(buf, &saddr.sin_addr);
-
-                       if (AddrRequiresPPPConnection((struct sockaddr *)&saddr)) debugf("Ignoring router %s (requires PPP connection)", buf);
-                       else *(in_addr_t *)&r->ip.v4 = saddr.sin_addr.s_addr;
-                       }
-               }
-
-       // handle primary interface changes
-       // if we gained or lost DNS servers (e.g. logged into VPN) "toggle" primary address so it gets re-registered even if it is unchanged
-       if (nAdditions || nDeletions) mDNS_SetPrimaryInterfaceInfo(m, NULL, NULL, NULL);
-
-       string = CFDictionaryGetValue(dict, kSCDynamicStorePropNetPrimaryInterface);
-
-       if (string)
+       SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder:mDNSPlatformGetPrimaryInterface"), NULL, NULL);
+       if (!store) LogMsg("mDNSPlatformGetPrimaryInterface: SCDynamicStoreCreate failed");
+       else
                {
                {
-               mDNSBool HavePrimaryGlobalv6 = mDNSfalse;  // does the primary interface have a global v6 address?
-               struct ifaddrs *ifa = myGetIfAddrs(1);
-
-               *v4 = *v6 = zeroAddr;
-
-               if (!CFStringGetCString(string, buf, 256, kCFStringEncodingUTF8)) { LogMsg("Could not convert router to CString"); goto exit; }
-
-               // find primary interface in list
-               while (ifa && (mDNSIPv4AddressIsZero(v4->ip.v4) || mDNSv4AddressIsLinkLocal(&v4->ip.v4) || !HavePrimaryGlobalv6))
+               CFDictionaryRef dict = SCDynamicStoreCopyValue(store, NetworkChangedKey_IPv4);
+               if (dict)
                        {
                        {
-                       mDNSAddr tmp6 = zeroAddr;
-                       if (!strcmp(buf, ifa->ifa_name))
+                       r->type  = mDNSAddrType_IPv4;
+                       r->ip.v4 = zerov4Addr;
+                       CFStringRef string = CFDictionaryGetValue(dict, kSCPropNetIPv4Router);
+                       if (string)
                                {
                                {
-                               if (ifa->ifa_addr->sa_family == AF_INET)
-                                       {
-                                       if (mDNSIPv4AddressIsZero(v4->ip.v4) || mDNSv4AddressIsLinkLocal(&v4->ip.v4)) SetupAddr(v4, ifa->ifa_addr);
-                                       }
-                               else if (ifa->ifa_addr->sa_family == AF_INET6)
+                               if (!CFStringGetCString(string, buf, 256, kCFStringEncodingUTF8))
+                                       LogMsg("Could not convert router to CString");
+                               else
                                        {
                                        {
-                                       SetupAddr(&tmp6, ifa->ifa_addr);
-                                       if (tmp6.ip.v6.b[0] >> 5 == 1)   // global prefix: 001
-                                               { HavePrimaryGlobalv6 = mDNStrue; *v6 = tmp6; }
+                                       struct sockaddr_in saddr;
+                                       saddr.sin_len = sizeof(saddr);
+                                       saddr.sin_family = AF_INET;
+                                       saddr.sin_port = 0;
+                                       inet_aton(buf, &saddr.sin_addr);
+               
+                                       if (AddrRequiresPPPConnection((struct sockaddr *)&saddr)) debugf("Ignoring router %s (requires PPP connection)", buf);
+                                       else *(in_addr_t *)&r->ip.v4 = saddr.sin_addr.s_addr;
                                        }
                                }
                                        }
                                }
-                       else
+               
+                       string = CFDictionaryGetValue(dict, kSCDynamicStorePropNetPrimaryInterface);
+                       if (string)
                                {
                                {
-                               // We'll take a V6 address from the non-primary interface if the primary interface doesn't have a global V6 address
-                               if (!HavePrimaryGlobalv6 && ifa->ifa_addr->sa_family == AF_INET6 && !v6->ip.v6.b[0])
+                               mDNSBool HavePrimaryGlobalv6 = mDNSfalse;  // does the primary interface have a global v6 address?
+                               struct ifaddrs *ifa = myGetIfAddrs(1);
+               
+                               *v4 = *v6 = zeroAddr;
+               
+                               if (!CFStringGetCString(string, buf, 256, kCFStringEncodingUTF8)) { LogMsg("Could not convert router to CString"); goto exit; }
+               
+                               // find primary interface in list
+                               while (ifa && (mDNSIPv4AddressIsZero(v4->ip.v4) || mDNSv4AddressIsLinkLocal(&v4->ip.v4) || !HavePrimaryGlobalv6))
                                        {
                                        {
-                                       SetupAddr(&tmp6, ifa->ifa_addr);
-                                       if (tmp6.ip.v6.b[0] >> 5 == 1) *v6 = tmp6;
+                                       mDNSAddr tmp6 = zeroAddr;
+                                       if (!strcmp(buf, ifa->ifa_name))
+                                               {
+                                               if (ifa->ifa_addr->sa_family == AF_INET)
+                                                       {
+                                                       if (mDNSIPv4AddressIsZero(v4->ip.v4) || mDNSv4AddressIsLinkLocal(&v4->ip.v4)) SetupAddr(v4, ifa->ifa_addr);
+                                                       }
+                                               else if (ifa->ifa_addr->sa_family == AF_INET6)
+                                                       {
+                                                       SetupAddr(&tmp6, ifa->ifa_addr);
+                                                       if (tmp6.ip.v6.b[0] >> 5 == 1)   // global prefix: 001
+                                                               { HavePrimaryGlobalv6 = mDNStrue; *v6 = tmp6; }
+                                                       }
+                                               }
+                                       else
+                                               {
+                                               // We'll take a V6 address from the non-primary interface if the primary interface doesn't have a global V6 address
+                                               if (!HavePrimaryGlobalv6 && ifa->ifa_addr->sa_family == AF_INET6 && !v6->ip.v6.b[0])
+                                                       {
+                                                       SetupAddr(&tmp6, ifa->ifa_addr);
+                                                       if (tmp6.ip.v6.b[0] >> 5 == 1) *v6 = tmp6;
+                                                       }
+                                               }
+                                       ifa = ifa->ifa_next;
                                        }
                                        }
+               
+                               // Note that while we advertise v6, we still require v4 (possibly NAT'd, but not link-local) because we must use
+                               // V4 to communicate w/ our DNS server
                                }
                                }
-                       ifa = ifa->ifa_next;
+               
+                       exit:
+                       CFRelease(dict);
                        }
                        }
-
-               // Note that while we advertise v6, we still require v4 (possibly NAT'd, but not link-local) because we must use
-               // V4 to communicate w/ our DNS server
+               CFRelease(store);
                }
                }
-
-       exit:
-       if (dict) CFRelease(dict);
-       if (key) CFRelease(key);
-       if (store) CFRelease(store);
        return err;
        }
 
        return err;
        }
 
@@ -3357,7 +3431,7 @@ mDNSexport void SetDomainSecrets(mDNS *m)
        for (client = m->TunnelClients; client; client = client->next)
                {
                LogOperation("SetDomainSecrets: tunnel to %##s marked for deletion", client->dstname.c);
        for (client = m->TunnelClients; client; client = client->next)
                {
                LogOperation("SetDomainSecrets: tunnel to %##s marked for deletion", client->dstname.c);
-               client->markedForDeletion = mDNStrue;
+               client->MarkedForDeletion = mDNStrue;
                }
        }
 #endif APPLE_OSX_mDNSResponder
                }
        }
 #endif APPLE_OSX_mDNSResponder
@@ -3429,7 +3503,7 @@ mDNSexport void SetDomainSecrets(mDNS *m)
                                        if (FoundInList == GetAuthInfoForName_internal(m, &client->dstname))
                                        {
                                        LogOperation("SetDomainSecrets: tunnel to %##s no longer marked for deletion", client->dstname.c);
                                        if (FoundInList == GetAuthInfoForName_internal(m, &client->dstname))
                                        {
                                        LogOperation("SetDomainSecrets: tunnel to %##s no longer marked for deletion", client->dstname.c);
-                                       client->markedForDeletion = mDNSfalse;
+                                       client->MarkedForDeletion = mDNSfalse;
                                        // If the key has changed, reconfigure the tunnel
                                        if (strncmp(stringbuf, client->b64keydata, sizeof(client->b64keydata)))
                                                {
                                        // If the key has changed, reconfigure the tunnel
                                        if (strncmp(stringbuf, client->b64keydata, sizeof(client->b64keydata)))
                                                {
@@ -3486,20 +3560,20 @@ mDNSexport void SetDomainSecrets(mDNS *m)
        #if APPLE_OSX_mDNSResponder
                {
                // clean up ClientTunnels
        #if APPLE_OSX_mDNSResponder
                {
                // clean up ClientTunnels
-               ClientTunnel **ptr = &m->TunnelClients;
-               while (*ptr)
+               ClientTunnel **pp = &m->TunnelClients;
+               while (*pp)
                        {
                        {
-                       if ((*ptr)->markedForDeletion)
+                       if ((*pp)->MarkedForDeletion)
                                {
                                {
-                               ClientTunnel *cur = *ptr;
-                               LogOperation("SetDomainSecrets: removing client %##s from list", cur->dstname.c);
+                               ClientTunnel *cur = *pp;
+                               LogOperation("SetDomainSecrets: removing client %p %##s from list", cur, cur->dstname.c);
                                if (cur->q.ThisQInterval >= 0) mDNS_StopQuery(m, &cur->q);
                                AutoTunnelSetKeys(cur, mDNSfalse);
                                if (cur->q.ThisQInterval >= 0) mDNS_StopQuery(m, &cur->q);
                                AutoTunnelSetKeys(cur, mDNSfalse);
-                               *ptr = cur->next;
+                               *pp = cur->next;
                                freeL("ClientTunnel", cur);
                                }
                        else 
                                freeL("ClientTunnel", cur);
                                }
                        else 
-                               ptr = &(*ptr)->next;
+                               pp = &(*pp)->next;
                        }
 
                DomainAuthInfo *info = m->AuthInfoList;
                        }
 
                DomainAuthInfo *info = m->AuthInfoList;
@@ -3632,7 +3706,7 @@ mDNSlocal void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, v
        int c2 = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_Computername) != 0);
        int c3 = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_DynamicDNS  ) != 0);
        if (c && c - c1 - c2 - c3 == 0) delay = mDNSPlatformOneSecond/20;       // If these were the only changes, shorten delay
        int c2 = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_Computername) != 0);
        int c3 = (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_DynamicDNS  ) != 0);
        if (c && c - c1 - c2 - c3 == 0) delay = mDNSPlatformOneSecond/20;       // If these were the only changes, shorten delay
-
+       
 #if LogAllOperations
        int i;
        for (i=0; i<c; i++)
 #if LogAllOperations
        int i;
        for (i=0; i<c; i++)
@@ -3653,6 +3727,9 @@ mDNSlocal void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, v
                m->p->NetworkChanged - NonZeroTime(m->timenow + delay) < 0)
                m->p->NetworkChanged = NonZeroTime(m->timenow + delay);
 
                m->p->NetworkChanged - NonZeroTime(m->timenow + delay) < 0)
                m->p->NetworkChanged = NonZeroTime(m->timenow + delay);
 
+       // If we have a global DNS change, then disregard delay and reconfigure immediately
+       if (CFArrayContainsValue(changedKeys, range, NetworkChangedKey_DNS) != 0) m->p->NetworkChanged = NonZeroTime(m->timenow);
+
        // KeyChain frequently fails to notify clients of change events. To work around this
        // we set a timer and periodically poll to detect if any changes have occurred.
        // Without this Back To My Mac just does't work for a large number of users.
        // KeyChain frequently fails to notify clients of change events. To work around this
        // we set a timer and periodically poll to detect if any changes have occurred.
        // Without this Back To My Mac just does't work for a large number of users.
@@ -3772,6 +3849,7 @@ mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messag
        mDNS *const m = (mDNS *const)refcon;
        KQueueLock(m);
        (void)service;    // Parameter not used
        mDNS *const m = (mDNS *const)refcon;
        KQueueLock(m);
        (void)service;    // Parameter not used
+       LogOperation("PowerChanged %X %lX", messageType, messageArgument);
        switch(messageType)
                {
                case kIOMessageCanSystemPowerOff:               debugf      ("PowerChanged kIOMessageCanSystemPowerOff (no action)");                           break; // E0000240
        switch(messageType)
                {
                case kIOMessageCanSystemPowerOff:               debugf      ("PowerChanged kIOMessageCanSystemPowerOff (no action)");                           break; // E0000240
@@ -3795,7 +3873,15 @@ mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messag
                                                                                                mDNSMacOSXNetworkChanged(m); mDNSCoreMachineSleep(m, false);                                            break; // E0000320
                default:                                                                LogOperation("PowerChanged unknown message %X", messageType);                                           break;
                }
                                                                                                mDNSMacOSXNetworkChanged(m); mDNSCoreMachineSleep(m, false);                                            break; // E0000320
                default:                                                                LogOperation("PowerChanged unknown message %X", messageType);                                           break;
                }
-       IOAllowPowerChange(m->p->PowerConnection, (long)messageArgument);
+
+       if (!m->p->SleepLimit && messageType == kIOMessageSystemWillSleep)
+               {
+               m->p->SleepLimit  = NonZeroTime(mDNS_TimeNow(m) + mDNSPlatformOneSecond * 5);
+               m->p->SleepCookie = (long)messageArgument;
+               }
+       else
+               IOAllowPowerChange(m->p->PowerConnection, (long)messageArgument);
+
        KQueueUnlock(m, "Sleep/Wake");
        }
 #endif /* NO_IOPOWER */
        KQueueUnlock(m, "Sleep/Wake");
        }
 #endif /* NO_IOPOWER */
@@ -3913,9 +3999,9 @@ mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m)
        m->p->permanentsockets.kqsv4.KQcontext  = m->p->permanentsockets.kqsv6.KQcontext  = &m->p->permanentsockets;
        m->p->permanentsockets.kqsv4.KQtask     = m->p->permanentsockets.kqsv6.KQtask     = "UDP packet reception";
 
        m->p->permanentsockets.kqsv4.KQcontext  = m->p->permanentsockets.kqsv6.KQcontext  = &m->p->permanentsockets;
        m->p->permanentsockets.kqsv4.KQtask     = m->p->permanentsockets.kqsv6.KQtask     = "UDP packet reception";
 
-       err = SetupSocket(&m->p->permanentsockets, MulticastDNSPort, AF_INET);
+       err = SetupSocket(&m->p->permanentsockets, MulticastDNSPort, AF_INET, mDNSNULL);
 #ifndef NO_IPV6
 #ifndef NO_IPV6
-       err = SetupSocket(&m->p->permanentsockets, MulticastDNSPort, AF_INET6);
+       err = SetupSocket(&m->p->permanentsockets, MulticastDNSPort, AF_INET6, mDNSNULL);
 #endif
 
        struct sockaddr_in s4;
 #endif
 
        struct sockaddr_in s4;
@@ -3937,6 +4023,7 @@ mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m)
        m->p->usernicelabel.c[0] = 0;
        m->p->NotifyUser         = 0;
        m->p->KeyChainBugTimer   = 0;
        m->p->usernicelabel.c[0] = 0;
        m->p->NotifyUser         = 0;
        m->p->KeyChainBugTimer   = 0;
+       m->p->SleepLimit         = 0;
 
        m->AutoTunnelHostAddr.b[0] = 0;         // Zero out AutoTunnelHostAddr so UpdateInterfaceList() know it has to set it up
 
 
        m->AutoTunnelHostAddr.b[0] = 0;         // Zero out AutoTunnelHostAddr so UpdateInterfaceList() know it has to set it up
 
index 25fe6a4df8df118cc9cbe7ca4230bdf38a0ef010..a721c1172590260240ce21b1bf5f9cd0a227b7ff 100644 (file)
@@ -17,6 +17,9 @@
     Change History (most recent first):
 
 $Log: mDNSMacOSX.h,v $
     Change History (most recent first):
 
 $Log: mDNSMacOSX.h,v $
+Revision 1.75  2007/12/14 00:45:21  cheshire
+Add SleepLimit and SleepCookie, for when we need to delay sleep until TLS/TCP record deregistration completes
+
 Revision 1.74  2007/11/02 20:18:13  cheshire
 <rdar://problem/5575583> BTMM: Work around keychain notification bug <rdar://problem/5124399>
 
 Revision 1.74  2007/11/02 20:18:13  cheshire
 <rdar://problem/5575583> BTMM: Work around keychain notification bug <rdar://problem/5124399>
 
@@ -171,6 +174,8 @@ struct mDNS_PlatformSupport_struct
        IONotificationPortRef    PowerPortRef;
        io_connect_t             PowerConnection;
        io_object_t              PowerNotifier;
        IONotificationPortRef    PowerPortRef;
        io_connect_t             PowerConnection;
        io_object_t              PowerNotifier;
+       mDNSs32                  SleepLimit;            // Set when we get kIOMessageSystemWillSleep notification
+       long                     SleepCookie;           // Cookie we need to pass to IOAllowPowerChange()
        pthread_mutex_t          BigMutex;
        mDNSs32                  BigMutexStartTime;
        int                                              WakeKQueueLoopFD;
        pthread_mutex_t          BigMutex;
        mDNSs32                  BigMutexStartTime;
        int                                              WakeKQueueLoopFD;
@@ -218,7 +223,7 @@ struct CompileTimeAssertionChecks_mDNSMacOSX
        // other overly-large structures instead of having a pointer to them, can inadvertently
        // cause structure sizes (and therefore memory usage) to balloon unreasonably.
        char sizecheck_NetworkInterfaceInfoOSX[(sizeof(NetworkInterfaceInfoOSX) <=  4100) ? 1 : -1];
        // other overly-large structures instead of having a pointer to them, can inadvertently
        // cause structure sizes (and therefore memory usage) to balloon unreasonably.
        char sizecheck_NetworkInterfaceInfoOSX[(sizeof(NetworkInterfaceInfoOSX) <=  4100) ? 1 : -1];
-       char sizecheck_mDNS_PlatformSupport   [(sizeof(mDNS_PlatformSupport)    <=   260) ? 1 : -1];
+       char sizecheck_mDNS_PlatformSupport   [(sizeof(mDNS_PlatformSupport)    <=   268) ? 1 : -1];
        };
 
 #ifdef  __cplusplus
        };
 
 #ifdef  __cplusplus
index 0454e3e5e820b1e5572e5723be758c05d026104e..904efc0e6e29de639eacf999b8726620460a314e 100644 (file)
@@ -67,7 +67,7 @@
 
 /* Begin PBXBuildFile section */
                2E0405F50C3195F700F13B59 /* helper.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405F40C3195F700F13B59 /* helper.c */; };
 
 /* Begin PBXBuildFile section */
                2E0405F50C3195F700F13B59 /* helper.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405F40C3195F700F13B59 /* helper.c */; };
-               2E0405F60C31961100F13B59 /* helpermsg.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */; settings = {ATTRIBUTES = (Server, Client, ); }; };
+               2E0405F60C31961100F13B59 /* helpermsg.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */; settings = {ATTRIBUTES = (Server, Client, ); COMPILER_FLAGS = "-Wno-error"; }; };
                2E0406150C3197CB00F13B59 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E0406140C3197CB00F13B59 /* libbsm.dylib */; };
                2E04061F0C3198B700F13B59 /* helpermsg.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */; };
                2E0406200C3198B700F13B59 /* helpermsg.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */; };
                2E0406150C3197CB00F13B59 /* libbsm.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E0406140C3197CB00F13B59 /* libbsm.dylib */; };
                2E04061F0C3198B700F13B59 /* helpermsg.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */; };
                2E0406200C3198B700F13B59 /* helpermsg.defs in Sources */ = {isa = PBXBuildFile; fileRef = 2E0405EB0C3190DC00F13B59 /* helpermsg.defs */; };
@@ -83,7 +83,6 @@
                2E8165E80C5980E300485EB2 /* libpfkey.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A8202520C56C36500DDFD48 /* libpfkey.h */; };
                2E8165E90C5980EE00485EB2 /* pfkey.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A8202530C56C36600DDFD48 /* pfkey.c */; };
                2E8165EA0C5980F700485EB2 /* ipsec_strerror.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A8202510C56C36500DDFD48 /* ipsec_strerror.h */; };
                2E8165E80C5980E300485EB2 /* libpfkey.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A8202520C56C36500DDFD48 /* libpfkey.h */; };
                2E8165E90C5980EE00485EB2 /* pfkey.c in Sources */ = {isa = PBXBuildFile; fileRef = 4A8202530C56C36600DDFD48 /* pfkey.c */; };
                2E8165EA0C5980F700485EB2 /* ipsec_strerror.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A8202510C56C36500DDFD48 /* ipsec_strerror.h */; };
-               2E8165F70C59835F00485EB2 /* libipsec.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E8165F60C59835F00485EB2 /* libipsec.dylib */; };
                2E8165F90C59838100485EB2 /* libipsec.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E8165F60C59835F00485EB2 /* libipsec.dylib */; };
                2E96A51D0C39BDAC0087C4D2 /* helper-main.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E0406CA0C31E9AD00F13B59 /* helper-main.c */; };
                2E96A5260C39BE480087C4D2 /* helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E96A5250C39BE480087C4D2 /* helper.h */; };
                2E8165F90C59838100485EB2 /* libipsec.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E8165F60C59835F00485EB2 /* libipsec.dylib */; };
                2E96A51D0C39BDAC0087C4D2 /* helper-main.c in Sources */ = {isa = PBXBuildFile; fileRef = 2E0406CA0C31E9AD00F13B59 /* helper-main.c */; };
                2E96A5260C39BE480087C4D2 /* helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E96A5250C39BE480087C4D2 /* helper.h */; };
                        isa = PBXContainerItemProxy;
                        containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
                        proxyType = 1;
                        isa = PBXContainerItemProxy;
                        containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = D284BE500ADD80740027CCDF /* mDNSResponder */;
+                       remoteGlobalIDString = D284BE500ADD80740027CCDF;
                        remoteInfo = mDNSResponder;
                };
                03067D690C83A3890022BE1F /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
                        proxyType = 1;
                        remoteInfo = mDNSResponder;
                };
                03067D690C83A3890022BE1F /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = D284BE750ADD80800027CCDF /* mDNSResponder debug */;
+                       remoteGlobalIDString = D284BE750ADD80800027CCDF;
                        remoteInfo = "mDNSResponder debug";
                };
                03067D6B0C83A3920022BE1F /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
                        proxyType = 1;
                        remoteInfo = "mDNSResponder debug";
                };
                03067D6B0C83A3920022BE1F /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = D284BEA50ADD80920027CCDF /* dns-sd tool */;
+                       remoteGlobalIDString = D284BEA50ADD80920027CCDF;
                        remoteInfo = "dns-sd tool";
                };
                03067D6D0C83A39C0022BE1F /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
                        proxyType = 1;
                        remoteInfo = "dns-sd tool";
                };
                03067D6D0C83A39C0022BE1F /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = 2E0405EF0C31955500F13B59 /* mDNSResponderHelper */;
+                       remoteGlobalIDString = 2E0405EF0C31955500F13B59;
                        remoteInfo = mDNSResponderHelper;
                };
                03067D850C849CC30022BE1F /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
                        proxyType = 1;
                        remoteInfo = mDNSResponderHelper;
                };
                03067D850C849CC30022BE1F /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
                        proxyType = 1;
-                       remoteGlobalIDString = 03067D640C83A3700022BE1F /* Build Some */;
+                       remoteGlobalIDString = 03067D640C83A3700022BE1F;
                        remoteInfo = "Build Some";
                };
                D284BDEA0ADD77F60027CCDF /* PBXContainerItemProxy */ = {
                        remoteInfo = "Build Some";
                };
                D284BDEA0ADD77F60027CCDF /* PBXContainerItemProxy */ = {
                                2E04070A0C31EEEC00F13B59 /* CoreFoundation.framework in Frameworks */,
                                2E04070B0C31EEEC00F13B59 /* SystemConfiguration.framework in Frameworks */,
                                2E4D9B050C38C19500480551 /* Security.framework in Frameworks */,
                                2E04070A0C31EEEC00F13B59 /* CoreFoundation.framework in Frameworks */,
                                2E04070B0C31EEEC00F13B59 /* SystemConfiguration.framework in Frameworks */,
                                2E4D9B050C38C19500480551 /* Security.framework in Frameworks */,
-                               2E8165F70C59835F00485EB2 /* libipsec.dylib in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        isa = PBXNativeTarget;
                        buildConfigurationList = 2E0405F30C31956600F13B59 /* Build configuration list for PBXNativeTarget "mDNSResponderHelper" */;
                        buildPhases = (
                        isa = PBXNativeTarget;
                        buildConfigurationList = 2E0405F30C31956600F13B59 /* Build configuration list for PBXNativeTarget "mDNSResponderHelper" */;
                        buildPhases = (
+                               030BBED60CE11EEC00472F0C /* ShellScript */,
                                2EC8F8ED0C39CCCA003C9C48 /* Headers */,
                                2E0405ED0C31955500F13B59 /* Sources */,
                                2E0405EE0C31955500F13B59 /* Frameworks */,
                                2EC8F8ED0C39CCCA003C9C48 /* Headers */,
                                2E0405ED0C31955500F13B59 /* Sources */,
                                2E0405EE0C31955500F13B59 /* Frameworks */,
                        isa = PBXNativeTarget;
                        buildConfigurationList = D284BED60ADD80A20027CCDF /* Build configuration list for PBXNativeTarget "dnsextd" */;
                        buildPhases = (
                        isa = PBXNativeTarget;
                        buildConfigurationList = D284BED60ADD80A20027CCDF /* Build configuration list for PBXNativeTarget "dnsextd" */;
                        buildPhases = (
+                               030BBF010CE13A2800472F0C /* ShellScript */,
                                D284BEC20ADD80A20027CCDF /* Headers */,
                                D284BEC40ADD80A20027CCDF /* Sources */,
                                D284BECE0ADD80A20027CCDF /* Frameworks */,
                                D284BEC20ADD80A20027CCDF /* Headers */,
                                D284BEC40ADD80A20027CCDF /* Sources */,
                                D284BECE0ADD80A20027CCDF /* Frameworks */,
                08FB7793FE84155DC02AAC07 /* Project object */ = {
                        isa = PBXProject;
                        buildConfigurationList = D284BE2B0ADD78180027CCDF /* Build configuration list for PBXProject "mDNSResponder" */;
                08FB7793FE84155DC02AAC07 /* Project object */ = {
                        isa = PBXProject;
                        buildConfigurationList = D284BE2B0ADD78180027CCDF /* Build configuration list for PBXProject "mDNSResponder" */;
+                       compatibilityVersion = "Xcode 2.4";
                        hasScannedForEncodings = 1;
                        mainGroup = 08FB7794FE84155DC02AAC07 /* mDNSResponder */;
                        projectDirPath = "";
                        hasScannedForEncodings = 1;
                        mainGroup = 08FB7794FE84155DC02AAC07 /* mDNSResponder */;
                        projectDirPath = "";
 /* End PBXRezBuildPhase section */
 
 /* Begin PBXShellScriptBuildPhase section */
 /* End PBXRezBuildPhase section */
 
 /* Begin PBXShellScriptBuildPhase section */
+               030BBED60CE11EEC00472F0C /* ShellScript */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "if [ -e \"${SDKROOT}/usr/lib/libipsec.dylib\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/ipsec_options.h\"\ntouch \"${CONFIGURATION_TEMP_DIR}/ipsec_options.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libipsec.a\"\nelse\necho \"#define MDNS_NO_IPSEC 1\" > ${CONFIGURATION_TEMP_DIR}/ipsec_options.h\ntouch \"${CONFIGURATION_TEMP_DIR}/empty.c\"\nfor i in ${ARCHS}\ndo\nccflags=\"-arch $i $ccflags\"\ndone\ncc ${ccflags} \"${CONFIGURATION_TEMP_DIR}/empty.c\" -c -o \"${CONFIGURATION_TEMP_DIR}/libipsec.a\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/empty.c\"\nfi\n";
+               };
+               030BBF010CE13A2800472F0C /* ShellScript */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                       );
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "rm -f \"${CONFIGURATION_TEMP_DIR}/ipsec_options.h\"\ntouch \"${CONFIGURATION_TEMP_DIR}/ipsec_options.h\"\n";
+                       showEnvVarsInLog = 0;
+               };
                D284BE510ADD80740027CCDF /* ShellScript */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                D284BE510ADD80740027CCDF /* ShellScript */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        shellPath = /bin/sh;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        shellPath = /bin/sh;
-                       shellScript = "if [ -e /usr/local/include/dnsinfo.h ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/dnsinfo.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${CONFIGURATION_TEMP_DIR}/dnsinfo.h\ntouch ${CONFIGURATION_TEMP_DIR}/empty.c\ncc -arch i386 -arch ppc ${CONFIGURATION_TEMP_DIR}/empty.c -c -o \"${CONFIGURATION_TEMP_DIR}/libdnsinfo.a\"\nrm -f ${CONFIGURATION_TEMP_DIR}/empty.c\nfi\n\nif [ -e /usr/include/sandbox.h ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/sandbox.h\"\nelse\necho \"#define MDNS_NO_SANDBOX 1\" > ${CONFIGURATION_TEMP_DIR}/sandbox.h\nfi\n";
+                       shellScript = "if [ -e \"${SDKROOT}/usr/local/include/dnsinfo.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/dnsinfo.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${CONFIGURATION_TEMP_DIR}/dnsinfo.h\ntouch \"${CONFIGURATION_TEMP_DIR}/empty.c\"\nfor i in ${ARCHS}\ndo\nccflags=\"-arch $i $ccflags\"\ndone\ncc ${ccflags} \"${CONFIGURATION_TEMP_DIR}/empty.c\" -c -o \"${CONFIGURATION_TEMP_DIR}/libdnsinfo.a\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/empty.c\"\nfi\n\nif [ -e \"${SDKROOT}/usr/include/sandbox.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/sandbox.h\"\nelse\necho \"#define MDNS_NO_SANDBOX 1\" > \"${CONFIGURATION_TEMP_DIR}/sandbox.h\"\nfi\n";
                };
                D284BE6C0ADD80740027CCDF /* ShellScript */ = {
                        isa = PBXShellScriptBuildPhase;
                };
                D284BE6C0ADD80740027CCDF /* ShellScript */ = {
                        isa = PBXShellScriptBuildPhase;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        shellPath = /bin/sh;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        shellPath = /bin/sh;
-                       shellScript = "if [ -e /usr/local/include/dnsinfo.h ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/dnsinfo.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${CONFIGURATION_TEMP_DIR}/dnsinfo.h\ntouch ${CONFIGURATION_TEMP_DIR}/empty.c\ncc -arch i386 -arch ppc ${CONFIGURATION_TEMP_DIR}/empty.c -c -o \"${CONFIGURATION_TEMP_DIR}/libdnsinfo.a\"\nrm -f ${CONFIGURATION_TEMP_DIR}/empty.c\nfi\n\nif [ -e /usr/include/sandbox.h ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/sandbox.h\"\nelse\necho \"#define MDNS_NO_SANDBOX 1\" > ${CONFIGURATION_TEMP_DIR}/sandbox.h\nfi\n";
+                       shellScript = "if [ -e \"${SDKROOT}/usr/local/include/dnsinfo.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/dnsinfo.h\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/libdnsinfo.a\"\nelse\necho \"#define MDNS_NO_DNSINFO 1\" > ${CONFIGURATION_TEMP_DIR}/dnsinfo.h\ntouch \"${CONFIGURATION_TEMP_DIR}/empty.c\"\ncc -arch i386 -arch ppc \"${CONFIGURATION_TEMP_DIR}/empty.c\" -c -o \"${CONFIGURATION_TEMP_DIR}/libdnsinfo.a\"\nrm -f \"${CONFIGURATION_TEMP_DIR}/empty.c\"\nfi\n\nif [ -e \"${SDKROOT}/usr/include/sandbox.h\" ]\nthen\nrm -f \"${CONFIGURATION_TEMP_DIR}/sandbox.h\"\nelse\necho \"#define MDNS_NO_SANDBOX 1\" > \"${CONFIGURATION_TEMP_DIR}/sandbox.h\"\nfi\n";
                };
                DB2CC4550662DE1700335AB3 /* ShellScript */ = {
                        isa = PBXShellScriptBuildPhase;
                };
                DB2CC4550662DE1700335AB3 /* ShellScript */ = {
                        isa = PBXShellScriptBuildPhase;
                                HEADER_SEARCH_PATHS = "${CONFIGURATION_TEMP_DIR}";
                                INSTALL_PATH = /usr/sbin;
                                LD_MAP_FILE_PATH = "$(TARGET_TEMP_DIR)/$(PRODUCT_NAME)-LinkMap-$(CURRENT_VARIANT)-$(CURRENT_ARCH).txt";
                                HEADER_SEARCH_PATHS = "${CONFIGURATION_TEMP_DIR}";
                                INSTALL_PATH = /usr/sbin;
                                LD_MAP_FILE_PATH = "$(TARGET_TEMP_DIR)/$(PRODUCT_NAME)-LinkMap-$(CURRENT_VARIANT)-$(CURRENT_ARCH).txt";
+                               LIBRARY_SEARCH_PATHS = "\"${CONFIGURATION_TEMP_DIR}\"";
                                MACOSX_DEPLOYMENT_TARGET = 10.4;
                                MACOSX_DEPLOYMENT_TARGET = 10.4;
+                               OTHER_LDFLAGS = (
+                                       "$(inherited)",
+                                       "-lipsec",
+                               );
                                PREBINDING = NO;
                                PRODUCT_NAME = mDNSResponderHelper;
                        };
                                PREBINDING = NO;
                                PRODUCT_NAME = mDNSResponderHelper;
                        };
                                        "-Wmissing-prototypes",
                                        "-Wno-four-char-constants",
                                        "-Wno-unknown-pragmas",
                                        "-Wmissing-prototypes",
                                        "-Wno-four-char-constants",
                                        "-Wno-unknown-pragmas",
+                                       "-Wshadow",
                                );
                                YACC_GENERATED_FILE_STEM = Standard;
                        };
                                );
                                YACC_GENERATED_FILE_STEM = Standard;
                        };
                                GCC_ENABLE_FIX_AND_CONTINUE = YES;
                                GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
                                INSTALL_PATH = /usr/bin;
                                GCC_ENABLE_FIX_AND_CONTINUE = YES;
                                GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
                                INSTALL_PATH = /usr/bin;
-                               MACOSX_DEPLOYMENT_TARGET = 10.2;
+                               MACOSX_DEPLOYMENT_TARGET = 10.4;
                                OTHER_CFLAGS = "-no-cpp-precomp";
                                OTHER_LDFLAGS = "";
                                OTHER_REZFLAGS = "";
                                OTHER_CFLAGS = "-no-cpp-precomp";
                                OTHER_LDFLAGS = "";
                                OTHER_REZFLAGS = "";
                                GCC_ENABLE_FIX_AND_CONTINUE = YES;
                                GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
                                INSTALL_PATH = "/Library/Application Support/Bonjour";
                                GCC_ENABLE_FIX_AND_CONTINUE = YES;
                                GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
                                INSTALL_PATH = "/Library/Application Support/Bonjour";
-                               MACOSX_DEPLOYMENT_TARGET = 10.3;
+                               MACOSX_DEPLOYMENT_TARGET = 10.4;
                                OTHER_CFLAGS = "";
                                OTHER_LDFLAGS = "";
                                OTHER_REZFLAGS = "";
                                OTHER_CFLAGS = "";
                                OTHER_LDFLAGS = "";
                                OTHER_REZFLAGS = "";
                                GCC_SYMBOLS_PRIVATE_EXTERN = NO;
                                INFOPLIST_FILE = "PreferencePane/Info-PreferencePane.plist";
                                INSTALL_PATH = /AppleInternal/Library/PreferencePanes;
                                GCC_SYMBOLS_PRIVATE_EXTERN = NO;
                                INFOPLIST_FILE = "PreferencePane/Info-PreferencePane.plist";
                                INSTALL_PATH = /AppleInternal/Library/PreferencePanes;
-                               MACOSX_DEPLOYMENT_TARGET = 10.3;
+                               MACOSX_DEPLOYMENT_TARGET = 10.4;
                                OTHER_CFLAGS = "";
                                OTHER_LDFLAGS = "-twolevel_namespace";
                                OTHER_REZFLAGS = "";
                                OTHER_CFLAGS = "";
                                OTHER_LDFLAGS = "-twolevel_namespace";
                                OTHER_REZFLAGS = "";
index b2a4d9df2ce92d97b378fc40d63ccc6ff1ee6169..09448102e4ba5cf821c07d39f9b9aeb57767c249 100644 (file)
@@ -60,6 +60,9 @@
 
 #include "ipsec_strerror.h"
 #include "libpfkey.h"
 
 #include "ipsec_strerror.h"
 #include "libpfkey.h"
+#include "ipsec_options.h"
+
+#ifndef MDNS_NO_IPSEC
 
 #define CALLOC(size, cast) (cast)calloc(1, (size))
 
 
 #define CALLOC(size, cast) (cast)calloc(1, (size))
 
@@ -2124,3 +2127,5 @@ pfkey_setsadbxsa2(buf, lim, mode0, reqid)
 
        return(buf + len);
 }
 
        return(buf + len);
 }
+
+#endif /* ndef MDNS_NO_IPSEC */
index ad1821ca5b0ab5e832980e3b7838e5dcff664d3b..2c9f32f721e12a31a715dc1960082f67ca26bc5f 100755 (executable)
@@ -17,6 +17,9 @@
     Change History (most recent first):
 
 $Log: mDNSUNP.c,v $
     Change History (most recent first):
 
 $Log: mDNSUNP.c,v $
+Revision 1.35  2007/11/15 21:36:19  cheshire
+<rdar://problem/5289340> POSIX: Off by one overflow in get_ifi_info_linuxv6()
+
 Revision 1.34  2006/08/14 23:24:47  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
 Revision 1.34  2006/08/14 23:24:47  cheshire
 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
 
@@ -200,7 +203,7 @@ struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
        FILE *fp;
        char addr[8][5];
        int flags, myflags, index, plen, scope;
        FILE *fp;
        char addr[8][5];
        int flags, myflags, index, plen, scope;
-       char ifname[8], lastname[IFNAMSIZ];
+       char ifname[9], lastname[IFNAMSIZ];
        char addr6[32+7+1]; /* don't forget the seven ':' */
        struct addrinfo hints, *res0;
        struct sockaddr_in6 *sin6;
        char addr6[32+7+1]; /* don't forget the seven ':' */
        struct addrinfo hints, *res0;
        struct sockaddr_in6 *sin6;
index d321b503bed65fc78a31df2816217164143236ac..c1d3b66687bd8f1f5c445eddd0dbb29ef56ab89b 100644 (file)
     Change History (most recent first):
 
 $Log: JNISupport.c,v $
     Change History (most recent first):
 
 $Log: JNISupport.c,v $
+Revision 1.22  2007/11/30 23:38:53  cheshire
+Fix compiler warning:
+/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers/jni.h:609: warning: declaration of 'index' shadows a global declaration
+
 Revision 1.21  2007/09/18 19:09:02  cheshire
 <rdar://problem/5489549> mDNSResponderHelper (and other binaries) missing SCCS version strings
 
 Revision 1.21  2007/09/18 19:09:02  cheshire
 <rdar://problem/5489549> mDNSResponderHelper (and other binaries) missing SCCS version strings
 
@@ -122,9 +126,14 @@ static DWORD       if_nametoindex( const char * nameStr );
 #include <sys/socket.h>
 #include <net/if.h>
 #endif // _WIN32
 #include <sys/socket.h>
 #include <net/if.h>
 #endif // _WIN32
-#include <jni.h>
 
 
+// When compiling with "-Wshadow" set, including jni.h produces the following error:
+// /System/Library/Frameworks/JavaVM.framework/Versions/A/Headers/jni.h:609: warning: declaration of 'index' shadows a global declaration
+// To work around this, we use the preprocessor to map the identifier 'index', which appears harmlessly in function prototype declarations,
+// to something 'jni_index', which doesn't conflict
+#define index jni_index
 #include "DNSSD.java.h"
 #include "DNSSD.java.h"
+#undef index
 
 //#include <syslog.h>
 
 
 //#include <syslog.h>
 
index 08b4945bbd8012712b2f69c1e74ead293ae88239..61c53614b00b8c2b362f96499720a9585046c63b 100644 (file)
     Change History (most recent first):
 
 $Log: PlatformCommon.c,v $
     Change History (most recent first):
 
 $Log: PlatformCommon.c,v $
+Revision 1.14  2007/12/03 18:37:26  cheshire
+Moved mDNSPlatformWriteLogMsg & mDNSPlatformWriteDebugMsg
+from mDNSMacOSX.c to PlatformCommon.c, so that Posix build can use them
+
 Revision 1.13  2007/10/22 20:07:07  cheshire
 Moved mDNSPlatformSourceAddrForDest from mDNSMacOSX.c to PlatformCommon.c so
 Posix build can share the code (better than just pasting it into mDNSPosix.c)
 Revision 1.13  2007/10/22 20:07:07  cheshire
 Moved mDNSPlatformSourceAddrForDest from mDNSMacOSX.c to PlatformCommon.c so
 Posix build can share the code (better than just pasting it into mDNSPosix.c)
@@ -69,6 +73,7 @@ Move ReadDDNSSettingsFromConfFile() from mDNSMacOSX.c to PlatformCommon.c
 #include <errno.h>                             // Needed for errno etc.
 #include <sys/socket.h>                        // Needed for socket() etc.
 #include <netinet/in.h>                        // Needed for sockaddr_in
 #include <errno.h>                             // Needed for errno etc.
 #include <sys/socket.h>                        // Needed for socket() etc.
 #include <netinet/in.h>                        // Needed for sockaddr_in
+#include <syslog.h>
 
 #include "mDNSEmbeddedAPI.h"   // Defines the interface provided to the client layer above
 #include "DNSCommon.h"
 
 #include "mDNSEmbeddedAPI.h"   // Defines the interface provided to the client layer above
 #include "DNSCommon.h"
@@ -179,3 +184,26 @@ mDNSexport void ReadDDNSSettingsFromConfFile(mDNS *const m, const char *const fi
        LogMsg("ERROR: malformatted config file");
        if (f) fclose(f);       
        }
        LogMsg("ERROR: malformatted config file");
        if (f) fclose(f);       
        }
+
+#if MDNS_DEBUGMSGS
+mDNSexport void        mDNSPlatformWriteDebugMsg(const char *msg)
+       {
+       fprintf(stderr,"%s\n", msg);
+       fflush(stderr);
+       }
+#endif
+
+mDNSexport void        mDNSPlatformWriteLogMsg(const char *ident, const char *buffer, int logoptflags)
+       {
+       if (mDNS_DebugMode)     // In debug mode we write to stderr
+               {
+               fprintf(stderr,"%s\n", buffer);
+               fflush(stderr);
+               }
+       else                            // else, in production mode, we write to syslog
+               {
+               openlog(ident, LOG_CONS | logoptflags, LOG_DAEMON);
+               syslog(LOG_ERR, "%s", buffer);
+               closelog();
+               }
+       }
index de5527759cbf2639a004919e1b3180fcc8154ab9..da571b2a5845265449e5a57c6a04ed82bbeae6c8 100644 (file)
@@ -77,7 +77,7 @@
  */
 
 #ifndef _DNS_SD_H
  */
 
 #ifndef _DNS_SD_H
-#define _DNS_SD_H 1640000
+#define _DNS_SD_H 1700000
 
 #ifdef  __cplusplus
     extern "C" {
 
 #ifdef  __cplusplus
     extern "C" {
 #include <sys/types.h>
 
 /* EFI does not have stdint.h, or anything else equivalent */
 #include <sys/types.h>
 
 /* EFI does not have stdint.h, or anything else equivalent */
-#elif defined(EFI32) || defined(EFI64)
+#elif defined(EFI32) || defined(EFI64) || defined(EFIX64)
+#include "Tiano.h"
+#if !defined(_STDINT_H_)
 typedef UINT8       uint8_t;
 typedef INT8        int8_t;
 typedef UINT16      uint16_t;
 typedef INT16       int16_t;
 typedef UINT32      uint32_t;
 typedef INT32       int32_t;
 typedef UINT8       uint8_t;
 typedef INT8        int8_t;
 typedef UINT16      uint16_t;
 typedef INT16       int16_t;
 typedef UINT32      uint32_t;
 typedef INT32       int32_t;
-
+#endif
 /* Windows has its own differences */
 #elif defined(_WIN32)
 #include <windows.h>
 /* Windows has its own differences */
 #elif defined(_WIN32)
 #include <windows.h>
@@ -299,7 +301,7 @@ enum
      * DNSServiceRef's created by other calls like DNSServiceBrowse() or DNSServiceResolve()
      * cannot be shared by copying them and using kDNSServiceFlagsShareConnection.
      *
      * DNSServiceRef's created by other calls like DNSServiceBrowse() or DNSServiceResolve()
      * cannot be shared by copying them and using kDNSServiceFlagsShareConnection.
      *
-     * 3. Don't double-deallocate
+     * 3. Don't Double-Deallocate
      * Calling DNSServiceRefDeallocate(ref) for a particular operation's DNSServiceRef terminates
      * just that operation. Calling DNSServiceRefDeallocate(ref) for the main shared DNSServiceRef
      * (the parent DNSServiceRef, originally created by DNSServiceCreateConnection(&ref))
      * Calling DNSServiceRefDeallocate(ref) for a particular operation's DNSServiceRef terminates
      * just that operation. Calling DNSServiceRefDeallocate(ref) for the main shared DNSServiceRef
      * (the parent DNSServiceRef, originally created by DNSServiceCreateConnection(&ref))
@@ -308,6 +310,13 @@ enum
      * The memory used by those subordinate DNSServiceRef's has already been freed, so any attempt
      * to do a DNSServiceRefDeallocate (or any other operation) on them will result in accesses
      * to freed memory, leading to crashes or other equally undesirable results.
      * The memory used by those subordinate DNSServiceRef's has already been freed, so any attempt
      * to do a DNSServiceRefDeallocate (or any other operation) on them will result in accesses
      * to freed memory, leading to crashes or other equally undesirable results.
+     *
+     * 4. Thread Safety
+     * The dns_sd.h API does not presuppose any particular threading model, and consequently
+     * does no locking of its own (which would require linking some specific threading library).
+     * If client code calls API routines on the same DNSServiceRef concurrently
+     * from multiple threads, it is the client's responsibility to use a mutext
+     * lock or take similar appropriate precautions to serialize those calls.
      */
 
     };
      */
 
     };
@@ -735,7 +744,6 @@ typedef void (DNSSD_API *DNSServiceDomainEnumReply)
 
 
 /* DNSServiceEnumerateDomains() Parameters:
 
 
 /* DNSServiceEnumerateDomains() Parameters:
- *
  *
  * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds
  *                  then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
  *
  * sdRef:           A pointer to an uninitialized DNSServiceRef. If the call succeeds
  *                  then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError,
@@ -781,7 +789,6 @@ DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains
  *********************************************************************************************/
 
 /* Register a service that is discovered via Browse() and Resolve() calls.
  *********************************************************************************************/
 
 /* Register a service that is discovered via Browse() and Resolve() calls.
- *
  *
  * DNSServiceRegisterReply() Callback Parameters:
  *
  *
  * DNSServiceRegisterReply() Callback Parameters:
  *
@@ -953,7 +960,6 @@ DNSServiceErrorType DNSSD_API DNSServiceRegister
  * DNSServiceRef, then it's the caller's responsibility to use a mutext lock
  * or take similar appropriate precautions to serialize those calls.
  *
  * DNSServiceRef, then it's the caller's responsibility to use a mutext lock
  * or take similar appropriate precautions to serialize those calls.
  *
- *
  * Parameters;
  *
  * sdRef:           A DNSServiceRef initialized by DNSServiceRegister().
  * Parameters;
  *
  * sdRef:           A DNSServiceRef initialized by DNSServiceRegister().
@@ -996,7 +1002,6 @@ DNSServiceErrorType DNSSD_API DNSServiceAddRecord
  *   - A record added to a registered service via DNSServiceAddRecord()
  *   - An individual record registered by DNSServiceRegisterRecord()
  *
  *   - A record added to a registered service via DNSServiceAddRecord()
  *   - An individual record registered by DNSServiceRegisterRecord()
  *
- *
  * Parameters:
  *
  * sdRef:           A DNSServiceRef that was initialized by DNSServiceRegister()
  * Parameters:
  *
  * sdRef:           A DNSServiceRef that was initialized by DNSServiceRegister()
@@ -1064,7 +1069,6 @@ DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord
  *********************************************************************************************/
 
 /* Browse for instances of a service.
  *********************************************************************************************/
 
 /* Browse for instances of a service.
- *
  *
  * DNSServiceBrowseReply() Parameters:
  *
  *
  * DNSServiceBrowseReply() Parameters:
  *
@@ -1303,7 +1307,6 @@ DNSServiceErrorType DNSSD_API DNSServiceResolve
  *
  * Query for an arbitrary DNS record.
  *
  *
  * Query for an arbitrary DNS record.
  *
- *
  * DNSServiceQueryRecordReply() Callback Parameters:
  *
  * sdRef:           The DNSServiceRef initialized by DNSServiceQueryRecord().
  * DNSServiceQueryRecordReply() Callback Parameters:
  *
  * sdRef:           The DNSServiceRef initialized by DNSServiceQueryRecord().
@@ -1346,7 +1349,7 @@ DNSServiceErrorType DNSSD_API DNSServiceResolve
 
 typedef void (DNSSD_API *DNSServiceQueryRecordReply)
     (
 
 typedef void (DNSSD_API *DNSServiceQueryRecordReply)
     (
-    DNSServiceRef                       DNSServiceRef,
+    DNSServiceRef                       sdRef,
     DNSServiceFlags                     flags,
     uint32_t                            interfaceIndex,
     DNSServiceErrorType                 errorCode,
     DNSServiceFlags                     flags,
     uint32_t                            interfaceIndex,
     DNSServiceErrorType                 errorCode,
@@ -1422,7 +1425,6 @@ DNSServiceErrorType DNSSD_API DNSServiceQueryRecord
  *
  * Queries for the IP address of a hostname by using either Multicast or Unicast DNS.
  *
  *
  * Queries for the IP address of a hostname by using either Multicast or Unicast DNS.
  *
- *
  * DNSServiceGetAddrInfoReply() parameters:
  *
  * sdRef:           The DNSServiceRef initialized by DNSServiceGetAddrInfo().
  * DNSServiceGetAddrInfoReply() parameters:
  *
  * sdRef:           The DNSServiceRef initialized by DNSServiceGetAddrInfo().
@@ -1538,7 +1540,6 @@ DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo
  * Create a connection to the daemon allowing efficient registration of
  * multiple individual records.
  *
  * Create a connection to the daemon allowing efficient registration of
  * multiple individual records.
  *
- *
  * Parameters:
  *
  * sdRef:           A pointer to an uninitialized DNSServiceRef. Deallocating
  * Parameters:
  *
  * sdRef:           A pointer to an uninitialized DNSServiceRef. Deallocating
@@ -1560,7 +1561,6 @@ DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef);
  * Note that name conflicts occurring for records registered via this call must be handled
  * by the client in the callback.
  *
  * Note that name conflicts occurring for records registered via this call must be handled
  * by the client in the callback.
  *
- *
  * DNSServiceRegisterRecordReply() parameters:
  *
  * sdRef:           The connected DNSServiceRef initialized by
  * DNSServiceRegisterRecordReply() parameters:
  *
  * sdRef:           The connected DNSServiceRef initialized by
@@ -1721,7 +1721,6 @@ DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord
  * port mapping, the client should be prepared to handle these notifications of changes
  * in the environment, and should update its recorded address and/or port as appropriate.
  *
  * port mapping, the client should be prepared to handle these notifications of changes
  * in the environment, and should update its recorded address and/or port as appropriate.
  *
- *
  * DNSServiceNATPortMappingReply() parameters:
  *
  * sdRef:           The DNSServiceRef initialized by DNSServiceNATPortMappingCreate().
  * DNSServiceNATPortMappingReply() parameters:
  *
  * sdRef:           The DNSServiceRef initialized by DNSServiceNATPortMappingCreate().
@@ -2193,7 +2192,7 @@ uint16_t DNSSD_API TXTRecordGetCount
  *
  * txtRecord:       Pointer to the received TXT Record bytes.
  *
  *
  * txtRecord:       Pointer to the received TXT Record bytes.
  *
- * index:           An index into the TXT Record.
+ * itemIndex:       An index into the TXT Record.
  *
  * keyBufLen:       The size of the string buffer being supplied.
  *
  *
  * keyBufLen:       The size of the string buffer being supplied.
  *
@@ -2218,7 +2217,7 @@ DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex
     (
     uint16_t         txtLen,
     const void       *txtRecord,
     (
     uint16_t         txtLen,
     const void       *txtRecord,
-    uint16_t         index,
+    uint16_t         itemIndex,
     uint16_t         keyBufLen,
     char             *key,
     uint8_t          *valueLen,
     uint16_t         keyBufLen,
     char             *key,
     uint8_t          *valueLen,
@@ -2239,7 +2238,6 @@ DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex
  * register in this wide-area domain in addition to .local. In addition, this
  * domain will be returned as a Browse domain via domain enumeration calls.
  *
  * register in this wide-area domain in addition to .local. In addition, this
  * domain will be returned as a Browse domain via domain enumeration calls.
  *
- *
  * Parameters:
  *
  * flags:           Pass kDNSServiceFlagsAdd to add a domain for a user. Call without
  * Parameters:
  *
  * flags:           Pass kDNSServiceFlagsAdd to add a domain for a user. Call without
index a3860f22bd84ae10f8714423a91f401781ae103b..5a6541cf67d3c615f3da6928f7da24eca705bf29 100644 (file)
     Change History (most recent first):
 
 $Log: dnsextd.c,v $
     Change History (most recent first):
 
 $Log: dnsextd.c,v $
+Revision 1.87  2007/12/17 23:34:50  cheshire
+Don't need to set ptr to result of DNSDigest_SignMessage -- ptr is updated anyway (it's passed by reference)
+
+Revision 1.86  2007/12/13 20:22:34  cheshire
+Got rid of redundant SameResourceRecord() routine; replaced calls to this
+with calls to IdenticalResourceRecord() which does exactly the same thing.
+
+Revision 1.85  2007/12/01 00:30:36  cheshire
+Fixed compile warning: declaration of 'time' shadows a global declaration
+
 Revision 1.84  2007/10/24 18:19:37  cheshire
 Fixed header byte order bug sending update responses
 
 Revision 1.84  2007/10/24 18:19:37  cheshire
 Fixed header byte order bug sending update responses
 
@@ -1094,7 +1104,7 @@ mDNSlocal int UpdateSRV(DaemonInfo *d, mDNSBool registration)
 
                if ( zone->updateKeys )
                        {
 
                if ( zone->updateKeys )
                        {
-                       ptr = DNSDigest_SignMessage( &pkt.msg, &ptr, zone->updateKeys, 0 );
+                       DNSDigest_SignMessage( &pkt.msg, &ptr, zone->updateKeys, 0 );
                        require_action( ptr, exit, Log("UpdateSRV: Error constructing lease expiration update" ) );
                        }
 
                        require_action( ptr, exit, Log("UpdateSRV: Error constructing lease expiration update" ) );
                        }
 
@@ -1429,7 +1439,7 @@ mDNSlocal void DeleteOneRecord(DaemonInfo *d, CacheRecord *rr, domainname *zname
 
        if ( zone && zone->updateKeys)
                {
 
        if ( zone && zone->updateKeys)
                {
-               ptr = DNSDigest_SignMessage(&pkt.msg, &ptr, zone->updateKeys, 0 );
+               DNSDigest_SignMessage(&pkt.msg, &ptr, zone->updateKeys, 0 );
                if (!ptr) goto end;
                }
 
                if (!ptr) goto end;
                }
 
@@ -1493,7 +1503,7 @@ mDNSlocal void UpdateLeaseTable(PktMsg *pkt, DaemonInfo *d, mDNSs32 lease)
        LargeCacheRecord lcr;
        ResourceRecord *rr = &lcr.r.resrec;
        const mDNSu8 *ptr, *end;
        LargeCacheRecord lcr;
        ResourceRecord *rr = &lcr.r.resrec;
        const mDNSu8 *ptr, *end;
-       struct timeval time;
+       struct timeval tv;
        DNSQuestion zone;
        char buf[MaxMsg];
        
        DNSQuestion zone;
        char buf[MaxMsg];
        
@@ -1530,7 +1540,7 @@ mDNSlocal void UpdateLeaseTable(PktMsg *pkt, DaemonInfo *d, mDNSs32 lease)
                          if (SameDomainName((*rptr)->rr.resrec.name, rr->name) &&
                                 (DeleteAllRRSets ||
                                 (DeleteOneRRSet && (*rptr)->rr.resrec.rrtype == rr->rrtype) ||
                          if (SameDomainName((*rptr)->rr.resrec.name, rr->name) &&
                                 (DeleteAllRRSets ||
                                 (DeleteOneRRSet && (*rptr)->rr.resrec.rrtype == rr->rrtype) ||
-                                 (DeleteOneRR && SameResourceRecord(&(*rptr)->rr.resrec, rr))))
+                                 (DeleteOneRR && IdenticalResourceRecord(&(*rptr)->rr.resrec, rr))))
                                  {
                                  tmp = *rptr;
                                  VLog("Received deletion update for %s", GetRRDisplayString_rdb(&tmp->rr.resrec, &tmp->rr.resrec.rdata->u, buf));
                                  {
                                  tmp = *rptr;
                                  VLog("Received deletion update for %s", GetRRDisplayString_rdb(&tmp->rr.resrec, &tmp->rr.resrec.rdata->u, buf));
@@ -1544,12 +1554,12 @@ mDNSlocal void UpdateLeaseTable(PktMsg *pkt, DaemonInfo *d, mDNSs32 lease)
                else if (lease > 0)
                        {
                        // see if add or refresh
                else if (lease > 0)
                        {
                        // see if add or refresh
-                       while (*rptr && !SameResourceRecord(&(*rptr)->rr.resrec, rr)) rptr = &(*rptr)->next;
+                       while (*rptr && !IdenticalResourceRecord(&(*rptr)->rr.resrec, rr)) rptr = &(*rptr)->next;
                        if (*rptr)
                                {
                                // refresh
                        if (*rptr)
                                {
                                // refresh
-                               if (gettimeofday(&time, NULL)) { LogErr("UpdateLeaseTable", "gettimeofday"); goto cleanup; }
-                               (*rptr)->expire = time.tv_sec + (unsigned)lease;
+                               if (gettimeofday(&tv, NULL)) { LogErr("UpdateLeaseTable", "gettimeofday"); goto cleanup; }
+                               (*rptr)->expire = tv.tv_sec + (unsigned)lease;
                                VLog("Refreshing lease for %s", GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf));
                                }
                        else
                                VLog("Refreshing lease for %s", GetRRDisplayString_rdb(&lcr.r.resrec, &lcr.r.resrec.rdata->u, buf));
                                }
                        else
@@ -1561,7 +1571,7 @@ mDNSlocal void UpdateLeaseTable(PktMsg *pkt, DaemonInfo *d, mDNSs32 lease)
                                        bucket = rr->namehash % d->nbuckets;
                                        rptr = &d->table[bucket];
                                        }
                                        bucket = rr->namehash % d->nbuckets;
                                        rptr = &d->table[bucket];
                                        }
-                               if (gettimeofday(&time, NULL)) { LogErr("UpdateLeaseTable", "gettimeofday"); goto cleanup; }
+                               if (gettimeofday(&tv, NULL)) { LogErr("UpdateLeaseTable", "gettimeofday"); goto cleanup; }
                                allocsize = sizeof(RRTableElem);
                                if (rr->rdlength > InlineCacheRDSize) allocsize += (rr->rdlength - InlineCacheRDSize);
                                tmp = malloc(allocsize);
                                allocsize = sizeof(RRTableElem);
                                if (rr->rdlength > InlineCacheRDSize) allocsize += (rr->rdlength - InlineCacheRDSize);
                                tmp = malloc(allocsize);
@@ -1570,7 +1580,7 @@ mDNSlocal void UpdateLeaseTable(PktMsg *pkt, DaemonInfo *d, mDNSs32 lease)
                                tmp->rr.resrec.rdata = (RData *)&tmp->rr.rdatastorage;
                                AssignDomainName(&tmp->name, rr->name);
                                tmp->rr.resrec.name = &tmp->name;
                                tmp->rr.resrec.rdata = (RData *)&tmp->rr.rdatastorage;
                                AssignDomainName(&tmp->name, rr->name);
                                tmp->rr.resrec.name = &tmp->name;
-                               tmp->expire = time.tv_sec + (unsigned)lease;
+                               tmp->expire = tv.tv_sec + (unsigned)lease;
                                tmp->cli.sin_addr = pkt->src.sin_addr;
                                AssignDomainName(&tmp->zone, &zone.qname);
                                tmp->next = d->table[bucket];
                                tmp->cli.sin_addr = pkt->src.sin_addr;
                                AssignDomainName(&tmp->zone, &zone.qname);
                                tmp->next = d->table[bucket];
@@ -1953,7 +1963,7 @@ mDNSlocal void *UpdateAnswerList(void *args)
                {
                for (na = &NewAnswers; *na; na = &(*na)->next)
                        {
                {
                for (na = &NewAnswers; *na; na = &(*na)->next)
                        {
-                       if (SameResourceRecord(&(*ka)->resrec, &(*na)->resrec))
+                       if (IdenticalResourceRecord(&(*ka)->resrec, &(*na)->resrec))
                                { (*ka)->resrec.rroriginalttl = 0; break; } // 0 means no change
                        }
                }
                                { (*ka)->resrec.rroriginalttl = 0; break; } // 0 means no change
                        }
                }
@@ -1963,7 +1973,7 @@ mDNSlocal void *UpdateAnswerList(void *args)
        while (*na)
                {
                for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next)
        while (*na)
                {
                for (ka = &a->KnownAnswers; *ka; ka = &(*ka)->next)
-                       if (SameResourceRecord(&(*ka)->resrec, &(*na)->resrec)) break;
+                       if (IdenticalResourceRecord(&(*ka)->resrec, &(*na)->resrec)) break;
                if (!*ka)
                        {
                        // answer is not in list - splice from NewAnswers list, add to Event list
                if (!*ka)
                        {
                        // answer is not in list - splice from NewAnswers list, add to Event list
@@ -2708,19 +2718,18 @@ RecvUDPMessage
 
        if ( IsNotify( &context->pkt ) )
                {
 
        if ( IsNotify( &context->pkt ) )
                {
-               int err = RecvNotify( self, &context->pkt );
+               int e = RecvNotify( self, &context->pkt );
                free(context);
                free(context);
-               return err;
+               return e;
                }
        else if ( IsAuthorized( context->d, &context->pkt, &key, &rcode, &tcode ) )
                {
                if ( IsLLQRequest( &context->pkt ) )
                        {
                        // LLQ messages handled by main thread
                }
        else if ( IsAuthorized( context->d, &context->pkt, &key, &rcode, &tcode ) )
                {
                if ( IsLLQRequest( &context->pkt ) )
                        {
                        // LLQ messages handled by main thread
-
-                       int err = RecvLLQ( self, &context->pkt, NULL );
+                       int e = RecvLLQ( self, &context->pkt, NULL );
                        free(context);
                        free(context);
-                       return err;
+                       return e;
                        }
 
                if ( IsLLQAck(&context->pkt ) )
                        }
 
                if ( IsLLQAck(&context->pkt ) )
@@ -2739,15 +2748,15 @@ RecvUDPMessage
        else
                {
                PktMsg reply;
        else
                {
                PktMsg reply;
-               int    res;
+               int    e;
 
                memcpy( &reply, &context->pkt, sizeof( PktMsg ) );
 
                reply.msg.h.flags.b[0]  =  kDNSFlag0_QR_Response | kDNSFlag0_AA | kDNSFlag0_RD;
                reply.msg.h.flags.b[1]  =  kDNSFlag1_RA | kDNSFlag1_RC_NXDomain;
 
 
                memcpy( &reply, &context->pkt, sizeof( PktMsg ) );
 
                reply.msg.h.flags.b[0]  =  kDNSFlag0_QR_Response | kDNSFlag0_AA | kDNSFlag0_RD;
                reply.msg.h.flags.b[1]  =  kDNSFlag1_RA | kDNSFlag1_RC_NXDomain;
 
-               res = sendto( sd, &reply.msg, reply.len, 0, ( struct sockaddr* ) &context->pkt.src, sizeof( context->pkt.src ) );
-               require_action_quiet( res == ( int ) reply.len, exit, LogErr( "RecvUDPMessage", "sendto" ) );
+               e = sendto( sd, &reply.msg, reply.len, 0, ( struct sockaddr* ) &context->pkt.src, sizeof( context->pkt.src ) );
+               require_action_quiet( e == ( int ) reply.len, exit, LogErr( "RecvUDPMessage", "sendto" ) );
 
                err = mStatus_NoAuth;
                }
 
                err = mStatus_NoAuth;
                }
index f32351f218859a0311e8a861c7ed592e5d2b2431..01ffaff9fbf4d601579b49cdf94530f4a2ec670d 100644 (file)
@@ -28,6 +28,9 @@
    Change History (most recent first):
 
 $Log: dnssd_clientlib.c,v $
    Change History (most recent first):
 
 $Log: dnssd_clientlib.c,v $
+Revision 1.18  2007/11/30 23:06:10  cheshire
+Fixed compile warning: declaration of 'index' shadows a global declaration
+
 Revision 1.17  2007/10/02 19:36:04  cheshire
 <rdar://problem/5516444> TXTRecordGetValuePtr should be case-insenstive
 
 Revision 1.17  2007/10/02 19:36:04  cheshire
 <rdar://problem/5516444> TXTRecordGetValuePtr should be case-insenstive
 
@@ -353,7 +356,7 @@ DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex
        (
        uint16_t         txtLen,
        const void       *txtRecord,
        (
        uint16_t         txtLen,
        const void       *txtRecord,
-       uint16_t         index,
+       uint16_t         itemIndex,
        uint16_t         keyBufLen,
        char             *key,
        uint8_t          *valueLen,
        uint16_t         keyBufLen,
        char             *key,
        uint8_t          *valueLen,
@@ -363,7 +366,7 @@ DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex
        uint16_t count = 0;
        uint8_t *p = (uint8_t*)txtRecord;
        uint8_t *e = p + txtLen;
        uint16_t count = 0;
        uint8_t *p = (uint8_t*)txtRecord;
        uint8_t *e = p + txtLen;
-       while (p<e && count<index) { p += 1 + p[0]; count++; }  // Find requested item
+       while (p<e && count<itemIndex) { p += 1 + p[0]; count++; }      // Find requested item
        if (p<e && p + 1 + p[0] <= e)   // If valid
                {
                uint8_t *x = p+1;
        if (p<e && p + 1 + p[0] <= e)   // If valid
                {
                uint8_t *x = p+1;
index 0b02ad809e0ccf7ad77aef83862ac01e8c1be21a..3bd7c1ff186757a172590d89bc6709ef59845d5a 100644 (file)
@@ -25,6 +25,9 @@
        Change History (most recent first):
 
 $Log: dnssd_clientshim.c,v $
        Change History (most recent first):
 
 $Log: dnssd_clientshim.c,v $
+Revision 1.16  2007/11/30 20:12:24  cheshire
+Removed unused "badparam:" label
+
 Revision 1.15  2007/07/27 19:30:41  cheshire
 Changed mDNSQuestionCallback parameter from mDNSBool to QC_result,
 to properly reflect tri-state nature of the possible responses
 Revision 1.15  2007/07/27 19:30:41  cheshire
 Changed mDNSQuestionCallback parameter from mDNSBool to QC_result,
 to properly reflect tri-state nature of the possible responses
@@ -711,8 +714,6 @@ DNSServiceErrorType DNSServiceQueryRecord
        *sdRef = (DNSServiceRef)x;
        return(mStatus_NoError);
 
        *sdRef = (DNSServiceRef)x;
        return(mStatus_NoError);
 
-badparam:
-       err = mStatus_BadParamErr;
 fail:
        LogMsg("DNSServiceQueryRecord(\"%s\", %d, %d) failed: %s (%ld)", fullname, rrtype, rrclass, errormsg, err);
        return(err);
 fail:
        LogMsg("DNSServiceQueryRecord(\"%s\", %d, %d) failed: %s (%ld)", fullname, rrtype, rrclass, errormsg, err);
        return(err);
index bc47f6b72d0e6ae8b8ea94a0cf9a59b51bc443eb..d197344ce868ba98a07d9921b6fe3c9159202d86 100644 (file)
        Change History (most recent first):
 
 $Log: dnssd_clientstub.c,v $
        Change History (most recent first):
 
 $Log: dnssd_clientstub.c,v $
+Revision 1.100  2007/11/02 17:56:37  cheshire
+<rdar://problem/5565787> Bonjour API broken for 64-bit apps (SCM_RIGHTS sendmsg fails)
+Wrap hack code in "#if APPLE_OSX_mDNSResponder" since (as far as we know right now)
+we don't want to do this on 64-bit Linux, Solaris, etc.
+
+Revision 1.99  2007/11/02 17:29:40  cheshire
+<rdar://problem/5565787> Bonjour API broken for 64-bit apps (SCM_RIGHTS sendmsg fails)
+To get 64-bit code that works, we need to NOT use the standard CMSG_* macros
+
+Revision 1.98  2007/11/01 19:52:43  cheshire
+Wrap debugging messages in "#if DEBUG_64BIT_SCM_RIGHTS"
+
+Revision 1.97  2007/11/01 19:45:55  cheshire
+Added "DEBUG_64BIT_SCM_RIGHTS" debugging code
+See <rdar://problem/5565787> Bonjour API broken for 64-bit apps (SCM_RIGHTS sendmsg fails)
+
+Revision 1.96  2007/11/01 15:59:33  cheshire
+umask not being set and restored properly in USE_NAMED_ERROR_RETURN_SOCKET code
+(no longer used on OS X, but relevant for other platforms)
+
+Revision 1.95  2007/10/31 20:07:16  cheshire
+<rdar://problem/5541498> Set SO_NOSIGPIPE on client socket
+Refinement: the cleanup code still needs to close listenfd when necesssary
+
+Revision 1.94  2007/10/15 22:34:27  cheshire
+<rdar://problem/5541498> Set SO_NOSIGPIPE on client socket
+
 Revision 1.93  2007/10/10 00:48:54  cheshire
 <rdar://problem/5526379> Daemon spins in an infinite loop when it doesn't get the control message it's expecting
 
 Revision 1.93  2007/10/10 00:48:54  cheshire
 <rdar://problem/5526379> Daemon spins in an infinite loop when it doesn't get the control message it's expecting
 
@@ -480,6 +507,9 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f
                }
        else
                {
                }
        else
                {
+               #ifdef SO_NOSIGPIPE
+               const unsigned long optval = 1;
+               #endif
                *ref = NULL;
                sdr->sockfd    = socket(AF_DNSSD, SOCK_STREAM, 0);
                sdr->validator = sdr->sockfd ^ ValidatorBits;
                *ref = NULL;
                sdr->sockfd    = socket(AF_DNSSD, SOCK_STREAM, 0);
                sdr->validator = sdr->sockfd ^ ValidatorBits;
@@ -489,6 +519,11 @@ static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags f
                        FreeDNSServiceOp(sdr);
                        return kDNSServiceErr_NoMemory;
                        }
                        FreeDNSServiceOp(sdr);
                        return kDNSServiceErr_NoMemory;
                        }
+               #ifdef SO_NOSIGPIPE
+               // Some environments (e.g. OS X) support turning off SIGPIPE for a socket
+               if (setsockopt(sdr->sockfd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)) < 0)
+                       syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: SO_NOSIGPIPE failed %d %s", errno, strerror(errno));
+               #endif
                #if defined(USE_TCP_LOOPBACK)
                saddr.sin_family      = AF_INET;
                saddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
                #if defined(USE_TCP_LOOPBACK)
                saddr.sin_family      = AF_INET;
                saddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR);
@@ -565,8 +600,9 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
                        }
                #elif defined(USE_NAMED_ERROR_RETURN_SOCKET)
                        {
                        }
                #elif defined(USE_NAMED_ERROR_RETURN_SOCKET)
                        {
+                       mode_t mask;
+                       int bindresult;
                        dnssd_sockaddr_t caddr;
                        dnssd_sockaddr_t caddr;
-                       mode_t mask = umask(0);
                        listenfd = socket(AF_DNSSD, SOCK_STREAM, 0);
                        if (!dnssd_SocketValid(listenfd)) goto cleanup;
 
                        listenfd = socket(AF_DNSSD, SOCK_STREAM, 0);
                        if (!dnssd_SocketValid(listenfd)) goto cleanup;
 
@@ -577,8 +613,10 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
                        caddr.sun_len = sizeof(struct sockaddr_un);
                        #endif
                        strcpy(caddr.sun_path, data);
                        caddr.sun_len = sizeof(struct sockaddr_un);
                        #endif
                        strcpy(caddr.sun_path, data);
+                       mask = umask(0);
+                       bindresult = bind(listenfd, (struct sockaddr *)&caddr, sizeof(caddr));
                        umask(mask);
                        umask(mask);
-                       if (bind(listenfd, (struct sockaddr *)&caddr, sizeof(caddr)) < 0) goto cleanup;
+                       if (bindresult < 0) goto cleanup;
                        listen(listenfd, 1);
                        }
                #else
                        listen(listenfd, 1);
                        }
                #else
@@ -634,29 +672,66 @@ static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr)
                errsd = accept(listenfd, (struct sockaddr *)&daddr, &len);
                if (!dnssd_SocketValid(errsd)) goto cleanup;
 #else
                errsd = accept(listenfd, (struct sockaddr *)&daddr, &len);
                if (!dnssd_SocketValid(errsd)) goto cleanup;
 #else
+
+#if APPLE_OSX_mDNSResponder
+// On Leopard, the stock definitions of the CMSG_* macros in /usr/include/sys/socket.h,
+// while arguably correct in theory, nonetheless in practice produce code that doesn't work on 64-bit machines
+// For details see <rdar://problem/5565787> Bonjour API broken for 64-bit apps (SCM_RIGHTS sendmsg fails)
+#undef  CMSG_DATA
+#define CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + (sizeof(struct cmsghdr)))
+#undef  CMSG_SPACE
+#define CMSG_SPACE(l)   ((sizeof(struct cmsghdr)) + (l))
+#undef  CMSG_LEN
+#define CMSG_LEN(l)     ((sizeof(struct cmsghdr)) + (l))
+#endif
+
                struct iovec vec = { ((char *)hdr) + sizeof(ipc_msg_hdr) + datalen, 1 }; // Send the last byte along with the SCM_RIGHTS
                struct msghdr msg;
                struct cmsghdr *cmsg;
                struct iovec vec = { ((char *)hdr) + sizeof(ipc_msg_hdr) + datalen, 1 }; // Send the last byte along with the SCM_RIGHTS
                struct msghdr msg;
                struct cmsghdr *cmsg;
-               char cbuf[sizeof(struct cmsghdr) + sizeof(dnssd_sock_t)];
+               char cbuf[CMSG_SPACE(sizeof(dnssd_sock_t))];
                msg.msg_name       = 0;
                msg.msg_namelen    = 0;
                msg.msg_iov        = &vec;
                msg.msg_iovlen     = 1;
                msg.msg_control    = cbuf;
                msg.msg_name       = 0;
                msg.msg_namelen    = 0;
                msg.msg_iov        = &vec;
                msg.msg_iovlen     = 1;
                msg.msg_control    = cbuf;
-               msg.msg_controllen = sizeof(cbuf);
+               msg.msg_controllen = CMSG_LEN(sizeof(dnssd_sock_t));
                msg.msg_flags      = 0;
                cmsg = CMSG_FIRSTHDR(&msg);
                msg.msg_flags      = 0;
                cmsg = CMSG_FIRSTHDR(&msg);
-               cmsg->cmsg_len     = sizeof(cbuf);
+               cmsg->cmsg_len     = CMSG_LEN(sizeof(dnssd_sock_t));
                cmsg->cmsg_level   = SOL_SOCKET;
                cmsg->cmsg_type    = SCM_RIGHTS;
                *((dnssd_sock_t *)CMSG_DATA(cmsg)) = listenfd;
                cmsg->cmsg_level   = SOL_SOCKET;
                cmsg->cmsg_type    = SCM_RIGHTS;
                *((dnssd_sock_t *)CMSG_DATA(cmsg)) = listenfd;
+
 #if TEST_KQUEUE_CONTROL_MESSAGE_BUG
                sleep(1);
 #endif
 #if TEST_KQUEUE_CONTROL_MESSAGE_BUG
                sleep(1);
 #endif
+
+#if DEBUG_64BIT_SCM_RIGHTS
+               syslog(LOG_WARNING, "dnssd_clientstub sendmsg read sd=%d write sd=%d %ld %ld %ld/%ld/%ld/%ld",
+                       errsd, listenfd, sizeof(dnssd_sock_t), sizeof(void*),
+                       sizeof(struct cmsghdr) + sizeof(dnssd_sock_t),
+                       CMSG_LEN(sizeof(dnssd_sock_t)), (long)CMSG_SPACE(sizeof(dnssd_sock_t)),
+                       (long)((char*)CMSG_DATA(cmsg) + 4 - cbuf));
+#endif DEBUG_64BIT_SCM_RIGHTS
+
                if (sendmsg(sdr->sockfd, &msg, 0) < 0)
                if (sendmsg(sdr->sockfd, &msg, 0) < 0)
+                       {
                        syslog(LOG_WARNING, "dnssd_clientstub ERROR: sendmsg failed read sd=%d write sd=%d errno %d (%s)",
                                errsd, listenfd, errno, strerror(errno));
                        syslog(LOG_WARNING, "dnssd_clientstub ERROR: sendmsg failed read sd=%d write sd=%d errno %d (%s)",
                                errsd, listenfd, errno, strerror(errno));
+                       err = kDNSServiceErr_Incompatible;
+                       goto cleanup;
+                       }
+
+#if DEBUG_64BIT_SCM_RIGHTS
+               syslog(LOG_WARNING, "dnssd_clientstub sendmsg read sd=%d write sd=%d okay", errsd, listenfd);
+#endif DEBUG_64BIT_SCM_RIGHTS
+
 #endif
 #endif
+               // Close our end of the socketpair *before* blocking in read_all to get the four-byte error code.
+               // Otherwise, if the daemon closes our socket (or crashes), we block in read_all() forever
+               // because the socket is not closed (we still have an open reference to it ourselves).
+               dnssd_close(listenfd);
+               listenfd = dnssd_InvalidSocket;         // Make sure we don't close it a second time in the cleanup handling below
                }
 
        // At this point we may block in read_all for a few milliseconds waiting for the daemon to send us the error code,
                }
 
        // At this point we may block in read_all for a few milliseconds waiting for the daemon to send us the error code,
index ca3eda963dbad7fd939b6836cb833e1c6140ae82..4d0adbc6891b793837e3cb7531a279d3e4c7aa75 100644 (file)
@@ -23,6 +23,9 @@
     Change History (most recent first):
 
 $Log: mDNSDebug.c,v $
     Change History (most recent first):
 
 $Log: mDNSDebug.c,v $
+Revision 1.13  2007/12/01 00:40:30  cheshire
+Fixes from Bob Bradley for building on EFI
+
 Revision 1.12  2007/10/01 19:06:19  cheshire
 Defined symbolic constant MDNS_LOG_INITIAL_LEVEL to set the logging level we start out at
 
 Revision 1.12  2007/10/01 19:06:19  cheshire
 Defined symbolic constant MDNS_LOG_INITIAL_LEVEL to set the logging level we start out at
 
@@ -68,14 +71,11 @@ Changes necessary to support mDNSResponder on Linux.
 
 #include <stdio.h>
 
 
 #include <stdio.h>
 
-#if defined(WIN32)
-// Need to add Windows syslog support here
+#if defined(WIN32) || defined(EFI32) || defined(EFI64) || defined(EFIX64)
+// Need to add Windows/EFI syslog support here
 #define LOG_PID 0x01
 #define LOG_CONS 0x02
 #define LOG_PERROR 0x20
 #define LOG_PID 0x01
 #define LOG_CONS 0x02
 #define LOG_PERROR 0x20
-#define openlog(A,B,C) (void)(A); (void)(B)
-#define syslog(A,B,C)
-#define closelog()
 #else
 #include <syslog.h>
 #endif
 #else
 #include <syslog.h>
 #endif
@@ -95,44 +95,27 @@ mDNSexport int mDNS_DebugMode = mDNSfalse;
 #if MDNS_DEBUGMSGS
 mDNSexport void debugf_(const char *format, ...)
        {
 #if MDNS_DEBUGMSGS
 mDNSexport void debugf_(const char *format, ...)
        {
-       unsigned char buffer[512];
+       char buffer[512];
        va_list ptr;
        va_start(ptr,format);
        va_list ptr;
        va_start(ptr,format);
-       buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
+       buffer[mDNS_vsnprintf(buffer, sizeof(buffer), format, ptr)] = 0;
        va_end(ptr);
        va_end(ptr);
-       fprintf(stderr,"%s\n", buffer);
-       fflush(stderr);
+       mDNSPlatformWriteDebugMsg(buffer);
        }
 #endif
 
 #if MDNS_DEBUGMSGS > 1
 mDNSexport void verbosedebugf_(const char *format, ...)
        {
        }
 #endif
 
 #if MDNS_DEBUGMSGS > 1
 mDNSexport void verbosedebugf_(const char *format, ...)
        {
-       unsigned char buffer[512];
+       char buffer[512];
        va_list ptr;
        va_start(ptr,format);
        va_list ptr;
        va_start(ptr,format);
-       buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
+       buffer[mDNS_vsnprintf(buffer, sizeof(buffer), format, ptr)] = 0;
        va_end(ptr);
        va_end(ptr);
-       fprintf(stderr,"%s\n", buffer);
-       fflush(stderr);
+       mDNSPlatformWriteDebugMsg(buffer);
        }
 #endif
 
        }
 #endif
 
-mDNSlocal void WriteLogMsg(const char *ident, const char *buffer, int logoptflags)
-       {
-       if (mDNS_DebugMode)     // In debug mode we write to stderr
-               {
-               fprintf(stderr,"%s\n", buffer);
-               fflush(stderr);
-               }
-       else                            // else, in production mode, we write to syslog
-               {
-               openlog(ident, LOG_CONS | logoptflags, LOG_DAEMON);
-               syslog(LOG_ERR, "%s", buffer);
-               closelog();
-               }
-       }
-
 // Log message with default "mDNSResponder" ident string at the start
 mDNSexport void LogMsg(const char *format, ...)
        {
 // Log message with default "mDNSResponder" ident string at the start
 mDNSexport void LogMsg(const char *format, ...)
        {
@@ -141,7 +124,7 @@ mDNSexport void LogMsg(const char *format, ...)
        va_start(ptr,format);
        buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
        va_end(ptr);
        va_start(ptr,format);
        buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
        va_end(ptr);
-       WriteLogMsg(ProgramName, buffer, 0);
+       mDNSPlatformWriteLogMsg(ProgramName, buffer, 0);
        }
 
 // Log message with specified ident string at the start
        }
 
 // Log message with specified ident string at the start
@@ -152,7 +135,7 @@ mDNSexport void LogMsgIdent(const char *ident, const char *format, ...)
        va_start(ptr,format);
        buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
        va_end(ptr);
        va_start(ptr,format);
        buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
        va_end(ptr);
-       WriteLogMsg(ident, buffer, ident && *ident ? LOG_PID : 0);
+       mDNSPlatformWriteLogMsg(ident, buffer, ident && *ident ? LOG_PID : 0);
        }
 
 // Log message with no ident string at the start
        }
 
 // Log message with no ident string at the start
@@ -163,7 +146,7 @@ mDNSexport void LogMsgNoIdent(const char *format, ...)
        va_start(ptr,format);
        buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
        va_end(ptr);
        va_start(ptr,format);
        buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
        va_end(ptr);
-       WriteLogMsg("", buffer, 0);
+       mDNSPlatformWriteLogMsg("", buffer, 0);
        }
 
 mDNSlocal const char *CStringForLogLevel(LogLevel_t level)
        }
 
 mDNSlocal const char *CStringForLogLevel(LogLevel_t level)
index 201a44b0ab338d27de549a521d7089c6b43bbf42..3e0a60196f8c9007a2dd1130fc99ab188716a41f 100644 (file)
        Change History (most recent first):
 
 $Log: uds_daemon.c,v $
        Change History (most recent first):
 
 $Log: uds_daemon.c,v $
+Revision 1.384  2007/12/22 01:38:05  cheshire
+Improve display of "Auth Records" SIGINFO output
+
+Revision 1.383  2007/12/07 00:45:58  cheshire
+<rdar://problem/5526800> BTMM: Need to deregister records and services on shutdown/sleep
+
+Revision 1.382  2007/11/30 20:11:48  cheshire
+Fixed compile warning: declaration of 'remove' shadows a global declaration
+
+Revision 1.381  2007/11/28 22:02:52  cheshire
+Remove pointless "if (!domain)" check (domain is an array on the stack, so its address can never be null)
+
+Revision 1.380  2007/11/28 18:38:41  cheshire
+Fixed typo in log message: "DNSServiceResolver" -> "DNSServiceResolve"
+
 Revision 1.379  2007/11/01 19:32:14  cheshire
 Added "DEBUG_64BIT_SCM_RIGHTS" debugging code
 
 Revision 1.379  2007/11/01 19:32:14  cheshire
 Added "DEBUG_64BIT_SCM_RIGHTS" debugging code
 
@@ -2067,10 +2082,10 @@ mDNSlocal void udsserver_automatic_browse_domain_changed(const DNameListElem *co
                                        if (p) debugf("udsserver_automatic_browse_domain_changed %##s still in list, not removing", &d->name);
                                        else
                                                {
                                        if (p) debugf("udsserver_automatic_browse_domain_changed %##s still in list, not removing", &d->name);
                                        else
                                                {
-                                               browser_t *remove = *ptr;
+                                               browser_t *rem = *ptr;
                                                *ptr = (*ptr)->next;
                                                *ptr = (*ptr)->next;
-                                               mDNS_StopQueryWithRemoves(&mDNSStorage, &remove->q);
-                                               freeL("browser_t/udsserver_automatic_browse_domain_changed", remove);
+                                               mDNS_StopQueryWithRemoves(&mDNSStorage, &rem->q);
+                                               freeL("browser_t/udsserver_automatic_browse_domain_changed", rem);
                                                }
                                        }
                                }
                                                }
                                        }
                                }
@@ -2138,9 +2153,9 @@ mDNSlocal void DeregisterLocalOnlyDomainEnumPTR(mDNS *m, const domainname *d, in
                {
                if (SameDomainName(&(*ptr)->ar.resrec.rdata->u.name, d) && SameDomainName((*ptr)->ar.resrec.name, &lhs))
                        {
                {
                if (SameDomainName(&(*ptr)->ar.resrec.rdata->u.name, d) && SameDomainName((*ptr)->ar.resrec.name, &lhs))
                        {
-                       ARListElem *remove = *ptr;
+                       ARListElem *rem = *ptr;
                        *ptr = (*ptr)->next;
                        *ptr = (*ptr)->next;
-                       mDNS_Deregister(m, &remove->ar);
+                       mDNS_Deregister(m, &rem->ar);
                        return;
                        }
                else ptr = &(*ptr)->next;
                        return;
                        }
                else ptr = &(*ptr)->next;
@@ -2335,7 +2350,7 @@ mDNSlocal mStatus handle_browse_request(request_state *request)
 
        if (!request->msgptr) { LogMsg("%3d: DNSServiceBrowse(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
 
 
        if (!request->msgptr) { LogMsg("%3d: DNSServiceBrowse(unreadable parameters)", request->sd); return(mStatus_BadParamErr); }
 
-       if (!domain || (domain[0] == '\0')) uDNS_RegisterSearchDomains(&mDNSStorage);
+       if (domain[0] == '\0') uDNS_RegisterSearchDomains(&mDNSStorage);
 
        typedn.c[0] = 0;
        NumSubTypes = ChopSubTypes(regtype);    // Note: Modifies regtype string to remove trailing subtypes
 
        typedn.c[0] = 0;
        NumSubTypes = ChopSubTypes(regtype);    // Note: Modifies regtype string to remove trailing subtypes
@@ -3300,7 +3315,13 @@ mDNSlocal void request_callback(int fd, short filter, void *info)
                req = newreq;
                }
 
                req = newreq;
                }
 
-       switch(req->hdr.op)
+       // If we're shutting down, don't allow new client requests
+       // We do allow "cancel" and "getproperty" during shutdown
+       if (mDNSStorage.ShutdownTime && req->hdr.op != cancel_request && req->hdr.op != getproperty_request)
+               {
+               err = mStatus_ServiceNotRunning;
+               }
+       else switch(req->hdr.op)
                {
                // These are all operations that have their own first-class request_state object
                case connection_request:
                {
                // These are all operations that have their own first-class request_state object
                case connection_request:
@@ -3331,8 +3352,7 @@ mDNSlocal void request_callback(int fd, short filter, void *info)
        if (req->msgbuf) freeL("request_state msgbuf", req->msgbuf);
 
        // There's no return data for a cancel request (DNSServiceRefDeallocate returns no result)
        if (req->msgbuf) freeL("request_state msgbuf", req->msgbuf);
 
        // There's no return data for a cancel request (DNSServiceRefDeallocate returns no result)
-       // For a DNSServiceGetProperty call, the handler already generated the response,
-       // so no need to do it again here
+       // For a DNSServiceGetProperty call, the handler already generated the response, so no need to do it again here
        if (req->hdr.op != cancel_request && req->hdr.op != getproperty_request)
                {
                err = dnssd_htonl(err);
        if (req->hdr.op != cancel_request && req->hdr.op != getproperty_request)
                {
                err = dnssd_htonl(err);
@@ -3402,10 +3422,10 @@ mDNSlocal void connect_callback(int fd, short filter, void *info)
                request->errsd = sd;
 #if APPLE_OSX_mDNSResponder
        struct xucred x;
                request->errsd = sd;
 #if APPLE_OSX_mDNSResponder
        struct xucred x;
-       socklen_t len = sizeof(x);
-       if (getsockopt(sd, 0, LOCAL_PEERCRED, &x, &len) >= 0 && x.cr_version == XUCRED_VERSION) request->uid = x.cr_uid;
+       socklen_t xucredlen = sizeof(x);
+       if (getsockopt(sd, 0, LOCAL_PEERCRED, &x, &xucredlen) >= 0 && x.cr_version == XUCRED_VERSION) request->uid = x.cr_uid;
        else my_perror("ERROR: getsockopt, LOCAL_PEERCRED");
        else my_perror("ERROR: getsockopt, LOCAL_PEERCRED");
-       debugf("LOCAL_PEERCRED %d %u %u %d", len, x.cr_version, x.cr_uid, x.cr_ngroups);
+       debugf("LOCAL_PEERCRED %d %u %u %d", xucredlen, x.cr_version, x.cr_uid, x.cr_ngroups);
 #endif APPLE_OSX_mDNSResponder
                LogOperation("%3d: Adding FD for uid %u", request->sd, request->uid);
                udsSupportAddFDToEventLoop(sd, request_callback, request);
 #endif APPLE_OSX_mDNSResponder
                LogOperation("%3d: Adding FD for uid %u", request->sd, request->uid);
                udsSupportAddFDToEventLoop(sd, request_callback, request);
@@ -3665,11 +3685,19 @@ mDNSexport void udsserver_info(mDNS *const m)
                AuthRecord *ar;
                LogMsgNoIdent("    Int    Next  Expire   State");
                for (ar = m->ResourceRecords; ar; ar=ar->next)
                AuthRecord *ar;
                LogMsgNoIdent("    Int    Next  Expire   State");
                for (ar = m->ResourceRecords; ar; ar=ar->next)
-                       LogMsgNoIdent("%7d %7d %7d %7d %s",
-                               ar->ThisAPInterval / mDNSPlatformOneSecond,
-                               AuthRecord_uDNS(ar) || ar->AnnounceCount ? (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond : 0,
-                               AuthRecord_uDNS(ar) && ar->expire        ? (ar->expire - now) / mDNSPlatformOneSecond : 0,
-                               ar->state, ARDisplayString(m, ar));
+                       if (AuthRecord_uDNS(ar))
+                               LogMsgNoIdent("%7d %7d %7d %7d %s",
+                                       ar->ThisAPInterval / mDNSPlatformOneSecond,
+                                       (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond,
+                                       ar->expire ? (ar->expire - now) / mDNSPlatformOneSecond : 0,
+                                       ar->state, ARDisplayString(m, ar));
+                       else if (ar->resrec.InterfaceID != mDNSInterface_LocalOnly)
+                               LogMsgNoIdent("%7d %7d               M %s",
+                                       ar->ThisAPInterval / mDNSPlatformOneSecond,
+                                       ar->AnnounceCount ? (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond : 0,
+                                       ARDisplayString(m, ar));
+                       else
+                               LogMsgNoIdent("                             LO %s", ARDisplayString(m, ar));
                }
 
        LogMsgNoIdent("----- ServiceRegistrations -----");
                }
 
        LogMsgNoIdent("----- ServiceRegistrations -----");
@@ -3864,7 +3892,7 @@ mDNSexport mDNSs32 udsserver_idle(mDNSs32 nextevent)
                        if ((*req)->u.resolve.ReportTime && now - (*req)->u.resolve.ReportTime >= 0)
                                {
                                (*req)->u.resolve.ReportTime = 0;
                        if ((*req)->u.resolve.ReportTime && now - (*req)->u.resolve.ReportTime >= 0)
                                {
                                (*req)->u.resolve.ReportTime = 0;
-                               LogMsgNoIdent("Client application bug: DNSServiceResolver(%##s) active for over two minutes. "
+                               LogMsgNoIdent("Client application bug: DNSServiceResolve(%##s) active for over two minutes. "
                                        "This places considerable burden on the network.", (*req)->u.resolve.qsrv.qname.c);
                                }
 
                                        "This places considerable burden on the network.", (*req)->u.resolve.qsrv.qname.c);
                                }
 
index 13b04048bb5e64bc1d55435f72f180530679e5ff..1cb1f6466bfecb946de6c96bba939b68b6ce39aa 100755 (executable)
@@ -17,6 +17,9 @@
     Change History (most recent first):
     
 $Log: mDNSWin32.c,v $
     Change History (most recent first):
     
 $Log: mDNSWin32.c,v $
+Revision 1.130  2007/11/16 18:53:56  cheshire
+TCPSocketFlags needs to be first field of TCPSocket_struct
+
 Revision 1.129  2007/10/17 22:52:26  cheshire
 Get rid of unused mDNS_UpdateLLQs()
 
 Revision 1.129  2007/10/17 22:52:26  cheshire
 Get rid of unused mDNS_UpdateLLQs()
 
@@ -219,8 +222,8 @@ struct      mDNSPlatformInterfaceInfo
 
 struct TCPSocket_struct
 {
 
 struct TCPSocket_struct
 {
+       TCPSocketFlags flags;           // MUST BE FIRST FIELD -- mDNSCore expects every TCPSocket_struct to begin with TCPSocketFlags flags
        SocketRef                               fd;
        SocketRef                               fd;
-       TCPSocketFlags          flags;
        BOOL                                    connected;
        TCPConnectionCallback   callback;
        void                            *       context;
        BOOL                                    connected;
        TCPConnectionCallback   callback;
        void                            *       context;