]> git.saurik.com Git - apple/mdnsresponder.git/commitdiff
mDNSResponder-258.21.tar.gz mac-os-x-1068 v258.21
authorApple <opensource@apple.com>
Thu, 12 May 2011 22:10:54 +0000 (22:10 +0000)
committerApple <opensource@apple.com>
Thu, 12 May 2011 22:10:54 +0000 (22:10 +0000)
18 files changed:
Clients/dns-sd.c
Makefile
mDNSCore/DNSCommon.c
mDNSCore/mDNS.c
mDNSCore/mDNSEmbeddedAPI.h
mDNSCore/uDNS.c
mDNSMacOSX/helper-stubs.c
mDNSMacOSX/helper.c
mDNSMacOSX/helper.h
mDNSMacOSX/helpermsg.defs
mDNSMacOSX/mDNSMacOSX.c
mDNSPosix/Identify.c
mDNSPosix/mDNSPosix.c
mDNSShared/dns_sd.h
mDNSShared/dnssd_clientshim.c
mDNSShared/dnssd_clientstub.c
mDNSShared/uds_daemon.c
mDNSWindows/mDNSWin32.c

index c1c5d27f9a5d4ac9e1f35702338a0c8a0abb1bbd..826245b9424e8ef24863c1d98ee2ac56ed17e582 100644 (file)
@@ -1073,7 +1073,7 @@ int main(int argc, char **argv)
                }
 
        if (argc < 2) goto Fail;        // Minimum command line is the command name and one argument
