From 377735b0ee279c59d1e883dff2f26a9cf5392938 Mon Sep 17 00:00:00 2001 From: Apple Date: Wed, 15 Jan 2003 01:12:03 +0000 Subject: [PATCH] mDNSResponder-25.tar.gz --- CFSocket.c | 7 +++- daemon.c | 56 ++++++++++++++++++------- mDNSCore/mDNS.c | 90 ++++++++++++++++++++++++++++++---------- mDNSCore/mDNSClientAPI.h | 3 +- 4 files changed, 117 insertions(+), 39 deletions(-) diff --git a/CFSocket.c b/CFSocket.c index 12b463a..2fcd97c 100644 --- a/CFSocket.c +++ b/CFSocket.c @@ -38,6 +38,8 @@ // to zero will cause CFSocket.c to not set the Advertise flag in its mDNS_RegisterInterface calls. int mDNS_AdvertiseLocalAddresses = 1; +void (*NotifyClientNetworkChanged)(void); + #include "mDNSClientAPI.h" // Defines the interface provided to the client layer above #include "mDNSPlatformFunctions.h" // Defines the interface to the supporting layer below #include "mDNSPlatformEnvironment.h" // Defines the specific types needed to run mDNS on this platform @@ -664,8 +666,10 @@ mDNSlocal void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, v debugf("*** Network Configuration Change ***"); (void)store; // Parameter not used (void)changedKeys; // Parameter not used + ClearInterfaceList(m); SetupInterfaceList(m); + if (NotifyClientNetworkChanged) NotifyClientNetworkChanged(); mDNSCoreSleep(m, false); } @@ -677,7 +681,7 @@ mDNSlocal mStatus WatchForNetworkChanges(mDNS *const m) CFStringRef key1 = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4); CFStringRef key2 = SCDynamicStoreKeyCreateComputerName(NULL); CFStringRef key3 = SCDynamicStoreKeyCreateHostNames(NULL); - CFStringRef pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4); + CFStringRef pattern = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4); CFMutableArrayRef keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); CFMutableArrayRef patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); @@ -809,7 +813,6 @@ mDNSexport void mDNSPlatformClose(mDNS *const m) } } -// To Do: Find out how to implement a proper modular time function in CF mDNSexport void mDNSPlatformScheduleTask(const mDNS *const m, SInt32 NextTaskTime) { if (m->p->CFTimer) diff --git a/daemon.c b/daemon.c index c012ab1..67365ae 100644 --- a/daemon.c +++ b/daemon.c @@ -119,6 +119,8 @@ struct DNSServiceRegistration_struct DNSServiceRegistration *next; mach_port_t ClientMachPort; mDNSBool autoname; + mDNSBool autorename; + domainlabel name; ServiceRecordSet s; // Don't add any fields after ServiceRecordSet. // This is where the implicit extra space goes if we allocate an oversized ServiceRecordSet object @@ -264,6 +266,7 @@ mDNSlocal void AbortClient(mach_port_t ClientMachPort) { DNSServiceRegistration *x = *r; *r = (*r)->next; + x->autorename = mDNSfalse; mDNS_DeregisterService(&mDNSStorage, &x->s); // Note that we don't do the "free(x);" here -- wait for the mStatus_MemFree message return; @@ -598,7 +601,7 @@ mDNSlocal void RegCallback(mDNS *const m, ServiceRecordSet *const sr, mStatus re // Note: By the time we get the mStatus_NameConflict message, the service is already deregistered // and the memory is free, so we don't have to wait for an mStatus_MemFree message as well. if (x->autoname) - mDNS_RenameAndReregisterService(m, sr); + mDNS_RenameAndReregisterService(m, sr, mDNSNULL); else { kern_return_t status; @@ -613,15 +616,25 @@ mDNSlocal void RegCallback(mDNS *const m, ServiceRecordSet *const sr, mStatus re if (result == mStatus_MemFree) { - DNSServiceRegistration **r = &DNSServiceRegistrationList; - while (*r && *r != x) r = &(*r)->next; - if (*r) + if (x->autorename) { - debugf("RegCallback: %##s Still in DNSServiceRegistration list; removing now", sr->RR_SRV.name.c); - *r = (*r)->next; + debugf("RegCallback renaming %#s to %#s", &x->name, &mDNSStorage.nicelabel); + x->autorename = mDNSfalse; + x->name = mDNSStorage.nicelabel; + mDNS_RenameAndReregisterService(m, &x->s, &x->name); + } + else + { + DNSServiceRegistration **r = &DNSServiceRegistrationList; + while (*r && *r != x) r = &(*r)->next; + if (*r) + { + debugf("RegCallback: %##s Still in DNSServiceRegistration list; removing now", sr->RR_SRV.name.c); + *r = (*r)->next; + } + debugf("RegCallback: Freeing DNSServiceRegistration %##s %d", sr->RR_SRV.name.c, x->ClientMachPort); + FreeDNSServiceRegistration(x); } - debugf("RegCallback: Freeing DNSServiceRegistration %##s %d", sr->RR_SRV.name.c, x->ClientMachPort); - FreeDNSServiceRegistration(x); } } @@ -651,7 +664,6 @@ mDNSexport kern_return_t provide_DNSServiceRegistrationCreate_rpc(mach_port_t un DNSCString name, DNSCString regtype, DNSCString domain, int notAnIntPort, DNSCString txtRecord) { mStatus err; - domainlabel n; domainname t, d; mDNSIPPort port; unsigned char txtinfo[1024] = ""; @@ -693,17 +705,18 @@ mDNSexport kern_return_t provide_DNSServiceRegistrationCreate_rpc(mach_port_t un DNSServiceRegistrationList = x; x->autoname = (*name == 0); - if (x->autoname) n = mDNSStorage.nicelabel; - else ConvertCStringToDomainLabel(name, &n); + x->autorename = mDNSfalse; + if (x->autoname) x->name = mDNSStorage.nicelabel; + else ConvertCStringToDomainLabel(name, &x->name); ConvertCStringToDomainName(regtype, &t); ConvertCStringToDomainName(*domain ? domain : "local.", &d); port.NotAnInteger = notAnIntPort; debugf("Client %d: provide_DNSServiceRegistrationCreate_rpc", client); debugf("Client %d: Register Service: %#s.%##s%##s %d %.30s", - client, &n, &t, &d, (int)port.b[0] << 8 | port.b[1], txtRecord); - CheckForDuplicateRegistrations(x, &n, &t, &d); - err = mDNS_RegisterService(&mDNSStorage, &x->s, &n, &t, &d, mDNSNULL, port, txtinfo, data_len, RegCallback, x); + client, &x->name, &t, &d, (int)port.b[0] << 8 | port.b[1], txtRecord); + CheckForDuplicateRegistrations(x, &x->name, &t, &d); + err = mDNS_RegisterService(&mDNSStorage, &x->s, &x->name, &t, &d, mDNSNULL, port, txtinfo, data_len, RegCallback, x); if (err) AbortClient(client); else EnableDeathNotificationForClient(client); @@ -714,6 +727,18 @@ mDNSexport kern_return_t provide_DNSServiceRegistrationCreate_rpc(mach_port_t un return(err); } +void NetworkChanged(void) + { + DNSServiceRegistration *r; + for (r = DNSServiceRegistrationList; r; r=r->next) + if (r->autoname && !SameDomainLabel(r->name.c, mDNSStorage.nicelabel.c)) + { + debugf("NetworkChanged renaming %#s to %#s", &r->name, &mDNSStorage.nicelabel); + r->autorename = mDNStrue; + mDNS_DeregisterService(&mDNSStorage, &r->s); + } + } + mDNSexport kern_return_t provide_DNSServiceRegistrationAddRecord_rpc(mach_port_t unusedserver, mach_port_t client, int type, const char *data, mach_msg_type_number_t data_len, uint32_t ttl, natural_t *reference) { @@ -1010,6 +1035,7 @@ mDNSlocal void ExitCallback(CFMachPortRef port, void *msg, CFIndex size, void *i mDNSlocal kern_return_t start(const char *bundleName, const char *bundleDir) { + extern void (*NotifyClientNetworkChanged)(void); // Temp fix for catching name changes mStatus err; CFRunLoopTimerContext myCFRunLoopTimerContext = { 0, &mDNSStorage, NULL, NULL, NULL }; CFMachPortRef d_port = CFMachPortCreate(NULL, ClientDeathCallback, NULL, NULL); @@ -1056,6 +1082,8 @@ mDNSlocal kern_return_t start(const char *bundleName, const char *bundleDir) CFRelease(e_rls); if (debug_mode) printf("Service registered with Mach Port %d\n", m_port); + NotifyClientNetworkChanged = NetworkChanged; + return(err); } diff --git a/mDNSCore/mDNS.c b/mDNSCore/mDNS.c index fc678e0..e216582 100755 --- a/mDNSCore/mDNS.c +++ b/mDNSCore/mDNS.c @@ -166,7 +166,7 @@ mDNSexport mDNSu32 DomainNameLength(const domainname *const name) return((mDNSu32)(src - name->c + 1)); } -mDNSlocal mDNSBool SameDomainLabel(const mDNSu8 *a, const mDNSu8 *b) +mDNSexport mDNSBool SameDomainLabel(const mDNSu8 *a, const mDNSu8 *b) { int i; const int len = *a++; @@ -569,13 +569,15 @@ mDNSlocal void IncrementLabelSuffix(domainlabel *name, mDNSBool RichText) ((RR)->InterfaceAddr.NotAnInteger == 0 || (RR)->InterfaceAddr.NotAnInteger == (I).NotAnInteger)) #define DefaultProbeCountForTypeUnique ((mDNSu8)3) +#define DefaultProbeCountForRecordType(X) ((X) == kDNSRecordTypeUnique ? DefaultProbeCountForTypeUnique : (mDNSu8)0) #define DefaultAnnounceCountForTypeShared ((mDNSu8)10) #define DefaultAnnounceCountForTypeUnique ((mDNSu8)2) -#define DefaultAnnounceCountForRecordType(X) ((X) == kDNSRecordTypeShared ? DefaultAnnounceCountForTypeShared : \ - (X) == kDNSRecordTypeUnique ? DefaultAnnounceCountForTypeUnique : \ - (X) == kDNSRecordTypeVerified ? DefaultAnnounceCountForTypeUnique : (mDNSu8)0) +#define DefaultAnnounceCountForRecordType(X) ((X) == kDNSRecordTypeShared ? DefaultAnnounceCountForTypeShared : \ + (X) == kDNSRecordTypeUnique ? DefaultAnnounceCountForTypeUnique : \ + (X) == kDNSRecordTypeVerified ? DefaultAnnounceCountForTypeUnique : \ + (X) == kDNSRecordTypeKnownUnique ? DefaultAnnounceCountForTypeUnique : (mDNSu8)0) #define DefaultSendIntervalForRecordType(X) ((X) == kDNSRecordTypeShared ? mDNSPlatformOneSecond : \ (X) == kDNSRecordTypeUnique ? mDNSPlatformOneSecond/4 : \ @@ -713,7 +715,11 @@ mDNSlocal void SetTargetToHostName(const mDNS *const m, ResourceRecord *const rr // If we're in the middle of probing this record, we need to start again, // because changing its rdata may change the outcome of the tie-breaker. - if (rr->RecordType == kDNSRecordTypeUnique) rr->ProbeCount = DefaultProbeCountForTypeUnique; + rr->ProbeCount = DefaultProbeCountForRecordType(rr->RecordType); + rr->AnnounceCount = DefaultAnnounceCountForRecordType(rr->RecordType); + rr->NextSendTime = mDNSPlatformTimeNow(); + rr->NextSendInterval = DefaultSendIntervalForRecordType(rr->RecordType); + if (rr->RecordType == kDNSRecordTypeUnique && m->SuppressProbes) rr->NextSendTime = m->SuppressProbes; } mDNSlocal void UpdateHostNameTargets(const mDNS *const m) @@ -766,7 +772,7 @@ mDNSlocal mStatus mDNS_Register_internal(mDNS *const m, ResourceRecord *const rr // Field Group 2: Transient state for Authoritative Records rr->Acknowledged = mDNSfalse; - rr->ProbeCount = (rr->RecordType == kDNSRecordTypeUnique) ? DefaultProbeCountForTypeUnique : (mDNSu8)0; + rr->ProbeCount = DefaultProbeCountForRecordType(rr->RecordType); rr->AnnounceCount = DefaultAnnounceCountForRecordType(rr->RecordType); rr->IncludeInProbe = mDNSfalse; rr->SendPriority = 0; @@ -823,7 +829,7 @@ mDNSlocal void mDNS_Deregister_internal(mDNS *const m, ResourceRecord *const rr, mDNSu8 RecordType = rr->RecordType; // If this is a shared record and we've announced it at least once, // we need to retract that announcement before we delete the record - if (RecordType == kDNSRecordTypeShared && rr->AnnounceCount < DefaultAnnounceCountForTypeShared) + if (RecordType == kDNSRecordTypeShared && rr->AnnounceCount <= DefaultAnnounceCountForTypeShared) { debugf("mDNS_Deregister_internal: Sending deregister for %##s (%s)", rr->name.c, DNSTypeName(rr->rrtype)); rr->RecordType = kDNSRecordTypeDeregistering; @@ -864,9 +870,10 @@ mDNSlocal void mDNS_Deregister_internal(mDNS *const m, ResourceRecord *const rr, // If we have an update queued up which never executed, give the client a chance to free that memory if (rr->NewRData) { - RData *n = rr->NewRData; + RData *OldRData = rr->rdata; + rr->rdata = rr->NewRData; // Update our rdata rr->NewRData = mDNSNULL; // Clear the NewRData pointer ... - if (rr->UpdateCallback) rr->UpdateCallback(m, rr, n); // ...and let the client free this memory, if necessary + if (rr->UpdateCallback) rr->UpdateCallback(m, rr, OldRData); // ... and let the client know } if (RecordType == kDNSRecordTypeShared && rr->Callback) @@ -1460,7 +1467,7 @@ mDNSlocal void DiscardDeregistrations(mDNS *const m, mDNSs32 timenow) if (rr->RecordType == kDNSRecordTypeDeregistering) { rr->RecordType = kDNSRecordTypeShared; - rr->AnnounceCount = DefaultAnnounceCountForTypeShared; + rr->AnnounceCount = DefaultAnnounceCountForTypeShared+1; mDNS_Deregister_internal(m, rr, timenow, mDNS_Dereg_normal); } } @@ -1480,6 +1487,7 @@ mDNSlocal mDNSu8 *BuildResponse(mDNS *const m, int numDereg = 0; int numAnnounce = 0; int numAnswer = 0; + mDNSs32 minExistingAnnounceInterval = 0; if (m->CurrentRecord) debugf("BuildResponse ERROR m->CurrentRecord already set"); m->CurrentRecord = m->ResourceRecords; @@ -1534,7 +1542,7 @@ mDNSlocal mDNSu8 *BuildResponse(mDNS *const m, numDereg++; responseptr = newptr; rr->RecordType = kDNSRecordTypeShared; - rr->AnnounceCount = DefaultAnnounceCountForTypeShared; + rr->AnnounceCount = DefaultAnnounceCountForTypeShared+1; mDNS_Deregister_internal(m, rr, timenow, mDNS_Dereg_normal); } } @@ -1560,6 +1568,8 @@ mDNSlocal mDNSu8 *BuildResponse(mDNS *const m, if (response->h.numAnswers == 0) debugf("BuildResponse announcements failed"); if (newptr || response->h.numAnswers == 0) { + if (minExistingAnnounceInterval > rr->NextSendInterval) + minExistingAnnounceInterval = rr->NextSendInterval; rr->SendPriority = 0; rr->Requester = zeroIPAddr; rr->AnnounceCount--; @@ -1571,6 +1581,38 @@ mDNSlocal mDNSu8 *BuildResponse(mDNS *const m, } } + // 2a. Look for additional announcements that are worth accelerating + // They must be (a) at least half-way to their next announcement and + // (b) at an interval equal or less than any of the ones we've already put in + for (rr = m->ResourceRecords; rr; rr=rr->next) + { + if (rr->InterfaceAddr.NotAnInteger == InterfaceAddr.NotAnInteger && + rr->AnnounceCount && ResourceRecordIsValidAnswer(rr) && + timenow - (rr->LastSendTime + rr->NextSendInterval/4) >= 0 && + rr->NextSendInterval <= minExistingAnnounceInterval) + { + newptr = putResourceRecord(response, responseptr, &response->h.numAnswers, rr, m, timenow); + if (newptr) + { + numAnnounce++; + responseptr = newptr; + } + // If we were able to put the record, then update the state variables + // If we were unable to put the record because it is too large to fit, even though + // there are no other answers in the packet, then pretend we succeeded anyway, + // or we'll end up in an infinite loop trying to send a record that will never fit + if (response->h.numAnswers == 0) debugf("BuildResponse announcements failed"); + if (newptr || response->h.numAnswers == 0) + { + rr->SendPriority = 0; + rr->Requester = zeroIPAddr; + rr->AnnounceCount--; + rr->NextSendTime = timenow + rr->NextSendInterval; + rr->NextSendInterval *= 2; + } + } + } + // 3. Look for answers we need to send for (rr = m->ResourceRecords; rr; rr=rr->next) if (rr->InterfaceAddr.NotAnInteger == InterfaceAddr.NotAnInteger && @@ -2356,7 +2398,7 @@ mDNSexport void mDNSCoreSleep(mDNS *const m, mDNSBool sleepstate) { // First mark all the records we need to deregister for (rr = m->ResourceRecords; rr; rr=rr->next) - if (rr->RecordType == kDNSRecordTypeShared && rr->AnnounceCount < DefaultAnnounceCountForTypeShared) + if (rr->RecordType == kDNSRecordTypeShared && rr->AnnounceCount <= DefaultAnnounceCountForTypeShared) rr->rrremainingttl = 0; while (HaveResponses(m, timenow)) SendResponses(m, timenow); } @@ -2367,10 +2409,10 @@ mDNSexport void mDNSCoreSleep(mDNS *const m, mDNSBool sleepstate) for (rr = m->ResourceRecords; rr; rr=rr->next) { if (rr->RecordType == kDNSRecordTypeVerified) rr->RecordType = kDNSRecordTypeUnique; - rr->ProbeCount = (rr->RecordType == kDNSRecordTypeUnique) ? DefaultProbeCountForTypeUnique : (mDNSu8)0; + rr->ProbeCount = DefaultProbeCountForRecordType(rr->RecordType); rr->AnnounceCount = DefaultAnnounceCountForRecordType(rr->RecordType); - rr->NextSendInterval = DefaultSendIntervalForRecordType(rr->RecordType); rr->NextSendTime = timenow; + rr->NextSendInterval = DefaultSendIntervalForRecordType(rr->RecordType); } for (q = m->ActiveQuestions; q; q=q->next) // Scan our list of questions if (!q->DuplicateOf) @@ -2888,7 +2930,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, else { // else, the packet RR has different rdata -- check to see if this is a conflict - if (PacketRRConflict(m, rr, &pktrr)) + if (pktrr.rroriginalttl > 0 && PacketRRConflict(m, rr, &pktrr)) { if (rr->rrtype == kDNSType_SRV) { @@ -3715,7 +3757,7 @@ mDNSexport mStatus mDNS_RemoveRecordFromService(mDNS *const m, ServiceRecordSet return(mStatus_NoError); } -mDNSexport mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordSet *const sr) +mDNSexport mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordSet *const sr, const domainlabel *newname) { domainlabel name; domainname type, domain; @@ -3724,11 +3766,15 @@ mDNSexport mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordS mStatus err; DeconstructServiceName(&sr->RR_SRV.name, &name, &type, &domain); - IncrementLabelSuffix(&name, mDNStrue); - debugf("Reregistering as %#s", name.c); + if (!newname) + { + IncrementLabelSuffix(&name, mDNStrue); + newname = &name; + } + debugf("Reregistering as %#s", newname->c); if (sr->RR_SRV.HostTarget == mDNSfalse && sr->Host.c[0]) host = &sr->Host; - err = mDNS_RegisterService(m, sr, &name, &type, &domain, + err = mDNS_RegisterService(m, sr, newname, &type, &domain, host, sr->RR_SRV.rdata->u.srv.port, sr->RR_TXT.rdata->u.txt.c, sr->RR_TXT.rdata->RDLength, sr->Callback, sr->Context); @@ -3748,16 +3794,16 @@ mDNSexport mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordS mDNSexport void mDNS_DeregisterService(mDNS *const m, ServiceRecordSet *sr) { const mDNSs32 timenow = mDNS_Lock(m); + ExtraResourceRecord *e = sr->Extras; // We use mDNS_Dereg_repeat because, in the event of a collision, some or all of // these records could have already been automatically deregistered, and that's okay mDNS_Deregister_internal(m, &sr->RR_SRV, timenow, mDNS_Dereg_repeat); mDNS_Deregister_internal(m, &sr->RR_TXT, timenow, mDNS_Dereg_repeat); - while (sr->Extras) + while (e) { - ExtraResourceRecord *e = sr->Extras; - sr->Extras = sr->Extras->next; mDNS_Deregister_internal(m, &e->r, timenow, mDNS_Dereg_repeat); + e=e->next; } // Be sure to deregister the PTR last! diff --git a/mDNSCore/mDNSClientAPI.h b/mDNSCore/mDNSClientAPI.h index 923e59f..c919500 100755 --- a/mDNSCore/mDNSClientAPI.h +++ b/mDNSCore/mDNSClientAPI.h @@ -477,7 +477,7 @@ extern mStatus mDNS_RegisterService (mDNS *const m, ServiceRecordSet *sr, mDNSServiceCallback Callback, void *Context); extern mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra, RData *rdata, mDNSu32 ttl); extern mStatus mDNS_RemoveRecordFromService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra); -extern mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordSet *const sr); +extern mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordSet *const sr, const domainlabel *newname); extern void mDNS_DeregisterService(mDNS *const m, ServiceRecordSet *sr); extern mStatus mDNS_StartBrowse(mDNS *const m, DNSQuestion *const question, @@ -511,6 +511,7 @@ extern mStatus mDNS_AdvertiseDomains(mDNS *const m, ResourceRecord *rr, mDNSu8 D // work with DNS's native length-prefixed strings. For convenience in C, the following utility functions // are provided for converting between C's null-terminated strings and DNS's length-prefixed strings. +extern mDNSBool SameDomainLabel(const mDNSu8 *a, const mDNSu8 *b); extern mDNSBool SameDomainName(const domainname *const d1, const domainname *const d2); extern mDNSu32 DomainNameLength(const domainname *const name); -- 2.47.2