-       operation = getfirstoption(argc, argv, "EFBZLRPQqCAUNTMISV"
+       operation = getfirstoption(argc, argv, "EFBZLlRPQqCAUNTMISV"
                                                                #if HAS_NAT_PMP_API
                                                                        "X"
                                                                #endif
@@ -1117,14 +1117,19 @@ int main(int argc, char **argv)
                                        err = DNSServiceBrowse(&sc1, kDNSServiceFlagsShareConnection, opinterface, typ, dom, zonedata_browse, NULL);
                                        break;
 
-               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"
-                                       printf("Lookup %s.%s.%s\n", argv[opi+0], typ, dom);
-                                       err = DNSServiceResolve(&client, 0, opinterface, argv[opi+0], typ, dom, resolve_reply, NULL);
-                                       break;
+               case 'l':
+               case 'L':       {
+                                       DNSServiceFlags rflags = 0;
+                                       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"
+                                       printf("Lookup %s.%s.%s\n", argv[opi+0], typ, dom);
+                                       if (operation == 'l') rflags |= kDNSServiceFlagsWakeOnResolve;
+                                       err = DNSServiceResolve(&client, rflags, opinterface, argv[opi+0], typ, dom, resolve_reply, NULL);
+                                       break;
+                                       }
 
                case 'R':       if (argc < opi+4) goto Fail;
                                        typ = (argc < opi+2) ? "" : argv[opi+1];
index 18b458f9a2a7d76ef7482f2029a70a3e5141b2a5..c8c8ef9d4d995e82886a1036e7a831c2eceb14f5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@
 
 include /Developer/Makefiles/pb_makefiles/platform.make
 
-MVERS = "mDNSResponder-258.18"
+MVERS = "mDNSResponder-258.21"
 
 DDNSWRITECONFIG = "$(DSTROOT)/Library/Application Support/Bonjour/ddnswriteconfig"
 
index bb7a082a02d5baad4bf40ad1ee544daf01a50ad9..b0fe39d70d7c0b477f5b0bb90e857b4caf0f5b8b 100644 (file)
@@ -1074,6 +1074,7 @@ mDNSexport void mDNS_SetupQuestion(DNSQuestion *const q, const mDNSInterfaceID I
        q->ForceMCast          = mDNSfalse;
        q->ReturnIntermed      = mDNSfalse;
        q->SuppressUnusable    = mDNSfalse;
+       q->WakeOnResolve       = mDNSfalse;
        q->QuestionCallback    = callback;
        q->QuestionContext     = context;
        }
index 700282ee7f74947f7dbf18d7bfec1c696c86dbbb..51cc3671eba6f1cd2fe5768f76481afc6e03848a 100755 (executable)
@@ -75,6 +75,7 @@ void WCFConnectionDealloc(WCFConnection* c) __attribute__((weak_import));
 mDNSlocal void BeginSleepProcessing(mDNS *const m);
 mDNSlocal void RetrySPSRegistrations(mDNS *const m);
 mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password);
+mDNSlocal void mDNS_PurgeBeforeResolve(mDNS *const m, DNSQuestion *q);
 
 // ***************************************************************************
 #if COMPILER_LIKES_PRAGMA_MARK
@@ -278,6 +279,9 @@ mDNSlocal void AnswerAllLocalQuestionsWithLocalAuthRecord(mDNS *const m, AuthRec
 #define GoodbyeCount ((mDNSu8)3)
 #define WakeupCount ((mDNSu8)18)
 
+// Number of wakeups we send if WakeOnResolve is set in the question
+#define InitialWakeOnResolveCount ((mDNSu8)3)
+
 // Note that the announce intervals use exponential backoff, doubling each time. The probe intervals do not.
 // This means that because the announce interval is doubled after sending the first packet, the first
 // observed on-the-wire inter-packet interval between announcements is actually one second.
@@ -776,6 +780,11 @@ mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
        rr->InFlightRDLen     = 0;
        rr->QueuedRData       = 0;
        rr->QueuedRDLen       = 0;
+       //mDNSPlatformMemZero(&rr->NATinfo, sizeof(rr->NATinfo));
+       // We should be recording the actual internal port for this service record here. Once we initiate our NAT mapping
+       // request we'll subsequently overwrite srv.port with the allocated external NAT port -- potentially multiple
+       // times with different values if the external NAT port changes during the lifetime of the service registration.
+       //if (rr->resrec.rrtype == kDNSType_SRV) rr->NATinfo.IntPort = rr->resrec.rdata->u.srv.port;
 
 //     rr->resrec.interface         = already set in mDNS_SetupResourceRecord
 //     rr->resrec.name->c           = MUST be set by client
@@ -2273,6 +2282,57 @@ mDNSlocal int RecordDupSuppressInfo(DupSuppressInfo ds[DupSuppressInfoSize], mDN
        return(i);
        }
 
+mDNSlocal void mDNSSendWakeOnResolve(mDNS *const m, DNSQuestion *q)
+       {
+       int len, i, cnt;
+       mDNSInterfaceID InterfaceID = q->InterfaceID;
+       domainname *d = &q->qname;
+
+       // We can't send magic packets without knowing which interface to send it on.
+       if (InterfaceID == mDNSInterface_Any || InterfaceID == mDNSInterface_LocalOnly || InterfaceID == mDNSInterface_P2P)
+               {
+               LogMsg("mDNSSendWakeOnResolve: ERROR!! Invalid InterfaceID %p for question %##s", InterfaceID, q->qname.c);
+               return;
+               }
+
+       // Split MAC@IPAddress and pass them separately
+       len = d->c[0];
+       i = 1;
+       cnt = 0;
+       for (i = 1; i < len; i++)
+               {
+               if (d->c[i] == '@')
+                       {
+                       char EthAddr[18];       // ethernet adddress : 12 bytes + 5 ":" + 1 NULL byte
+                       char IPAddr[47];    // Max IP address len: 46 bytes (IPv6) + 1 NULL byte
+                       if (cnt != 5)
+                               {
+                               LogMsg("mDNSSendWakeOnResolve: ERROR!! Malformed Ethernet address %##s, cnt %d", q->qname.c, cnt);
+                               return;
+                               }
+                       if ((i - 1) > (int) (sizeof(EthAddr) - 1))
+                               {
+                               LogMsg("mDNSSendWakeOnResolve: ERROR!! Malformed Ethernet address %##s, length %d", q->qname.c, i - 1);
+                               return;
+                               }
+                       if ((len - i) > (int)(sizeof(IPAddr) - 1))
+                               {
+                               LogMsg("mDNSSendWakeOnResolve: ERROR!! Malformed IP address %##s, length %d", q->qname.c, len - i);
+                               return;
+                               }
+                       mDNSPlatformMemCopy(EthAddr, &d->c[1], i - 1);
+                       EthAddr[i - 1] = 0;
+                       mDNSPlatformMemCopy(IPAddr, &d->c[i + 1], len - i);
+                       IPAddr[len - i] = 0;
+                       mDNSPlatformSendWakeupPacket(m, InterfaceID, EthAddr, IPAddr, InitialWakeOnResolveCount - q->WakeOnResolveCount);
+                       return;
+                       }
+               else if (d->c[i] == ':')
+                       cnt++;
+               }
+       LogMsg("mDNSSendWakeOnResolve: ERROR!! Malformed WakeOnResolve name %##s", q->qname.c);
+       }
+
 mDNSlocal mDNSBool AccelerateThisQuery(mDNS *const m, DNSQuestion *q)
        {
        // If more than 90% of the way to the query time, we should unconditionally accelerate it
@@ -2568,7 +2628,14 @@ mDNSlocal void SendQueries(mDNS *const m)
                                        // If we're suppressing this question, or we successfully put it, update its SendQNow state
                                        if (SuppressOnThisInterface(q->DupSuppress, intf) ||
                                                BuildQuestion(m, &m->omsg, &queryptr, q, &kalistptr, &answerforecast))
-                                                       q->SendQNow = (q->InterfaceID || !q->SendOnAll) ? mDNSNULL : GetNextActiveInterfaceID(intf);
+                                               {
+                                               q->SendQNow = (q->InterfaceID || !q->SendOnAll) ? mDNSNULL : GetNextActiveInterfaceID(intf);
+                                               if (q->WakeOnResolveCount)
+                                                       {
+                                                       mDNSSendWakeOnResolve(m, q);
+                                                       q->WakeOnResolveCount--;
+                                                       }
+                                               }
                                        }
                                }
 
@@ -5932,8 +5999,11 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
                                                                LogMsg("mDNSCoreReceiveResponse: ProbeCount %d; will rename %s", rr->ProbeCount, ARDisplayString(m, rr));
                                                                mDNS_Deregister_internal(m, rr, mDNS_Dereg_conflict);
                                                                }
-                                                       // We assumed this record must be unique, but we were wrong. (e.g. There are two mDNSResponders on the same machine giving
-                                                       // different answers for the reverse mapping record.) This is simply a misconfiguration, and we don't try to recover from it.
+                                                       // We assumed this record must be unique, but we were wrong. (e.g. There are two mDNSResponders on the
+                                                       // same machine giving different answers for the reverse mapping record, or there are two machines on the
+                                                       // network using the same IP address.) This is simply a misconfiguration, and there's nothing we can do
+                                                       // to fix it -- e.g. it's not our job to be trying to change the machine's IP address. We just discard our
+                                                       // record to avoid continued conflicts (as we do for a conflict on our Unique records) and get on with life.
                                                        else if (rr->resrec.RecordType == kDNSRecordTypeKnownUnique)
                                                                {
                                                                LogMsg("mDNSCoreReceiveResponse: Unexpected conflict discarding %s", ARDisplayString(m, rr));
@@ -7378,6 +7448,13 @@ mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const qu
                question->validDNSServers   = zeroOpaque64;
                question->triedAllServersOnce = 0;
                question->noServerResponse = 0;
+               if (question->WakeOnResolve)
+                       {
+                       question->WakeOnResolveCount = InitialWakeOnResolveCount;
+                       mDNS_PurgeBeforeResolve(m, question);
+                       }
+               else
+                       question->WakeOnResolveCount = 0;
 
                if (question->DuplicateOf) question->AuthInfo = question->DuplicateOf->AuthInfo;
 
@@ -7682,6 +7759,7 @@ mDNSlocal mStatus mDNS_StartBrowse_internal(mDNS *const m, DNSQuestion *const qu
        question->ForceMCast       = ForceMCast;
        question->ReturnIntermed   = mDNSfalse;
        question->SuppressUnusable = mDNSfalse;
+       question->WakeOnResolve    = mDNSfalse;
        question->QuestionCallback = Callback;
        question->QuestionContext  = Context;
        if (!ConstructServiceName(&question->qname, mDNSNULL, srv, domain)) return(mStatus_BadParamErr);
@@ -7855,6 +7933,7 @@ mDNSexport mStatus mDNS_StartResolveService(mDNS *const m,
        query->qSRV.ForceMCast          = mDNSfalse;
        query->qSRV.ReturnIntermed      = mDNSfalse;
        query->qSRV.SuppressUnusable    = mDNSfalse;
+       query->qSRV.WakeOnResolve       = mDNSfalse;
        query->qSRV.QuestionCallback    = FoundServiceInfoSRV;
        query->qSRV.QuestionContext     = query;
 
@@ -7869,6 +7948,7 @@ mDNSexport mStatus mDNS_StartResolveService(mDNS *const m,
        query->qTXT.ForceMCast          = mDNSfalse;
        query->qTXT.ReturnIntermed      = mDNSfalse;
        query->qTXT.SuppressUnusable    = mDNSfalse;
+       query->qTXT.WakeOnResolve       = mDNSfalse;
        query->qTXT.QuestionCallback    = FoundServiceInfoTXT;
        query->qTXT.QuestionContext     = query;
 
@@ -7883,6 +7963,7 @@ mDNSexport mStatus mDNS_StartResolveService(mDNS *const m,
        query->qAv4.ForceMCast          = mDNSfalse;
        query->qAv4.ReturnIntermed      = mDNSfalse;
        query->qAv4.SuppressUnusable    = mDNSfalse;
+       query->qAv4.WakeOnResolve       = mDNSfalse;
        query->qAv4.QuestionCallback    = FoundServiceInfo;
        query->qAv4.QuestionContext     = query;
 
@@ -7897,6 +7978,7 @@ mDNSexport mStatus mDNS_StartResolveService(mDNS *const m,
        query->qAv6.ForceMCast          = mDNSfalse;
        query->qAv6.ReturnIntermed      = mDNSfalse;
        query->qAv6.SuppressUnusable    = mDNSfalse;
+       query->qAv6.WakeOnResolve       = mDNSfalse;
        query->qAv6.QuestionCallback    = FoundServiceInfo;
        query->qAv6.QuestionContext     = query;
 
@@ -7947,6 +8029,7 @@ mDNSexport mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, m
        question->ForceMCast       = mDNSfalse;
        question->ReturnIntermed   = mDNSfalse;
        question->SuppressUnusable = mDNSfalse;
+       question->WakeOnResolve    = mDNSfalse;
        question->QuestionCallback = Callback;
        question->QuestionContext  = Context;
        if (DomainType > mDNS_DomainTypeMax) return(mStatus_BadParamErr);
@@ -9673,6 +9756,22 @@ mDNSlocal void PurgeOrReconfirmCacheRecord(mDNS *const m, CacheRecord *cr, const
                }
        }
 
+mDNSlocal void mDNS_PurgeBeforeResolve(mDNS *const m, DNSQuestion *q)
+       {
+       const mDNSu32 slot = HashSlot(&q->qname);
+       CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
+       CacheRecord *rp;
+
+       for (rp = cg ? cg->members : mDNSNULL; rp; rp = rp->next)
+               {
+               if (SameNameRecordAnswersQuestion(&rp->resrec, q))
+                       {
+                       LogInfo("mDNS_PurgeBeforeResolve: Flushing %s", CRDisplayString(m, rp));
+                       mDNS_PurgeCacheResourceRecord(m, rp);
+                       }
+               }
+       }
+
 mDNSlocal void CacheRecordResetDNSServer(mDNS *const m, DNSQuestion *q, DNSServer *new)
        {
        const mDNSu32 slot = HashSlot(&q->qname);
index a9881d03c41814b5451cf02f527b631ff8b45063..26aa0a87e38bc6e54086a6faff6d52740a9a8a0a 100755 (executable)
@@ -1452,6 +1452,7 @@ struct DNSQuestion_struct
        mDNSs32               LastQTxTime;              // Last time this Q was sent on one (but not necessarily all) interfaces
        mDNSu32               CNAMEReferrals;   // Count of how many CNAME redirections we've done
        mDNSBool              SuppressQuery;    // This query should be suppressed and not sent on the wire 
+       mDNSu8                WakeOnResolveCount; // Number of wakes that should be sent on resolve
 
        // Wide Area fields. These are used internally by the uDNS core
        UDPSocket            *LocalSocket;
@@ -1493,6 +1494,7 @@ struct DNSQuestion_struct
        mDNSBool              ForceMCast;               // Set by client to force mDNS query, even for apparently uDNS names
        mDNSBool              ReturnIntermed;   // Set by client to request callbacks for intermediate CNAME/NXDOMAIN results
        mDNSBool              SuppressUnusable; // Set by client to suppress unusable queries to be sent on the wire
+       mDNSBool              WakeOnResolve;    // Send wakeup on resolve
        mDNSQuestionCallback *QuestionCallback;
        void                 *QuestionContext;
        };
@@ -2541,6 +2543,7 @@ extern mStatus    mDNSPlatformGetPrimaryInterface(mDNS *const m, mDNSAddr *v4, m
 extern void       mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status);
 
 extern void       mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep);
+extern void       mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration);
 
 #ifdef _LEGACY_NAT_TRAVERSAL_
 // Support for legacy NAT traversal protocols, implemented by the platform layer and callable by the core.
@@ -2810,15 +2813,15 @@ struct CompileTimeAssertionChecks_mDNS
        char sizecheck_AuthRecord          [(sizeof(AuthRecord)           <=  1208) ? 1 : -1];
        char sizecheck_CacheRecord         [(sizeof(CacheRecord)          <=   184) ? 1 : -1];
        char sizecheck_CacheGroup          [(sizeof(CacheGroup)           <=   184) ? 1 : -1];
-       char sizecheck_DNSQuestion         [(sizeof(DNSQuestion)          <=   752) ? 1 : -1];
-       char sizecheck_ZoneData            [(sizeof(ZoneData)             <=  1588) ? 1 : -1];
+       char sizecheck_DNSQuestion         [(sizeof(DNSQuestion)          <=   762) ? 1 : -1];
+       char sizecheck_ZoneData            [(sizeof(ZoneData)             <=  1598) ? 1 : -1];
        char sizecheck_NATTraversalInfo    [(sizeof(NATTraversalInfo)     <=   192) ? 1 : -1];
        char sizecheck_HostnameInfo        [(sizeof(HostnameInfo)         <=  3050) ? 1 : -1];
        char sizecheck_DNSServer           [(sizeof(DNSServer)            <=   320) ? 1 : -1];
        char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <=  6750) ? 1 : -1];
        char sizecheck_ServiceRecordSet    [(sizeof(ServiceRecordSet)     <=  5500) ? 1 : -1];
        char sizecheck_DomainAuthInfo      [(sizeof(DomainAuthInfo)       <=  7550) ? 1 : -1];
-       char sizecheck_ServiceInfoQuery    [(sizeof(ServiceInfoQuery)     <=  3050) ? 1 : -1];
+       char sizecheck_ServiceInfoQuery    [(sizeof(ServiceInfoQuery)     <=  3090) ? 1 : -1];
 #if APPLE_OSX_mDNSResponder
        char sizecheck_ClientTunnel        [(sizeof(ClientTunnel)         <=  1104) ? 1 : -1];
 #endif
index 2d6ba4be62555a3ac60e1d4cab47fd0bdf7b10a5..5d0facfe3aa926eb027e1d9bdc1ad5b2d7bf78ff 100755 (executable)
@@ -553,6 +553,9 @@ mDNSexport mStatus mDNS_StartNATOperation_internal(mDNS *const m, NATTraversalIn
                        {
                        LogMsg("Error! Tried to add a NAT traversal that's already in the active list: request %p Prot %d Int %d TTL %d",
                                traversal, traversal->Protocol, mDNSVal16(traversal->IntPort), traversal->NATLease);
+                       #if ForceAlerts
+                               *(long*)0 = 0;
+                       #endif
                        return(mStatus_AlreadyRegistered);
                        }
                if (traversal->Protocol && traversal->Protocol == (*n)->Protocol && mDNSSameIPPort(traversal->IntPort, (*n)->IntPort) &&
@@ -1572,6 +1575,7 @@ mDNSlocal mStatus GetZoneData_StartQuery(mDNS *const m, ZoneData *zd, mDNSu16 qt
        zd->question.ForceMCast          = mDNSfalse;
        zd->question.ReturnIntermed      = mDNStrue;
        zd->question.SuppressUnusable    = mDNSfalse;
+       zd->question.WakeOnResolve       = mDNSfalse;
        zd->question.QuestionCallback    = GetZoneData_QuestionCallback;
        zd->question.QuestionContext     = zd;
 
@@ -1709,7 +1713,7 @@ mDNSlocal void CompleteRecordNatMap(mDNS *m, NATTraversalInfo *n)
        if (!rr->nta || mDNSIPv4AddressIsZero(rr->nta->Addr.ip.v4))
                {
                LogInfo("CompleteRecordNatMap called for %s but no zone information!", ARDisplayString(m, rr));
-               // We need to clear out the NATinfo state so that it will result in re-acuqiring the mapping
+               // We need to clear out the NATinfo state so that it will result in re-acquiring the mapping
                // and hence this callback called again.
                if (rr->NATinfo.clientContext)
                        {
@@ -1802,8 +1806,13 @@ mDNSlocal void StartRecordNatMap(mDNS *m, AuthRecord *rr)
        else if (SameDomainLabel(p, (mDNSu8 *)"\x4" "_udp")) protocol = NATOp_MapUDP;
        else { LogMsg("StartRecordNatMap: could not determine transport protocol of service %##s", rr->resrec.name->c); return; }
        
+       //LogMsg("StartRecordNatMap: clientContext %p IntPort %d srv.port %d %s",
+       //      rr->NATinfo.clientContext, mDNSVal16(rr->NATinfo.IntPort), mDNSVal16(rr->resrec.rdata->u.srv.port), ARDisplayString(m, rr));
        if (rr->NATinfo.clientContext) mDNS_StopNATOperation_internal(m, &rr->NATinfo);
        rr->NATinfo.Protocol       = protocol;
+
+       // Shouldn't be trying to set IntPort here --
+       // BuildUpdateMessage overwrites srs->RR_SRV.resrec.rdata->u.srv.port with external (mapped) port number
        rr->NATinfo.IntPort        = rr->resrec.rdata->u.srv.port;
        rr->NATinfo.RequestedPort  = rr->resrec.rdata->u.srv.port;
        rr->NATinfo.NATLease       = 0;         // Request default lease
@@ -1818,6 +1827,19 @@ mDNSlocal void StartRecordNatMap(mDNS *m, AuthRecord *rr)
 // record is temporarily left in the ResourceRecords list so that we can initialize later
 // when the target is resolvable. Similarly, when host name changes, we enter regState_NoTarget
 // and we do the same.
+
+// This UnlinkResourceRecord routine is very worrying. It bypasses all the normal cleanup performed
+// by mDNS_Deregister_internal and just unceremoniously cuts the record from the active list.
+// This is why re-regsitering this record was producing syslog messages like this:
+// "Error! Tried to add a NAT traversal that's already in the active list"
+// Right now UnlinkResourceRecord is fortunately only called by RegisterAllServiceRecords,
+// which then immediately calls mDNS_Register_internal to re-register the record, which probably
+// masked more serious problems. Any other use of UnlinkResourceRecord is likely to lead to crashes.
+// For now we'll workaround that specific problem by explicitly calling mDNS_StopNATOperation_internal,
+// but long-term we should either stop cancelling the record registration and then re-registering it,
+// or if we really do need to do this for some reason it should be done via the usual
+// mDNS_Deregister_internal path instead of just cutting the record from the list.
+
 mDNSlocal mStatus UnlinkResourceRecord(mDNS *const m, AuthRecord *const rr)
        {
        AuthRecord **list = &m->ResourceRecords;
@@ -1826,6 +1848,15 @@ mDNSlocal mStatus UnlinkResourceRecord(mDNS *const m, AuthRecord *const rr)
                {
                *list = rr->next;
                rr->next = mDNSNULL;
+
+               // Temporary workaround to cancel any active NAT mapping operation
+               if (rr->NATinfo.clientContext)
+                       {
+                       mDNS_StopNATOperation_internal(m, &rr->NATinfo);
+                       rr->NATinfo.clientContext = mDNSNULL;
+                       if (rr->resrec.rrtype == kDNSType_SRV) rr->resrec.rdata->u.srv.port = rr->NATinfo.IntPort;
+                       }
+
                return(mStatus_NoError);
                }
        LogMsg("UnlinkResourceRecord:ERROR!! - no such active record %##s", rr->resrec.name->c);
@@ -2189,6 +2220,7 @@ mDNSlocal void GetStaticHostname(mDNS *m)
        q->ForceMCast       = mDNSfalse;
        q->ReturnIntermed   = mDNStrue;
        q->SuppressUnusable = mDNSfalse;
+       q->WakeOnResolve    = mDNSfalse;
        q->QuestionCallback = FoundStaticHostname;
        q->QuestionContext  = mDNSNULL;
 
@@ -4786,6 +4818,7 @@ mDNSlocal void mDNS_StartCFQuestion(mDNS *const m, DNSQuestion *question, domain
        question->ForceMCast       = mDNSfalse;
        question->ReturnIntermed   = mDNSfalse;
        question->SuppressUnusable = mDNSfalse;
+       question->WakeOnResolve    = mDNSfalse;
        question->QuestionCallback = FoundCFDomain;
        question->QuestionContext  = context;
        LogInfo("mDNS_StartCFQuestion: Start CF domain question %##s", question->qname.c);
@@ -4919,5 +4952,5 @@ struct CompileTimeAssertionChecks_uDNS
        // 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_tcpInfo_t     [(sizeof(tcpInfo_t)      <=  9056) ? 1 : -1];
-       char sizecheck_SearchListElem[(sizeof(SearchListElem) <=  4800) ? 1 : -1];
+       char sizecheck_SearchListElem[(sizeof(SearchListElem) <=  4860) ? 1 : -1];
        };
index 9e5686041e7f0bfc00786cce3e52566ca181857d..a1bd53053a0349b3fc6fb70c0f431ca94021f616 100644 (file)
@@ -261,3 +261,14 @@ int mDNSAutoTunnelSetKeys(int replacedelete, v6addr_t local_inner,
 fin:
        return err;
        }
+
+void mDNSSendWakeupPacket(unsigned ifid, char *eth_addr, char *ip_addr, int iteration)
+       {
+       kern_return_t kr = KERN_SUCCESS;
+       int retry = 0, err = 0;
+       MACHRETRYLOOP_BEGIN(kr, retry, err, fin);
+       kr = proxy_mDNSSendWakeupPacket(getHelperPort(retry), ifid, eth_addr, ip_addr, iteration);
+       MACHRETRYLOOP_END(kr, retry, err, fin);
+fin:
+       (void) err;
+       }
index f4c0771a00134c25747ade400e8d33a9c791ac5c..a3a9046e5b0b853657ba696dce679b1bd5d227ba 100644 (file)
@@ -47,6 +47,7 @@
 #include <SystemConfiguration/SCDynamicStoreCopySpecific.h>
 #include <TargetConditionals.h>
 #include <IOKit/pwr_mgt/IOPMLib.h>
+#include <net/bpf.h>
 
 #include "mDNSEmbeddedAPI.h"
 #include "dns_sd.h"
@@ -2349,3 +2350,92 @@ fin:
        update_idle_timer();
        return KERN_SUCCESS;
        }
+
+kern_return_t
+do_mDNSSendWakeupPacket(__unused mach_port_t port, unsigned ifid, const char *eth_addr, const char *ip_addr, int iteration, audit_token_t token)
+       {
+       int bpf_fd, i, j;
+       struct ifreq ifr;
+       char ifname[IFNAMSIZ];
+       char packet[512];
+       char *ptr = packet;
+       char bpf_device[12];
+    struct ether_addr *ea;
+       (void) ip_addr; // unused
+       (void) iteration; // unused
+       (void) token; // unused
+
+       if (if_indextoname(ifid, ifname) == NULL)
+               {
+               helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket invalid interface index %u", ifid);
+               return errno;
+               }
+
+    ea = ether_aton(eth_addr);
+       if (ea == NULL)
+               {
+               helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket invalid ethernet address %s", eth_addr);
+               return errno;
+               }
+
+       for (i = 0; i < 100; i++)
+               {
+        snprintf(bpf_device, sizeof(bpf_device), "/dev/bpf%d", i);
+               bpf_fd = open(bpf_device, O_RDWR, 0);
+               if (bpf_fd == -1)
+                       continue;
+               else break;
+               }
+
+       if (bpf_fd == -1)
+               {
+               helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket cannot find a bpf device");
+               return ENXIO;
+               }
+
+       memset(&ifr, 0, sizeof(ifr));
+       strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+
+       if (ioctl(bpf_fd, BIOCSETIF, (char *)&ifr) < 0)
+               {
+               helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket BIOCSETIF failed %s", strerror(errno));
+               return errno;
+               }
+
+       // 0x00 Destination address
+    for (i=0; i<6; i++) *ptr++ = ea->octet[i];
+
+    // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option, BPF will fill in the real interface address for us)
+    for (i=0; i<6; i++) *ptr++ = 0;
+
+    // 0x0C Ethertype (0x0842)
+    *ptr++ = 0x08;
+    *ptr++ = 0x42;
+
+    // 0x0E Wakeup sync sequence
+    for (i=0; i<6; i++) *ptr++ = 0xFF;
+
+    // 0x14 Wakeup data
+    for (j=0; j<16; j++) for (i=0; i<6; i++) *ptr++ = ea->octet[i];
+
+    // 0x74 Password
+    for (i=0; i<6; i++) *ptr++ = 0;
+
+       if (write(bpf_fd, packet, ptr - packet) < 0)
+               {
+               helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket write failed %s", strerror(errno));
+               return errno;
+               }
+       helplog(ASL_LEVEL_INFO, "do_mDNSSendWakeupPacket sent unicast eth_addr %s, ip_addr %s", eth_addr, ip_addr);
+       // Send a broadcast one to handle ethernet switches that don't flood forward packets with
+       // unknown mac addresses.
+       for (i=0; i<6; i++) packet[i] = 0xFF;
+       if (write(bpf_fd, packet, ptr - packet) < 0)
+               {
+               helplog(ASL_LEVEL_ERR, "do_mDNSSendWakeupPacket write failed %s", strerror(errno));
+               return errno;
+               }
+       helplog(ASL_LEVEL_INFO, "do_mDNSSendWakeupPacket sent broadcast eth_addr %s, ip_addr %s", eth_addr, ip_addr);
+       close(bpf_fd);
+       return KERN_SUCCESS;
+       }
index 7bf8f495dce905d86070de9e558656c915b26ec0..e9abade30d2f8eae90e31eda1661fc8c8ddb9e12 100644 (file)
@@ -73,5 +73,6 @@ extern void mDNSConfigureServer(int updown, const domainname *const fqdn);
 extern int  mDNSAutoTunnelSetKeys(int replacedelete, v6addr_t local_inner,
                                v6addr_t local_outer, short local_port, v6addr_t remote_inner,
                                v6addr_t remote_outer, short remote_port, const domainname *const fqdn);
+extern void mDNSSendWakeupPacket(unsigned ifid, char *eth_addr, char *ip_addr, int iteration);
 
 #endif /* H_HELPER_H */
index ad946a3d6dc2f1283ab97215ab4e9ff8af4de0e2..546621ef27c850ff604bf32fb8f52568e688acf4 100644 (file)
@@ -98,3 +98,11 @@ routine mDNSAutoTunnelSetKeys(       port                    : mach_port_t;
                                                                fqdn                    : string_t;
                out                                             err                             : int;
                ServerAuditToken                token                   : audit_token_t);
+
+simpleroutine mDNSSendWakeupPacket(
+                                                               port                    : mach_port_t;
+                                                               ifid                    : unsigned;
+                                                               eth_addr                : string_t;
+                                                               ip_addr                 : string_t;
+                                                               iteration               : int;
+               ServerAuditToken                token                   : audit_token_t);
index 19f5d0a072ba2b4f978eca5080ceedf360c344e9..a3f3ad3105906e27111d8e0ad9d16aa76e89d1ca 100644 (file)
@@ -4352,6 +4352,7 @@ mDNSexport void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q)
        p->q.ForceMCast       = mDNSfalse;
        p->q.ReturnIntermed   = mDNStrue;
        p->q.SuppressUnusable = mDNSfalse;
+       p->q.WakeOnResolve    = mDNSfalse;
        p->q.QuestionCallback = AutoTunnelCallback;
        p->q.QuestionContext  = p;
 
@@ -7672,3 +7673,17 @@ mDNSexport void mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep)
                LogInfo("%s Creating NoIdleSleep power assertion", __FUNCTION__);
                }
        }
+
+mDNSexport void mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration)
+       {
+       mDNSu32 ifindex;
+
+       // Sanity check
+       ifindex = mDNSPlatformInterfaceIndexfromInterfaceID(m, InterfaceID);
+       if (ifindex <= 0)
+               {
+               LogMsg("mDNSPlatformSendWakeupPacket: ERROR!! Invalid InterfaceID %u", ifindex);
+               return;
+               }
+       mDNSSendWakeupPacket(ifindex, EthAddr, IPAddr, iteration);
+       }
index df83b8eb17511a4ed77898bc857acb062e5fc8dc..6bc9a24f83ef2fee6c22ddc51622535b69f25745 100644 (file)
@@ -220,6 +220,8 @@ mDNSlocal mStatus StartQuery(DNSQuestion *q, char *qname, mDNSu16 qtype, const m
        q->ExpectUnique     = mDNSfalse;        // Don't want to stop after the first response packet
        q->ForceMCast       = mDNStrue;         // Query via multicast, even for apparently uDNS names like 1.1.1.17.in-addr.arpa.
        q->ReturnIntermed   = mDNStrue;
+       q->SuppressUnusable = mDNSfalse;
+       q->WakeOnResolve    = mDNSfalse;
        q->QuestionCallback = callback;
        q->QuestionContext  = NULL;
 
index f205cd0c3b6cf37f6170b1ec3fa019a3a3922607..45aa621a913b4298e328f1375435510dad97c708 100755 (executable)
@@ -1359,6 +1359,15 @@ mDNSexport mDNSs32 mDNSPlatformUTC(void)
        return time(NULL);
        }
 
+mDNSexport void mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration)
+       {
+       (void) m;
+       (void) InterfaceID;
+       (void) EthAddr;
+       (void) IPAddr;
+       (void) iteration;
+       }
+
 mDNSlocal void mDNSPosixAddToFDSet(int *nfds, fd_set *readfds, int s)
        {
        if (*nfds < s + 1) *nfds = s + 1;
index 911c70d2c43ba823f9de9373879e8310c54c226d..d2a9fddb9f40767b6989c1af6e8165e58b7f30b8 100644 (file)
@@ -77,7 +77,7 @@
  */
 
 #ifndef _DNS_SD_H
-#define _DNS_SD_H 2581800
+#define _DNS_SD_H 2582100
 
 #ifdef  __cplusplus
     extern "C" {
@@ -341,7 +341,7 @@ enum
      * lock or take similar appropriate precautions to serialize those calls.
      */
 
-    kDNSServiceFlagsSuppressUnusable    = 0x8000
+    kDNSServiceFlagsSuppressUnusable    = 0x8000,
        /*
         * This flag is meaningful only in DNSServiceQueryRecord which suppresses unusable queries on the
         * wire. If "hostname" is a wide-area unicast DNS hostname (i.e. not a ".local." name)
@@ -350,6 +350,11 @@ enum
         * if this host has no routable IPv4 address, the call will not try to look up IPv4 addresses for
         * "hostname".
         */
+       kDNSServiceFlagsWakeOnResolve      = 0x40000
+       /*
+        * This flag is meaningful only in DNSServiceResolve. When set, it tries to send a magic packet
+        * to wake up the client.
+        */
 
     };
 
index 17f2e93921941870822f5d64942111ea6a444a5b..a891915d6dae830b2e041006338c38a4b8a81882 100644 (file)
@@ -523,6 +523,7 @@ DNSServiceErrorType DNSServiceResolve
        x->qTXT.ForceMCast          = mDNSfalse;
        x->qTXT.ReturnIntermed      = mDNSfalse;
        x->qTXT.SuppressUnusable    = mDNSfalse;
+       x->qTXT.WakeOnResolve       = mDNSfalse;
        x->qTXT.QuestionCallback    = FoundServiceInfo;
        x->qTXT.QuestionContext     = x;
 
index 62f640e252691278ef8fd2ea8655ca05fc058975..fc4373019725bf392444fcc78e725ac9818a280f 100644 (file)
@@ -1094,6 +1094,16 @@ DNSServiceErrorType DNSSD_API DNSServiceResolve
 
        if (!name || !regtype || !domain || !callBack) return kDNSServiceErr_BadParam;
 
+       // Need a real InterfaceID for WakeOnResolve
+       if ((flags & kDNSServiceFlagsWakeOnResolve) != 0 &&
+               ((interfaceIndex == kDNSServiceInterfaceIndexAny) ||
+               (interfaceIndex == kDNSServiceInterfaceIndexLocalOnly) ||
+               (interfaceIndex == kDNSServiceInterfaceIndexUnicast) ||
+               (interfaceIndex == kDNSServiceInterfaceIndexP2P)))
+               {
+               return kDNSServiceErr_BadParam;
+               }
+
        err = ConnectToServer(sdRef, flags, resolve_request, handle_resolve_response, callBack, context);
        if (err) return err;    // On error ConnectToServer leaves *sdRef set to NULL
 
index 964667cb99033c942d7206ea7bf0a0aea42128bc..9ad7bc5db4f2cd051205078b9210ecaa750d91ea 100644 (file)
@@ -2203,6 +2203,8 @@ mDNSlocal mStatus handle_resolve_request(request_state *request)
        request->u.resolve.qsrv.ExpectUnique     = mDNStrue;
        request->u.resolve.qsrv.ForceMCast       = (flags & kDNSServiceFlagsForceMulticast     ) != 0;
        request->u.resolve.qsrv.ReturnIntermed   = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
+       request->u.resolve.qsrv.SuppressUnusable = mDNSfalse;
+       request->u.resolve.qsrv.WakeOnResolve    = (flags & kDNSServiceFlagsWakeOnResolve      ) != 0;
        request->u.resolve.qsrv.QuestionCallback = resolve_result_callback;
        request->u.resolve.qsrv.QuestionContext  = request;
 
@@ -2216,6 +2218,7 @@ mDNSlocal mStatus handle_resolve_request(request_state *request)
        request->u.resolve.qtxt.ForceMCast       = (flags & kDNSServiceFlagsForceMulticast     ) != 0;
        request->u.resolve.qtxt.ReturnIntermed   = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
        request->u.resolve.qtxt.SuppressUnusable = mDNSfalse;
+       request->u.resolve.qtxt.WakeOnResolve    = mDNSfalse;
        request->u.resolve.qtxt.QuestionCallback = resolve_result_callback;
        request->u.resolve.qtxt.QuestionContext  = request;
 
@@ -2449,6 +2452,7 @@ mDNSlocal mStatus handle_queryrecord_request(request_state *request)
        q->ForceMCast       = (flags & kDNSServiceFlagsForceMulticast     ) != 0;
        q->ReturnIntermed   = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
        q->SuppressUnusable = (flags & kDNSServiceFlagsSuppressUnusable) != 0;
+       q->WakeOnResolve    = mDNSfalse;
        q->QuestionCallback = queryrecord_result_callback;
        q->QuestionContext  = request;
 
@@ -2858,6 +2862,7 @@ mDNSlocal mStatus handle_addrinfo_request(request_state *request)
        request->u.addrinfo.q4.ForceMCast       = request->u.addrinfo.q6.ForceMCast       = (flags & kDNSServiceFlagsForceMulticast     ) != 0;
        request->u.addrinfo.q4.ReturnIntermed   = request->u.addrinfo.q6.ReturnIntermed   = (flags & kDNSServiceFlagsReturnIntermediates) != 0;
        request->u.addrinfo.q4.SuppressUnusable = request->u.addrinfo.q6.SuppressUnusable = (flags & kDNSServiceFlagsSuppressUnusable   ) != 0;
+       request->u.addrinfo.q4.SuppressUnusable = request->u.addrinfo.q6.SuppressUnusable = mDNSfalse;
 
        if (request->u.addrinfo.protocol & kDNSServiceProtocol_IPv4)
                {
@@ -4020,7 +4025,7 @@ struct CompileTimeAssertionChecks_uds_daemon
        char sizecheck_request_state          [(sizeof(request_state)           <= 2000) ? 1 : -1];
        char sizecheck_registered_record_entry[(sizeof(registered_record_entry) <=   60) ? 1 : -1];
        char sizecheck_service_instance       [(sizeof(service_instance)        <= 6552) ? 1 : -1];
-       char sizecheck_browser_t              [(sizeof(browser_t)               <=  1016) ? 1 : -1];
+       char sizecheck_browser_t              [(sizeof(browser_t)               <=  1026) ? 1 : -1];
        char sizecheck_reply_hdr              [(sizeof(reply_hdr)               <=   12) ? 1 : -1];
        char sizecheck_reply_state            [(sizeof(reply_state)             <=   64) ? 1 : -1];
        };
index 4add8451fc69bc9aa87f279250ba262a48ade239..58feb7fb93bd827ba6da689125f77f037754ad44 100755 (executable)
@@ -2183,6 +2183,14 @@ exit:
        return err;
 }
 
+mDNSexport void mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration)
+       {
+       (void) m;
+       (void) InterfaceID;
+       (void) EthAddr;
+       (void) IPAddr;
+       (void) iteration;
+       }
 
 #if 0
 #pragma mark -