1 /* -*- Mode: C; tab-width: 4 -*- 2 * 3 * Copyright (c) 2002-2006 Apple Computer, Inc. All rights reserved. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 * This code is completely 100% portable C. It does not depend on any external header files 18 * from outside the mDNS project -- all the types it expects to find are defined right here. 19 * 20 * The previous point is very important: This file does not depend on any external 21 * header files. It should compile on *any* platform that has a C compiler, without 22 * making *any* assumptions about availability of so-called "standard" C functions, 23 * routines, or types (which may or may not be present on any given platform). 24 25 * Formatting notes: 26 * This code follows the "Whitesmiths style" C indentation rules. Plenty of discussion 27 * on C indentation can be found on the web, such as <http://www.kafejo.com/komp/1tbs.htm>, 28 * but for the sake of brevity here I will say just this: Curly braces are not syntactially 29 * part of an "if" statement; they are the beginning and ending markers of a compound statement; 30 * therefore common sense dictates that if they are part of a compound statement then they 31 * should be indented to the same level as everything else in that compound statement. 32 * Indenting curly braces at the same level as the "if" implies that curly braces are 33 * part of the "if", which is false. (This is as misleading as people who write "char* x,y;" 34 * thinking that variables x and y are both of type "char*" -- and anyone who doesn't 35 * understand why variable y is not of type "char*" just proves the point that poor code 36 * layout leads people to unfortunate misunderstandings about how the C language really works.) 37 */ 38 39 #include "DNSCommon.h" // Defines general DNS untility routines 40 #include "uDNS.h" // Defines entry points into unicast-specific routines 41 42 // Disable certain benign warnings with Microsoft compilers 43 #if(defined(_MSC_VER)) 44 // Disable "conditional expression is constant" warning for debug macros. 45 // Otherwise, this generates warnings for the perfectly natural construct "while(1)" 46 // If someone knows a variant way of writing "while(1)" that doesn't generate warning messages, please let us know 47 #pragma warning(disable:4127) 48 49 // Disable "assignment within conditional expression". 50 // Other compilers understand the convention that if you place the assignment expression within an extra pair 51 // of parentheses, this signals to the compiler that you really intended an assignment and no warning is necessary. 52 // The Microsoft compiler doesn't understand this convention, so in the absense of any other way to signal 53 // to the compiler that the assignment is intentional, we have to just turn this warning off completely. 54 #pragma warning(disable:4706) 55 #endif 56 57 #if APPLE_OSX_mDNSResponder 58 59 #include <WebFilterDNS/WebFilterDNS.h> 60 61 #if ! NO_WCF 62 WCFConnection *WCFConnectionNew(void) __attribute__((weak_import)); 63 void WCFConnectionDealloc(WCFConnection* c) __attribute__((weak_import)); 64 65 // Do we really need to define a macro for "if"? 66 #define CHECK_WCF_FUNCTION(X) if (X) 67 #endif // ! NO_WCF 68 69 #else 70 71 #define NO_WCF 1 72 #endif // APPLE_OSX_mDNSResponder 73 74 // Forward declarations 75 mDNSlocal void BeginSleepProcessing(mDNS *const m); 76 mDNSlocal void RetrySPSRegistrations(mDNS *const m); 77 mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password); 78 mDNSlocal mDNSBool CacheRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q); 79 mDNSlocal mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q); 80 mDNSlocal void mDNS_PurgeBeforeResolve(mDNS *const m, DNSQuestion *q); 81 82 // *************************************************************************** 83 #if COMPILER_LIKES_PRAGMA_MARK 84 #pragma mark - Program Constants 85 #endif 86 87 #define NO_HINFO 1 88 89 90 // Any records bigger than this are considered 'large' records 91 #define SmallRecordLimit 1024 92 93 #define kMaxUpdateCredits 10 94 #define kUpdateCreditRefreshInterval (mDNSPlatformOneSecond * 6) 95 96 mDNSexport const char *const mDNS_DomainTypeNames[] = 97 { 98 "b._dns-sd._udp.", // Browse 99 "db._dns-sd._udp.", // Default Browse 100 "lb._dns-sd._udp.", // Automatic Browse 101 "r._dns-sd._udp.", // Registration 102 "dr._dns-sd._udp." // Default Registration 103 }; 104 105 #ifdef UNICAST_DISABLED 106 #define uDNS_IsActiveQuery(q, u) mDNSfalse 107 #endif 108 109 // *************************************************************************** 110 #if COMPILER_LIKES_PRAGMA_MARK 111 #pragma mark - 112 #pragma mark - General Utility Functions 113 #endif 114 115 // If there is a authoritative LocalOnly record that answers questions of type A, AAAA and CNAME 116 // this returns true. Main use is to handle /etc/hosts records. 117 #define LORecordAnswersAddressType(rr) ((rr)->ARType == AuthRecordLocalOnly && \ 118 (rr)->resrec.RecordType & kDNSRecordTypeUniqueMask && \ 119 ((rr)->resrec.rrtype == kDNSType_A || (rr)->resrec.rrtype == kDNSType_AAAA || \ 120 (rr)->resrec.rrtype == kDNSType_CNAME)) 121 122 #define FollowCNAME(q, rr, AddRecord) (AddRecord && (q)->qtype != kDNSType_CNAME && \ 123 (rr)->RecordType != kDNSRecordTypePacketNegative && \ 124 (rr)->rrtype == kDNSType_CNAME) 125 126 mDNSlocal void SetNextQueryStopTime(mDNS *const m, const DNSQuestion *const q) 127 { 128 if (m->mDNS_busy != m->mDNS_reentrancy+1) 129 LogMsg("SetNextQueryTime: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy); 130 131 #if ForceAlerts 132 if (m->mDNS_busy != m->mDNS_reentrancy+1) *(long*)0 = 0; 133 #endif 134 135 if (m->NextScheduledStopTime - q->StopTime > 0) 136 m->NextScheduledStopTime = q->StopTime; 137 } 138 139 mDNSexport void SetNextQueryTime(mDNS *const m, const DNSQuestion *const q) 140 { 141 if (m->mDNS_busy != m->mDNS_reentrancy+1) 142 LogMsg("SetNextQueryTime: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy); 143 144 #if ForceAlerts 145 if (m->mDNS_busy != m->mDNS_reentrancy+1) *(long*)0 = 0; 146 #endif 147 148 if (ActiveQuestion(q)) 149 { 150 // Depending on whether this is a multicast or unicast question we want to set either: 151 // m->NextScheduledQuery = NextQSendTime(q) or 152 // m->NextuDNSEvent = NextQSendTime(q) 153 mDNSs32 *const timer = mDNSOpaque16IsZero(q->TargetQID) ? &m->NextScheduledQuery : &m->NextuDNSEvent; 154 if (*timer - NextQSendTime(q) > 0) 155 *timer = NextQSendTime(q); 156 } 157 } 158 159 mDNSlocal void ReleaseAuthEntity(AuthHash *r, AuthEntity *e) 160 { 161 #if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING >= 1 162 unsigned int i; 163 for (i=0; i<sizeof(*e); i++) ((char*)e)[i] = 0xFF; 164 #endif 165 e->next = r->rrauth_free; 166 r->rrauth_free = e; 167 r->rrauth_totalused--; 168 } 169 170 mDNSlocal void ReleaseAuthGroup(AuthHash *r, AuthGroup **cp) 171 { 172 AuthEntity *e = (AuthEntity *)(*cp); 173 LogMsg("ReleaseAuthGroup: Releasing AuthGroup %##s", (*cp)->name->c); 174 if ((*cp)->rrauth_tail != &(*cp)->members) 175 LogMsg("ERROR: (*cp)->members == mDNSNULL but (*cp)->rrauth_tail != &(*cp)->members)"); 176 if ((*cp)->name != (domainname*)((*cp)->namestorage)) mDNSPlatformMemFree((*cp)->name); 177 (*cp)->name = mDNSNULL; 178 *cp = (*cp)->next; // Cut record from list 179 ReleaseAuthEntity(r, e); 180 } 181 182 mDNSlocal AuthEntity *GetAuthEntity(AuthHash *r, const AuthGroup *const PreserveAG) 183 { 184 AuthEntity *e = mDNSNULL; 185 186 if (r->rrauth_lock) { LogMsg("GetFreeCacheRR ERROR! Cache already locked!"); return(mDNSNULL); } 187 r->rrauth_lock = 1; 188 189 if (!r->rrauth_free) 190 { 191 // We allocate just one AuthEntity at a time because we need to be able 192 // free them all individually which normally happens when we parse /etc/hosts into 193 // AuthHash where we add the "new" entries and discard (free) the already added 194 // entries. If we allocate as chunks, we can't free them individually. 195 AuthEntity *storage = mDNSPlatformMemAllocate(sizeof(AuthEntity)); 196 storage->next = mDNSNULL; 197 r->rrauth_free = storage; 198 } 199 200 // If we still have no free records, recycle all the records we can. 201 // Enumerating the entire auth is moderately expensive, so when we do it, we reclaim all the records we can in one pass. 202 if (!r->rrauth_free) 203 { 204 mDNSu32 oldtotalused = r->rrauth_totalused; 205 mDNSu32 slot; 206 for (slot = 0; slot < AUTH_HASH_SLOTS; slot++) 207 { 208 AuthGroup **cp = &r->rrauth_hash[slot]; 209 while (*cp) 210 { 211 if ((*cp)->members || (*cp)==PreserveAG) cp=&(*cp)->next; 212 else ReleaseAuthGroup(r, cp); 213 } 214 } 215 LogInfo("GetAuthEntity: Recycled %d records to reduce auth cache from %d to %d", 216 oldtotalused - r->rrauth_totalused, oldtotalused, r->rrauth_totalused); 217 } 218 219 if (r->rrauth_free) // If there are records in the free list, take one 220 { 221 e = r->rrauth_free; 222 r->rrauth_free = e->next; 223 if (++r->rrauth_totalused >= r->rrauth_report) 224 { 225 LogInfo("RR Auth now using %ld objects", r->rrauth_totalused); 226 if (r->rrauth_report < 100) r->rrauth_report += 10; 227 else if (r->rrauth_report < 1000) r->rrauth_report += 100; 228 else r->rrauth_report += 1000; 229 } 230 mDNSPlatformMemZero(e, sizeof(*e)); 231 } 232 233 r->rrauth_lock = 0; 234 235 return(e); 236 } 237 238 mDNSexport AuthGroup *AuthGroupForName(AuthHash *r, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name) 239 { 240 AuthGroup *ag; 241 for (ag = r->rrauth_hash[slot]; ag; ag=ag->next) 242 if (ag->namehash == namehash && SameDomainName(ag->name, name)) 243 break; 244 return(ag); 245 } 246 247 mDNSexport AuthGroup *AuthGroupForRecord(AuthHash *r, const mDNSu32 slot, const ResourceRecord *const rr) 248 { 249 return(AuthGroupForName(r, slot, rr->namehash, rr->name)); 250 } 251 252 mDNSlocal AuthGroup *GetAuthGroup(AuthHash *r, const mDNSu32 slot, const ResourceRecord *const rr) 253 { 254 mDNSu16 namelen = DomainNameLength(rr->name); 255 AuthGroup *ag = (AuthGroup*)GetAuthEntity(r, mDNSNULL); 256 if (!ag) { LogMsg("GetAuthGroup: Failed to allocate memory for %##s", rr->name->c); return(mDNSNULL); } 257 ag->next = r->rrauth_hash[slot]; 258 ag->namehash = rr->namehash; 259 ag->members = mDNSNULL; 260 ag->rrauth_tail = &ag->members; 261 ag->name = (domainname*)ag->namestorage; 262 ag->NewLocalOnlyRecords = mDNSNULL; 263 if (namelen > InlineCacheGroupNameSize) ag->name = mDNSPlatformMemAllocate(namelen); 264 if (!ag->name) 265 { 266 LogMsg("GetAuthGroup: Failed to allocate name storage for %##s", rr->name->c); 267 ReleaseAuthEntity(r, (AuthEntity*)ag); 268 return(mDNSNULL); 269 } 270 AssignDomainName(ag->name, rr->name); 271 272 if (AuthGroupForRecord(r, slot, rr)) LogMsg("GetAuthGroup: Already have AuthGroup for %##s", rr->name->c); 273 r->rrauth_hash[slot] = ag; 274 if (AuthGroupForRecord(r, slot, rr) != ag) LogMsg("GetAuthGroup: Not finding AuthGroup for %##s", rr->name->c); 275 276 return(ag); 277 } 278 279 // Returns the AuthGroup in which the AuthRecord was inserted 280 mDNSexport AuthGroup *InsertAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr) 281 { 282 AuthGroup *ag; 283 const mDNSu32 slot = AuthHashSlot(rr->resrec.name); 284 ag = AuthGroupForRecord(r, slot, &rr->resrec); 285 if (!ag) ag = GetAuthGroup(r, slot, &rr->resrec); // If we don't have a AuthGroup for this name, make one now 286 if (ag) 287 { 288 LogInfo("InsertAuthRecord: inserting auth record %s from table", ARDisplayString(m, rr)); 289 *(ag->rrauth_tail) = rr; // Append this record to tail of cache slot list 290 ag->rrauth_tail = &(rr->next); // Advance tail pointer 291 } 292 return ag; 293 } 294 295 mDNSexport AuthGroup *RemoveAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr) 296 { 297 AuthGroup *a; 298 AuthGroup **ag = &a; 299 AuthRecord **rp; 300 const mDNSu32 slot = AuthHashSlot(rr->resrec.name); 301 302 a = AuthGroupForRecord(r, slot, &rr->resrec); 303 if (!a) { LogMsg("RemoveAuthRecord: ERROR!! AuthGroup not found for %s", ARDisplayString(m, rr)); return mDNSNULL; } 304 rp = &(*ag)->members; 305 while (*rp) 306 { 307 if (*rp != rr) 308 rp=&(*rp)->next; 309 else 310 { 311 // We don't break here, so that we can set the tail below without tracking "prev" pointers 312 313 LogInfo("RemoveAuthRecord: removing auth record %s from table", ARDisplayString(m, rr)); 314 *rp = (*rp)->next; // Cut record from list 315 } 316 } 317 // TBD: If there are no more members, release authgroup ? 318 (*ag)->rrauth_tail = rp; 319 return a; 320 } 321 322 mDNSexport CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name) 323 { 324 CacheGroup *cg; 325 for (cg = m->rrcache_hash[slot]; cg; cg=cg->next) 326 if (cg->namehash == namehash && SameDomainName(cg->name, name)) 327 break; 328 return(cg); 329 } 330 331 mDNSlocal CacheGroup *CacheGroupForRecord(const mDNS *const m, const mDNSu32 slot, const ResourceRecord *const rr) 332 { 333 return(CacheGroupForName(m, slot, rr->namehash, rr->name)); 334 } 335 336 mDNSexport mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr) 337 { 338 NetworkInterfaceInfo *intf; 339 340 if (addr->type == mDNSAddrType_IPv4) 341 { 342 // Normally we resist touching the NotAnInteger fields, but here we're doing tricky bitwise masking so we make an exception 343 if (mDNSv4AddressIsLinkLocal(&addr->ip.v4)) return(mDNStrue); 344 for (intf = m->HostInterfaces; intf; intf = intf->next) 345 if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID && intf->McastTxRx) 346 if (((intf->ip.ip.v4.NotAnInteger ^ addr->ip.v4.NotAnInteger) & intf->mask.ip.v4.NotAnInteger) == 0) 347 return(mDNStrue); 348 } 349 350 if (addr->type == mDNSAddrType_IPv6) 351 { 352 if (mDNSv6AddressIsLinkLocal(&addr->ip.v6)) return(mDNStrue); 353 for (intf = m->HostInterfaces; intf; intf = intf->next) 354 if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID && intf->McastTxRx) 355 if ((((intf->ip.ip.v6.l[0] ^ addr->ip.v6.l[0]) & intf->mask.ip.v6.l[0]) == 0) && 356 (((intf->ip.ip.v6.l[1] ^ addr->ip.v6.l[1]) & intf->mask.ip.v6.l[1]) == 0) && 357 (((intf->ip.ip.v6.l[2] ^ addr->ip.v6.l[2]) & intf->mask.ip.v6.l[2]) == 0) && 358 (((intf->ip.ip.v6.l[3] ^ addr->ip.v6.l[3]) & intf->mask.ip.v6.l[3]) == 0)) 359 return(mDNStrue); 360 } 361 362 return(mDNSfalse); 363 } 364 365 mDNSlocal NetworkInterfaceInfo *FirstInterfaceForID(mDNS *const m, const mDNSInterfaceID InterfaceID) 366 { 367 NetworkInterfaceInfo *intf = m->HostInterfaces; 368 while (intf && intf->InterfaceID != InterfaceID) intf = intf->next; 369 return(intf); 370 } 371 372 mDNSexport char *InterfaceNameForID(mDNS *const m, const mDNSInterfaceID InterfaceID) 373 { 374 NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID); 375 return(intf ? intf->ifname : mDNSNULL); 376 } 377 378 // Caller should hold the lock 379 mDNSlocal void GenerateNegativeResponse(mDNS *const m) 380 { 381 DNSQuestion *q; 382 if (!m->CurrentQuestion) { LogMsg("GenerateNegativeResponse: ERROR!! CurrentQuestion not set"); return; } 383 q = m->CurrentQuestion; 384 LogInfo("GenerateNegativeResponse: Generating negative response for question %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 385 386 MakeNegativeCacheRecord(m, &m->rec.r, &q->qname, q->qnamehash, q->qtype, q->qclass, 60, mDNSInterface_Any, mDNSNULL); 387 AnswerCurrentQuestionWithResourceRecord(m, &m->rec.r, QC_addnocache); 388 if (m->CurrentQuestion == q) { q->ThisQInterval = 0; } // Deactivate this question 389 // Don't touch the question after this 390 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 391 } 392 393 mDNSlocal void AnswerQuestionByFollowingCNAME(mDNS *const m, DNSQuestion *q, ResourceRecord *rr) 394 { 395 const mDNSBool selfref = SameDomainName(&q->qname, &rr->rdata->u.name); 396 if (q->CNAMEReferrals >= 10 || selfref) 397 LogMsg("AnswerQuestionByFollowingCNAME: %p %##s (%s) NOT following CNAME referral %d%s for %s", 398 q, q->qname.c, DNSTypeName(q->qtype), q->CNAMEReferrals, selfref ? " (Self-Referential)" : "", RRDisplayString(m, rr)); 399 else 400 { 401 const mDNSu32 c = q->CNAMEReferrals + 1; // Stash a copy of the new q->CNAMEReferrals value 402 403 // The SameDomainName check above is to ignore bogus CNAME records that point right back at 404 // themselves. Without that check we can get into a case where we have two duplicate questions, 405 // A and B, and when we stop question A, UpdateQuestionDuplicates copies the value of CNAMEReferrals 406 // from A to B, and then A is re-appended to the end of the list as a duplicate of B (because 407 // the target name is still the same), and then when we stop question B, UpdateQuestionDuplicates 408 // copies the B's value of CNAMEReferrals back to A, and we end up not incrementing CNAMEReferrals 409 // for either of them. This is not a problem for CNAME loops of two or more records because in 410 // those cases the newly re-appended question A has a different target name and therefore cannot be 411 // a duplicate of any other question ('B') which was itself a duplicate of the previous question A. 412 413 // Right now we just stop and re-use the existing query. If we really wanted to be 100% perfect, 414 // and track CNAMEs coming and going, we should really create a subordinate query here, 415 // which we would subsequently cancel and retract if the CNAME referral record were removed. 416 // In reality this is such a corner case we'll ignore it until someone actually needs it. 417 418 LogInfo("AnswerQuestionByFollowingCNAME: %p %##s (%s) following CNAME referral %d for %s", 419 q, q->qname.c, DNSTypeName(q->qtype), q->CNAMEReferrals, RRDisplayString(m, rr)); 420 421 mDNS_StopQuery_internal(m, q); // Stop old query 422 AssignDomainName(&q->qname, &rr->rdata->u.name); // Update qname 423 q->qnamehash = DomainNameHashValue(&q->qname); // and namehash 424 // If a unicast query results in a CNAME that points to a .local, we need to re-try 425 // this as unicast. Setting the mDNSInterface_Unicast tells mDNS_StartQuery_internal 426 // to try this as unicast query even though it is a .local name 427 if (!mDNSOpaque16IsZero(q->TargetQID) && IsLocalDomain(&q->qname)) 428 { 429 LogInfo("AnswerQuestionByFollowingCNAME: Resolving a .local CNAME %p %##s (%s) Record %s", 430 q, q->qname.c, DNSTypeName(q->qtype), RRDisplayString(m, rr)); 431 q->InterfaceID = mDNSInterface_Unicast; 432 } 433 mDNS_StartQuery_internal(m, q); // start new query 434 // Record how many times we've done this. We need to do this *after* mDNS_StartQuery_internal, 435 // because mDNS_StartQuery_internal re-initializes CNAMEReferrals to zero 436 q->CNAMEReferrals = c; 437 } 438 } 439 440 // For a single given DNSQuestion pointed to by CurrentQuestion, deliver an add/remove result for the single given AuthRecord 441 // Note: All the callers should use the m->CurrentQuestion to see if the question is still valid or not 442 mDNSlocal void AnswerLocalQuestionWithLocalAuthRecord(mDNS *const m, AuthRecord *rr, QC_result AddRecord) 443 { 444 DNSQuestion *q = m->CurrentQuestion; 445 mDNSBool followcname; 446 447 if (!q) 448 { 449 LogMsg("AnswerLocalQuestionWithLocalAuthRecord: ERROR!! CurrentQuestion NULL while answering with %s", ARDisplayString(m, rr)); 450 return; 451 } 452 453 followcname = FollowCNAME(q, &rr->resrec, AddRecord); 454 455 // We should not be delivering results for record types Unregistered, Deregistering, and (unverified) Unique 456 if (!(rr->resrec.RecordType & kDNSRecordTypeActiveMask)) 457 { 458 LogMsg("AnswerLocalQuestionWithLocalAuthRecord: *NOT* delivering %s event for local record type %X %s", 459 AddRecord ? "Add" : "Rmv", rr->resrec.RecordType, ARDisplayString(m, rr)); 460 return; 461 } 462 463 // Indicate that we've given at least one positive answer for this record, so we should be prepared to send a goodbye for it 464 if (AddRecord) rr->AnsweredLocalQ = mDNStrue; 465 mDNS_DropLockBeforeCallback(); // Allow client to legally make mDNS API calls from the callback 466 if (q->QuestionCallback && !q->NoAnswer) 467 { 468 q->CurrentAnswers += AddRecord ? 1 : -1; 469 if (LORecordAnswersAddressType(rr)) 470 { 471 if (!followcname || q->ReturnIntermed) 472 { 473 // Don't send this packet on the wire as we answered from /etc/hosts 474 q->ThisQInterval = 0; 475 q->LOAddressAnswers += AddRecord ? 1 : -1; 476 q->QuestionCallback(m, q, &rr->resrec, AddRecord); 477 } 478 mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again 479 // The callback above could have caused the question to stop. Detect that 480 // using m->CurrentQuestion 481 if (followcname && m->CurrentQuestion == q) 482 AnswerQuestionByFollowingCNAME(m, q, &rr->resrec); 483 return; 484 } 485 else 486 q->QuestionCallback(m, q, &rr->resrec, AddRecord); 487 } 488 mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again 489 } 490 491 mDNSlocal void AnswerInterfaceAnyQuestionsWithLocalAuthRecord(mDNS *const m, AuthRecord *rr, QC_result AddRecord) 492 { 493 if (m->CurrentQuestion) 494 LogMsg("AnswerInterfaceAnyQuestionsWithLocalAuthRecord: ERROR m->CurrentQuestion already set: %##s (%s)", 495 m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype)); 496 m->CurrentQuestion = m->Questions; 497 while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions) 498 { 499 mDNSBool answered; 500 DNSQuestion *q = m->CurrentQuestion; 501 if (RRAny(rr)) 502 answered = ResourceRecordAnswersQuestion(&rr->resrec, q); 503 else 504 answered = LocalOnlyRecordAnswersQuestion(rr, q); 505 if (answered) 506 AnswerLocalQuestionWithLocalAuthRecord(m, rr, AddRecord); // MUST NOT dereference q again 507 if (m->CurrentQuestion == q) // If m->CurrentQuestion was not auto-advanced, do it ourselves now 508 m->CurrentQuestion = q->next; 509 } 510 m->CurrentQuestion = mDNSNULL; 511 } 512 513 // When a new local AuthRecord is created or deleted, AnswerAllLocalQuestionsWithLocalAuthRecord() 514 // delivers the appropriate add/remove events to listening questions: 515 // 1. It runs though all our LocalOnlyQuestions delivering answers as appropriate, 516 // stopping if it reaches a NewLocalOnlyQuestion -- brand-new questions are handled by AnswerNewLocalOnlyQuestion(). 517 // 2. If the AuthRecord is marked mDNSInterface_LocalOnly or mDNSInterface_P2P, then it also runs though 518 // our main question list, delivering answers to mDNSInterface_Any questions as appropriate, 519 // stopping if it reaches a NewQuestion -- brand-new questions are handled by AnswerNewQuestion(). 520 // 521 // AnswerAllLocalQuestionsWithLocalAuthRecord is used by the m->NewLocalRecords loop in mDNS_Execute(), 522 // and by mDNS_Deregister_internal() 523 524 mDNSlocal void AnswerAllLocalQuestionsWithLocalAuthRecord(mDNS *const m, AuthRecord *rr, QC_result AddRecord) 525 { 526 if (m->CurrentQuestion) 527 LogMsg("AnswerAllLocalQuestionsWithLocalAuthRecord ERROR m->CurrentQuestion already set: %##s (%s)", 528 m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype)); 529 530 m->CurrentQuestion = m->LocalOnlyQuestions; 531 while (m->CurrentQuestion && m->CurrentQuestion != m->NewLocalOnlyQuestions) 532 { 533 mDNSBool answered; 534 DNSQuestion *q = m->CurrentQuestion; 535 // We are called with both LocalOnly/P2P record or a regular AuthRecord 536 if (RRAny(rr)) 537 answered = ResourceRecordAnswersQuestion(&rr->resrec, q); 538 else 539 answered = LocalOnlyRecordAnswersQuestion(rr, q); 540 if (answered) 541 AnswerLocalQuestionWithLocalAuthRecord(m, rr, AddRecord); // MUST NOT dereference q again 542 if (m->CurrentQuestion == q) // If m->CurrentQuestion was not auto-advanced, do it ourselves now 543 m->CurrentQuestion = q->next; 544 } 545 546 m->CurrentQuestion = mDNSNULL; 547 548 // If this AuthRecord is marked LocalOnly or P2P, then we want to deliver it to all local 'mDNSInterface_Any' questions 549 if (rr->ARType == AuthRecordLocalOnly || rr->ARType == AuthRecordP2P) 550 AnswerInterfaceAnyQuestionsWithLocalAuthRecord(m, rr, AddRecord); 551 552 } 553 554 // *************************************************************************** 555 #if COMPILER_LIKES_PRAGMA_MARK 556 #pragma mark - 557 #pragma mark - Resource Record Utility Functions 558 #endif 559 560 #define RRTypeIsAddressType(T) ((T) == kDNSType_A || (T) == kDNSType_AAAA) 561 562 #define ResourceRecordIsValidAnswer(RR) ( ((RR)-> resrec.RecordType & kDNSRecordTypeActiveMask) && \ 563 ((RR)->Additional1 == mDNSNULL || ((RR)->Additional1->resrec.RecordType & kDNSRecordTypeActiveMask)) && \ 564 ((RR)->Additional2 == mDNSNULL || ((RR)->Additional2->resrec.RecordType & kDNSRecordTypeActiveMask)) && \ 565 ((RR)->DependentOn == mDNSNULL || ((RR)->DependentOn->resrec.RecordType & kDNSRecordTypeActiveMask)) ) 566 567 #define ResourceRecordIsValidInterfaceAnswer(RR, INTID) \ 568 (ResourceRecordIsValidAnswer(RR) && \ 569 ((RR)->resrec.InterfaceID == mDNSInterface_Any || (RR)->resrec.InterfaceID == (INTID))) 570 571 #define DefaultProbeCountForTypeUnique ((mDNSu8)3) 572 #define DefaultProbeCountForRecordType(X) ((X) == kDNSRecordTypeUnique ? DefaultProbeCountForTypeUnique : (mDNSu8)0) 573 574 #define InitialAnnounceCount ((mDNSu8)8) 575 576 // For goodbye packets we set the count to 3, and for wakeups we set it to 18 577 // (which will be up to 15 wakeup attempts over the course of 30 seconds, 578 // and then if the machine fails to wake, 3 goodbye packets). 579 #define GoodbyeCount ((mDNSu8)3) 580 #define WakeupCount ((mDNSu8)18) 581 582 // Number of wakeups we send if WakeOnResolve is set in the question 583 #define InitialWakeOnResolveCount ((mDNSu8)3) 584 585 // Note that the announce intervals use exponential backoff, doubling each time. The probe intervals do not. 586 // This means that because the announce interval is doubled after sending the first packet, the first 587 // observed on-the-wire inter-packet interval between announcements is actually one second. 588 // The half-second value here may be thought of as a conceptual (non-existent) half-second delay *before* the first packet is sent. 589 #define DefaultProbeIntervalForTypeUnique (mDNSPlatformOneSecond/4) 590 #define DefaultAnnounceIntervalForTypeShared (mDNSPlatformOneSecond/2) 591 #define DefaultAnnounceIntervalForTypeUnique (mDNSPlatformOneSecond/2) 592 593 #define DefaultAPIntervalForRecordType(X) ((X) & kDNSRecordTypeActiveSharedMask ? DefaultAnnounceIntervalForTypeShared : \ 594 (X) & kDNSRecordTypeUnique ? DefaultProbeIntervalForTypeUnique : \ 595 (X) & kDNSRecordTypeActiveUniqueMask ? DefaultAnnounceIntervalForTypeUnique : 0) 596 597 #define TimeToAnnounceThisRecord(RR,time) ((RR)->AnnounceCount && (time) - ((RR)->LastAPTime + (RR)->ThisAPInterval) >= 0) 598 #define TimeToSendThisRecord(RR,time) ((TimeToAnnounceThisRecord(RR,time) || (RR)->ImmedAnswer) && ResourceRecordIsValidAnswer(RR)) 599 #define TicksTTL(RR) ((mDNSs32)(RR)->resrec.rroriginalttl * mDNSPlatformOneSecond) 600 #define RRExpireTime(RR) ((RR)->TimeRcvd + TicksTTL(RR)) 601 602 #define MaxUnansweredQueries 4 603 604 // SameResourceRecordSignature returns true if two resources records have the same name, type, and class, and may be sent 605 // (or were received) on the same interface (i.e. if *both* records specify an interface, then it has to match). 606 // TTL and rdata may differ. 607 // This is used for cache flush management: 608 // When sending a unique record, all other records matching "SameResourceRecordSignature" must also be sent 609 // When receiving a unique record, all old cache records matching "SameResourceRecordSignature" are flushed 610 611 // SameResourceRecordNameClassInterface is functionally the same as SameResourceRecordSignature, except rrtype does not have to match 612 613 #define SameResourceRecordSignature(A,B) (A)->resrec.rrtype == (B)->resrec.rrtype && SameResourceRecordNameClassInterface((A),(B)) 614 615 mDNSlocal mDNSBool SameResourceRecordNameClassInterface(const AuthRecord *const r1, const AuthRecord *const r2) 616 { 617 if (!r1) { LogMsg("SameResourceRecordSignature ERROR: r1 is NULL"); return(mDNSfalse); } 618 if (!r2) { LogMsg("SameResourceRecordSignature ERROR: r2 is NULL"); return(mDNSfalse); } 619 if (r1->resrec.InterfaceID && 620 r2->resrec.InterfaceID && 621 r1->resrec.InterfaceID != r2->resrec.InterfaceID) return(mDNSfalse); 622 return(mDNSBool)( 623 r1->resrec.rrclass == r2->resrec.rrclass && 624 r1->resrec.namehash == r2->resrec.namehash && 625 SameDomainName(r1->resrec.name, r2->resrec.name)); 626 } 627 628 // PacketRRMatchesSignature behaves as SameResourceRecordSignature, except that types may differ if our 629 // authoratative record is unique (as opposed to shared). For unique records, we are supposed to have 630 // complete ownership of *all* types for this name, so *any* record type with the same name is a conflict. 631 // In addition, when probing we send our questions with the wildcard type kDNSQType_ANY, 632 // so a response of any type should match, even if it is not actually the type the client plans to use. 633 634 // For now, to make it easier to avoid false conflicts, we treat SPS Proxy records like shared records, 635 // and require the rrtypes to match for the rdata to be considered potentially conflicting 636 mDNSlocal mDNSBool PacketRRMatchesSignature(const CacheRecord *const pktrr, const AuthRecord *const authrr) 637 { 638 if (!pktrr) { LogMsg("PacketRRMatchesSignature ERROR: pktrr is NULL"); return(mDNSfalse); } 639 if (!authrr) { LogMsg("PacketRRMatchesSignature ERROR: authrr is NULL"); return(mDNSfalse); } 640 if (pktrr->resrec.InterfaceID && 641 authrr->resrec.InterfaceID && 642 pktrr->resrec.InterfaceID != authrr->resrec.InterfaceID) return(mDNSfalse); 643 if (!(authrr->resrec.RecordType & kDNSRecordTypeUniqueMask) || authrr->WakeUp.HMAC.l[0]) 644 if (pktrr->resrec.rrtype != authrr->resrec.rrtype) return(mDNSfalse); 645 return(mDNSBool)( 646 pktrr->resrec.rrclass == authrr->resrec.rrclass && 647 pktrr->resrec.namehash == authrr->resrec.namehash && 648 SameDomainName(pktrr->resrec.name, authrr->resrec.name)); 649 } 650 651 // CacheRecord *ka is the CacheRecord from the known answer list in the query. 652 // This is the information that the requester believes to be correct. 653 // AuthRecord *rr is the answer we are proposing to give, if not suppressed. 654 // This is the information that we believe to be correct. 655 // We've already determined that we plan to give this answer on this interface 656 // (either the record is non-specific, or it is specific to this interface) 657 // so now we just need to check the name, type, class, rdata and TTL. 658 mDNSlocal mDNSBool ShouldSuppressKnownAnswer(const CacheRecord *const ka, const AuthRecord *const rr) 659 { 660 // If RR signature is different, or data is different, then don't suppress our answer 661 if (!IdenticalResourceRecord(&ka->resrec, &rr->resrec)) return(mDNSfalse); 662 663 // If the requester's indicated TTL is less than half the real TTL, 664 // we need to give our answer before the requester's copy expires. 665 // If the requester's indicated TTL is at least half the real TTL, 666 // then we can suppress our answer this time. 667 // If the requester's indicated TTL is greater than the TTL we believe, 668 // then that's okay, and we don't need to do anything about it. 669 // (If two responders on the network are offering the same information, 670 // that's okay, and if they are offering the information with different TTLs, 671 // the one offering the lower TTL should defer to the one offering the higher TTL.) 672 return(mDNSBool)(ka->resrec.rroriginalttl >= rr->resrec.rroriginalttl / 2); 673 } 674 675 mDNSlocal void SetNextAnnounceProbeTime(mDNS *const m, const AuthRecord *const rr) 676 { 677 if (rr->resrec.RecordType == kDNSRecordTypeUnique) 678 { 679 if ((rr->LastAPTime + rr->ThisAPInterval) - m->timenow > mDNSPlatformOneSecond * 10) 680 { 681 LogMsg("SetNextAnnounceProbeTime: ProbeCount %d Next in %d %s", rr->ProbeCount, (rr->LastAPTime + rr->ThisAPInterval) - m->timenow, ARDisplayString(m, rr)); 682 LogMsg("SetNextAnnounceProbeTime: m->SuppressProbes %d m->timenow %d diff %d", m->SuppressProbes, m->timenow, m->SuppressProbes - m->timenow); 683 } 684 if (m->NextScheduledProbe - (rr->LastAPTime + rr->ThisAPInterval) >= 0) 685 m->NextScheduledProbe = (rr->LastAPTime + rr->ThisAPInterval); 686 // Some defensive code: 687 // If (rr->LastAPTime + rr->ThisAPInterval) happens to be far in the past, we don't want to allow 688 // NextScheduledProbe to be set excessively in the past, because that can cause bad things to happen. 689 // See: <rdar://problem/7795434> mDNS: Sometimes advertising stops working and record interval is set to zero 690 if (m->NextScheduledProbe - m->timenow < 0) 691 m->NextScheduledProbe = m->timenow; 692 } 693 else if (rr->AnnounceCount && (ResourceRecordIsValidAnswer(rr) || rr->resrec.RecordType == kDNSRecordTypeDeregistering)) 694 { 695 if (m->NextScheduledResponse - (rr->LastAPTime + rr->ThisAPInterval) >= 0) 696 m->NextScheduledResponse = (rr->LastAPTime + rr->ThisAPInterval); 697 } 698 } 699 700 mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr) 701 { 702 // For reverse-mapping Sleep Proxy PTR records, probe interval is one second 703 rr->ThisAPInterval = rr->AddressProxy.type ? mDNSPlatformOneSecond : DefaultAPIntervalForRecordType(rr->resrec.RecordType); 704 705 // * If this is a record type that's going to probe, then we use the m->SuppressProbes time. 706 // * Otherwise, if it's not going to probe, but m->SuppressProbes is set because we have other 707 // records that are going to probe, then we delay its first announcement so that it will 708 // go out synchronized with the first announcement for the other records that *are* probing. 709 // This is a minor performance tweak that helps keep groups of related records synchronized together. 710 // The addition of "interval / 2" is to make sure that, in the event that any of the probes are 711 // delayed by a few milliseconds, this announcement does not inadvertently go out *before* the probing is complete. 712 // When the probing is complete and those records begin to announce, these records will also be picked up and accelerated, 713 // because they will meet the criterion of being at least half-way to their scheduled announcement time. 714 // * If it's not going to probe and m->SuppressProbes is not already set then we should announce immediately. 715 716 if (rr->ProbeCount) 717 { 718 // If we have no probe suppression time set, or it is in the past, set it now 719 if (m->SuppressProbes == 0 || m->SuppressProbes - m->timenow < 0) 720 { 721 // To allow us to aggregate probes when a group of services are registered together, 722 // the first probe is delayed 1/4 second. This means the common-case behaviour is: 723 // 1/4 second wait; probe 724 // 1/4 second wait; probe 725 // 1/4 second wait; probe 726 // 1/4 second wait; announce (i.e. service is normally announced exactly one second after being registered) 727 m->SuppressProbes = NonZeroTime(m->timenow + DefaultProbeIntervalForTypeUnique/2 + mDNSRandom(DefaultProbeIntervalForTypeUnique/2)); 728 729 // If we already have a *probe* scheduled to go out sooner, then use that time to get better aggregation 730 if (m->SuppressProbes - m->NextScheduledProbe >= 0) 731 m->SuppressProbes = NonZeroTime(m->NextScheduledProbe); 732 if (m->SuppressProbes - m->timenow < 0) // Make sure we don't set m->SuppressProbes excessively in the past 733 m->SuppressProbes = m->timenow; 734 735 // If we already have a *query* scheduled to go out sooner, then use that time to get better aggregation 736 if (m->SuppressProbes - m->NextScheduledQuery >= 0) 737 m->SuppressProbes = NonZeroTime(m->NextScheduledQuery); 738 if (m->SuppressProbes - m->timenow < 0) // Make sure we don't set m->SuppressProbes excessively in the past 739 m->SuppressProbes = m->timenow; 740 741 // except... don't expect to be able to send before the m->SuppressSending timer fires 742 if (m->SuppressSending && m->SuppressProbes - m->SuppressSending < 0) 743 m->SuppressProbes = NonZeroTime(m->SuppressSending); 744 745 if (m->SuppressProbes - m->timenow > mDNSPlatformOneSecond * 8) 746 { 747 LogMsg("InitializeLastAPTime ERROR m->SuppressProbes %d m->NextScheduledProbe %d m->NextScheduledQuery %d m->SuppressSending %d %d", 748 m->SuppressProbes - m->timenow, 749 m->NextScheduledProbe - m->timenow, 750 m->NextScheduledQuery - m->timenow, 751 m->SuppressSending, 752 m->SuppressSending - m->timenow); 753 m->SuppressProbes = NonZeroTime(m->timenow + DefaultProbeIntervalForTypeUnique/2 + mDNSRandom(DefaultProbeIntervalForTypeUnique/2)); 754 } 755 } 756 rr->LastAPTime = m->SuppressProbes - rr->ThisAPInterval; 757 } 758 else if (m->SuppressProbes && m->SuppressProbes - m->timenow >= 0) 759 rr->LastAPTime = m->SuppressProbes - rr->ThisAPInterval + DefaultProbeIntervalForTypeUnique * DefaultProbeCountForTypeUnique + rr->ThisAPInterval / 2; 760 else 761 rr->LastAPTime = m->timenow - rr->ThisAPInterval; 762 763 // For reverse-mapping Sleep Proxy PTR records we don't want to start probing instantly -- we 764 // wait one second to give the client a chance to go to sleep, and then start our ARP/NDP probing. 765 // After three probes one second apart with no answer, we conclude the client is now sleeping 766 // and we can begin broadcasting our announcements to take over ownership of that IP address. 767 // If we don't wait for the client to go to sleep, then when the client sees our ARP Announcements there's a risk 768 // (depending on the OS and networking stack it's using) that it might interpret it as a conflict and change its IP address. 769 if (rr->AddressProxy.type) rr->LastAPTime = m->timenow; 770 771 // Unsolicited Neighbor Advertisements (RFC 2461 Section 7.2.6) give us fast address cache updating, 772 // but some older IPv6 clients get confused by them, so for now we don't send them. Without Unsolicited 773 // Neighbor Advertisements we have to rely on Neighbor Unreachability Detection instead, which is slower. 774 // Given this, we'll do our best to wake for existing IPv6 connections, but we don't want to encourage 775 // new ones for sleeping clients, so we'll we send deletions for our SPS clients' AAAA records. 776 if (m->KnownBugs & mDNS_KnownBug_LimitedIPv6) 777 if (rr->WakeUp.HMAC.l[0] && rr->resrec.rrtype == kDNSType_AAAA) 778 rr->LastAPTime = m->timenow - rr->ThisAPInterval + mDNSPlatformOneSecond * 10; 779 780 // Set LastMCTime to now, to inhibit multicast responses 781 // (no need to send additional multicast responses when we're announcing anyway) 782 rr->LastMCTime = m->timenow; 783 rr->LastMCInterface = mDNSInterfaceMark; 784 785 SetNextAnnounceProbeTime(m, rr); 786 } 787 788 mDNSlocal const domainname *SetUnicastTargetToHostName(mDNS *const m, AuthRecord *rr) 789 { 790 const domainname *target; 791 if (rr->AutoTarget) 792 { 793 // For autotunnel services pointing at our IPv6 ULA we don't need or want a NAT mapping, but for all other 794 // advertised services referencing our uDNS hostname, we want NAT mappings automatically created as appropriate, 795 // with the port number in our advertised SRV record automatically tracking the external mapped port. 796 DomainAuthInfo *AuthInfo = GetAuthInfoForName_internal(m, rr->resrec.name); 797 if (!AuthInfo || !AuthInfo->AutoTunnel) rr->AutoTarget = Target_AutoHostAndNATMAP; 798 } 799 800 target = GetServiceTarget(m, rr); 801 if (!target || target->c[0] == 0) 802 { 803 // defer registration until we've got a target 804 LogInfo("SetUnicastTargetToHostName No target for %s", ARDisplayString(m, rr)); 805 rr->state = regState_NoTarget; 806 return mDNSNULL; 807 } 808 else 809 { 810 LogInfo("SetUnicastTargetToHostName target %##s for resource record %s", target->c, ARDisplayString(m,rr)); 811 return target; 812 } 813 } 814 815 // Right now this only applies to mDNS (.local) services where the target host is always m->MulticastHostname 816 // Eventually we should unify this with GetServiceTarget() in uDNS.c 817 mDNSlocal void SetTargetToHostName(mDNS *const m, AuthRecord *const rr) 818 { 819 domainname *const target = GetRRDomainNameTarget(&rr->resrec); 820 const domainname *newname = &m->MulticastHostname; 821 822 if (!target) LogInfo("SetTargetToHostName: Don't know how to set the target of rrtype %s", DNSTypeName(rr->resrec.rrtype)); 823 824 if (!(rr->ForceMCast || rr->ARType == AuthRecordLocalOnly || rr->ARType == AuthRecordP2P || IsLocalDomain(&rr->namestorage))) 825 { 826 const domainname *const n = SetUnicastTargetToHostName(m, rr); 827 if (n) newname = n; 828 else { target->c[0] = 0; SetNewRData(&rr->resrec, mDNSNULL, 0); return; } 829 } 830 831 if (target && SameDomainName(target, newname)) 832 debugf("SetTargetToHostName: Target of %##s is already %##s", rr->resrec.name->c, target->c); 833 834 if (target && !SameDomainName(target, newname)) 835 { 836 AssignDomainName(target, newname); 837 SetNewRData(&rr->resrec, mDNSNULL, 0); // Update rdlength, rdestimate, rdatahash 838 839 // If we're in the middle of probing this record, we need to start again, 840 // because changing its rdata may change the outcome of the tie-breaker. 841 // (If the record type is kDNSRecordTypeUnique (unconfirmed unique) then DefaultProbeCountForRecordType is non-zero.) 842 rr->ProbeCount = DefaultProbeCountForRecordType(rr->resrec.RecordType); 843 844 // If we've announced this record, we really should send a goodbye packet for the old rdata before 845 // changing to the new rdata. However, in practice, we only do SetTargetToHostName for unique records, 846 // so when we announce them we'll set the kDNSClass_UniqueRRSet and clear any stale data that way. 847 if (rr->RequireGoodbye && rr->resrec.RecordType == kDNSRecordTypeShared) 848 debugf("Have announced shared record %##s (%s) at least once: should have sent a goodbye packet before updating", 849 rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 850 851 rr->AnnounceCount = InitialAnnounceCount; 852 rr->RequireGoodbye = mDNSfalse; 853 InitializeLastAPTime(m, rr); 854 } 855 } 856 857 mDNSlocal void AcknowledgeRecord(mDNS *const m, AuthRecord *const rr) 858 { 859 if (rr->RecordCallback) 860 { 861 // CAUTION: MUST NOT do anything more with rr after calling rr->Callback(), because the client's callback function 862 // is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc. 863 rr->Acknowledged = mDNStrue; 864 mDNS_DropLockBeforeCallback(); // Allow client to legally make mDNS API calls from the callback 865 rr->RecordCallback(m, rr, mStatus_NoError); 866 mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again 867 } 868 } 869 870 mDNSexport void ActivateUnicastRegistration(mDNS *const m, AuthRecord *const rr) 871 { 872 // Make sure that we don't activate the SRV record and associated service records, if it is in 873 // NoTarget state. First time when a service is being instantiated, SRV record may be in NoTarget state. 874 // We should not activate any of the other reords (PTR, TXT) that are part of the service. When 875 // the target becomes available, the records will be reregistered. 876 if (rr->resrec.rrtype != kDNSType_SRV) 877 { 878 AuthRecord *srvRR = mDNSNULL; 879 if (rr->resrec.rrtype == kDNSType_PTR) 880 srvRR = rr->Additional1; 881 else if (rr->resrec.rrtype == kDNSType_TXT) 882 srvRR = rr->DependentOn; 883 if (srvRR) 884 { 885 if (srvRR->resrec.rrtype != kDNSType_SRV) 886 { 887 LogMsg("ActivateUnicastRegistration: ERROR!! Resource record %s wrong, expecting SRV type", ARDisplayString(m, srvRR)); 888 } 889 else 890 { 891 LogInfo("ActivateUnicastRegistration: Found Service Record %s in state %d for %##s (%s)", 892 ARDisplayString(m, srvRR), srvRR->state, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 893 rr->state = srvRR->state; 894 } 895 } 896 } 897 898 if (rr->state == regState_NoTarget) 899 { 900 LogInfo("ActivateUnicastRegistration record %s in regState_NoTarget, not activating", ARDisplayString(m, rr)); 901 return; 902 } 903 // When we wake up from sleep, we call ActivateUnicastRegistration. It is possible that just before we went to sleep, 904 // the service/record was being deregistered. In that case, we should not try to register again. For the cases where 905 // the records are deregistered due to e.g., no target for the SRV record, we would have returned from above if it 906 // was already in NoTarget state. If it was in the process of deregistration but did not complete fully before we went 907 // to sleep, then it is okay to start in Pending state as we will go back to NoTarget state if we don't have a target. 908 if (rr->resrec.RecordType == kDNSRecordTypeDeregistering) 909 { 910 LogInfo("ActivateUnicastRegistration: Resource record %s, current state %d, moving to DeregPending", ARDisplayString(m, rr), rr->state); 911 rr->state = regState_DeregPending; 912 } 913 else 914 { 915 LogInfo("ActivateUnicastRegistration: Resource record %s, current state %d, moving to Pending", ARDisplayString(m, rr), rr->state); 916 rr->state = regState_Pending; 917 } 918 rr->ProbeCount = 0; 919 rr->AnnounceCount = 0; 920 rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL; 921 rr->LastAPTime = m->timenow - rr->ThisAPInterval; 922 rr->expire = 0; // Forget about all the leases, start fresh 923 rr->uselease = mDNStrue; 924 rr->updateid = zeroID; 925 rr->SRVChanged = mDNSfalse; 926 rr->updateError = mStatus_NoError; 927 // RestartRecordGetZoneData calls this function whenever a new interface gets registered with core. 928 // The records might already be registered with the server and hence could have NAT state. 929 if (rr->NATinfo.clientContext) 930 { 931 mDNS_StopNATOperation_internal(m, &rr->NATinfo); 932 rr->NATinfo.clientContext = mDNSNULL; 933 } 934 if (rr->nta) { CancelGetZoneData(m, rr->nta); rr->nta = mDNSNULL; } 935 if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; } 936 if (m->NextuDNSEvent - (rr->LastAPTime + rr->ThisAPInterval) >= 0) 937 m->NextuDNSEvent = (rr->LastAPTime + rr->ThisAPInterval); 938 } 939 940 // Two records qualify to be local duplicates if: 941 // (a) the RecordTypes are the same, or 942 // (b) one is Unique and the other Verified 943 // (c) either is in the process of deregistering 944 #define RecordLDT(A,B) ((A)->resrec.RecordType == (B)->resrec.RecordType || \ 945 ((A)->resrec.RecordType | (B)->resrec.RecordType) == (kDNSRecordTypeUnique | kDNSRecordTypeVerified) || \ 946 ((A)->resrec.RecordType == kDNSRecordTypeDeregistering || (B)->resrec.RecordType == kDNSRecordTypeDeregistering)) 947 948 #define RecordIsLocalDuplicate(A,B) \ 949 ((A)->resrec.InterfaceID == (B)->resrec.InterfaceID && RecordLDT((A),(B)) && IdenticalResourceRecord(&(A)->resrec, &(B)->resrec)) 950 951 mDNSlocal AuthRecord *CheckAuthIdenticalRecord(AuthHash *r, AuthRecord *rr) 952 { 953 AuthGroup *a; 954 AuthGroup **ag = &a; 955 AuthRecord **rp; 956 const mDNSu32 slot = AuthHashSlot(rr->resrec.name); 957 958 a = AuthGroupForRecord(r, slot, &rr->resrec); 959 if (!a) return mDNSNULL; 960 rp = &(*ag)->members; 961 while (*rp) 962 { 963 if (!RecordIsLocalDuplicate(*rp, rr)) 964 rp=&(*rp)->next; 965 else 966 { 967 if ((*rp)->resrec.RecordType == kDNSRecordTypeDeregistering) 968 { 969 (*rp)->AnnounceCount = 0; 970 rp=&(*rp)->next; 971 } 972 else return *rp; 973 } 974 } 975 return (mDNSNULL); 976 } 977 978 mDNSlocal mDNSBool CheckAuthRecordConflict(AuthHash *r, AuthRecord *rr) 979 { 980 AuthGroup *a; 981 AuthGroup **ag = &a; 982 AuthRecord **rp; 983 const mDNSu32 slot = AuthHashSlot(rr->resrec.name); 984 985 a = AuthGroupForRecord(r, slot, &rr->resrec); 986 if (!a) return mDNSfalse; 987 rp = &(*ag)->members; 988 while (*rp) 989 { 990 const AuthRecord *s1 = rr->RRSet ? rr->RRSet : rr; 991 const AuthRecord *s2 = (*rp)->RRSet ? (*rp)->RRSet : *rp; 992 if (s1 != s2 && SameResourceRecordSignature((*rp), rr) && !IdenticalSameNameRecord(&(*rp)->resrec, &rr->resrec)) 993 return mDNStrue; 994 else 995 rp=&(*rp)->next; 996 } 997 return (mDNSfalse); 998 } 999 1000 // checks to see if "rr" is already present 1001 mDNSlocal AuthRecord *CheckAuthSameRecord(AuthHash *r, AuthRecord *rr) 1002 { 1003 AuthGroup *a; 1004 AuthGroup **ag = &a; 1005 AuthRecord **rp; 1006 const mDNSu32 slot = AuthHashSlot(rr->resrec.name); 1007 1008 a = AuthGroupForRecord(r, slot, &rr->resrec); 1009 if (!a) return mDNSNULL; 1010 rp = &(*ag)->members; 1011 while (*rp) 1012 { 1013 if (*rp != rr) 1014 rp=&(*rp)->next; 1015 else 1016 { 1017 return *rp; 1018 } 1019 } 1020 return (mDNSNULL); 1021 } 1022 1023 // Exported so uDNS.c can call this 1024 mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) 1025 { 1026 domainname *target = GetRRDomainNameTarget(&rr->resrec); 1027 AuthRecord *r; 1028 AuthRecord **p = &m->ResourceRecords; 1029 AuthRecord **d = &m->DuplicateRecords; 1030 1031 if ((mDNSs32)rr->resrec.rroriginalttl <= 0) 1032 { LogMsg("mDNS_Register_internal: TTL %X should be 1 - 0x7FFFFFFF %s", rr->resrec.rroriginalttl, ARDisplayString(m, rr)); return(mStatus_BadParamErr); } 1033 1034 if (!rr->resrec.RecordType) 1035 { LogMsg("mDNS_Register_internal: RecordType must be non-zero %s", ARDisplayString(m, rr)); return(mStatus_BadParamErr); } 1036 1037 if (m->ShutdownTime) 1038 { LogMsg("mDNS_Register_internal: Shutting down, can't register %s", ARDisplayString(m, rr)); return(mStatus_ServiceNotRunning); } 1039 1040 if (m->DivertMulticastAdvertisements && !AuthRecord_uDNS(rr)) 1041 { 1042 mDNSInterfaceID previousID = rr->resrec.InterfaceID; 1043 if (rr->resrec.InterfaceID == mDNSInterface_Any || rr->resrec.InterfaceID == mDNSInterface_P2P) 1044 { 1045 rr->resrec.InterfaceID = mDNSInterface_LocalOnly; 1046 rr->ARType = AuthRecordLocalOnly; 1047 } 1048 if (rr->resrec.InterfaceID != mDNSInterface_LocalOnly) 1049 { 1050 NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID); 1051 if (intf && !intf->Advertise){ rr->resrec.InterfaceID = mDNSInterface_LocalOnly; rr->ARType = AuthRecordLocalOnly; } 1052 } 1053 if (rr->resrec.InterfaceID != previousID) 1054 LogInfo("mDNS_Register_internal: Diverting record to local-only %s", ARDisplayString(m, rr)); 1055 } 1056 1057 if (RRLocalOnly(rr)) 1058 { 1059 if (CheckAuthSameRecord(&m->rrauth, rr)) 1060 { 1061 LogMsg("mDNS_Register_internal: ERROR!! Tried to register LocalOnly AuthRecord %p %##s (%s) that's already in the list", 1062 rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 1063 return(mStatus_AlreadyRegistered); 1064 } 1065 } 1066 else 1067 { 1068 while (*p && *p != rr) p=&(*p)->next; 1069 if (*p) 1070 { 1071 LogMsg("mDNS_Register_internal: ERROR!! Tried to register AuthRecord %p %##s (%s) that's already in the list", 1072 rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 1073 return(mStatus_AlreadyRegistered); 1074 } 1075 } 1076 1077 while (*d && *d != rr) d=&(*d)->next; 1078 if (*d) 1079 { 1080 LogMsg("mDNS_Register_internal: ERROR!! Tried to register AuthRecord %p %##s (%s) that's already in the Duplicate list", 1081 rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 1082 return(mStatus_AlreadyRegistered); 1083 } 1084 1085 if (rr->DependentOn) 1086 { 1087 if (rr->resrec.RecordType == kDNSRecordTypeUnique) 1088 rr->resrec.RecordType = kDNSRecordTypeVerified; 1089 else 1090 { 1091 LogMsg("mDNS_Register_internal: ERROR! %##s (%s): rr->DependentOn && RecordType != kDNSRecordTypeUnique", 1092 rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 1093 return(mStatus_Invalid); 1094 } 1095 if (!(rr->DependentOn->resrec.RecordType & (kDNSRecordTypeUnique | kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique))) 1096 { 1097 LogMsg("mDNS_Register_internal: ERROR! %##s (%s): rr->DependentOn->RecordType bad type %X", 1098 rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->DependentOn->resrec.RecordType); 1099 return(mStatus_Invalid); 1100 } 1101 } 1102 1103 // If this resource record is referencing a specific interface, make sure it exists. 1104 // Skip checks for LocalOnly and P2P as they are not valid InterfaceIDs. Also, for scoped 1105 // entries in /etc/hosts skip that check as that interface may not be valid at this time. 1106 if (rr->resrec.InterfaceID && rr->ARType != AuthRecordLocalOnly && rr->ARType != AuthRecordP2P) 1107 { 1108 NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID); 1109 if (!intf) 1110 { 1111 debugf("mDNS_Register_internal: Bogus InterfaceID %p in resource record", rr->resrec.InterfaceID); 1112 return(mStatus_BadReferenceErr); 1113 } 1114 } 1115 1116 rr->next = mDNSNULL; 1117 1118 // Field Group 1: The actual information pertaining to this resource record 1119 // Set up by client prior to call 1120 1121 // Field Group 2: Persistent metadata for Authoritative Records 1122 // rr->Additional1 = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client 1123 // rr->Additional2 = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client 1124 // rr->DependentOn = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client 1125 // rr->RRSet = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client 1126 // rr->Callback = already set in mDNS_SetupResourceRecord 1127 // rr->Context = already set in mDNS_SetupResourceRecord 1128 // rr->RecordType = already set in mDNS_SetupResourceRecord 1129 // rr->HostTarget = set to mDNSfalse in mDNS_SetupResourceRecord; may be overridden by client 1130 // rr->AllowRemoteQuery = set to mDNSfalse in mDNS_SetupResourceRecord; may be overridden by client 1131 // Make sure target is not uninitialized data, or we may crash writing debugging log messages 1132 if (rr->AutoTarget && target) target->c[0] = 0; 1133 1134 // Field Group 3: Transient state for Authoritative Records 1135 rr->Acknowledged = mDNSfalse; 1136 rr->ProbeCount = DefaultProbeCountForRecordType(rr->resrec.RecordType); 1137 rr->AnnounceCount = InitialAnnounceCount; 1138 rr->RequireGoodbye = mDNSfalse; 1139 rr->AnsweredLocalQ = mDNSfalse; 1140 rr->IncludeInProbe = mDNSfalse; 1141 rr->ImmedUnicast = mDNSfalse; 1142 rr->SendNSECNow = mDNSNULL; 1143 rr->ImmedAnswer = mDNSNULL; 1144 rr->ImmedAdditional = mDNSNULL; 1145 rr->SendRNow = mDNSNULL; 1146 rr->v4Requester = zerov4Addr; 1147 rr->v6Requester = zerov6Addr; 1148 rr->NextResponse = mDNSNULL; 1149 rr->NR_AnswerTo = mDNSNULL; 1150 rr->NR_AdditionalTo = mDNSNULL; 1151 if (!rr->AutoTarget) InitializeLastAPTime(m, rr); 1152 // rr->LastAPTime = Set for us in InitializeLastAPTime() 1153 // rr->LastMCTime = Set for us in InitializeLastAPTime() 1154 // rr->LastMCInterface = Set for us in InitializeLastAPTime() 1155 rr->NewRData = mDNSNULL; 1156 rr->newrdlength = 0; 1157 rr->UpdateCallback = mDNSNULL; 1158 rr->UpdateCredits = kMaxUpdateCredits; 1159 rr->NextUpdateCredit = 0; 1160 rr->UpdateBlocked = 0; 1161 1162 // For records we're holding as proxy (except reverse-mapping PTR records) two announcements is sufficient 1163 if (rr->WakeUp.HMAC.l[0] && !rr->AddressProxy.type) rr->AnnounceCount = 2; 1164 1165 // Field Group 4: Transient uDNS state for Authoritative Records 1166 rr->state = regState_Zero; 1167 rr->uselease = 0; 1168 rr->expire = 0; 1169 rr->Private = 0; 1170 rr->updateid = zeroID; 1171 rr->zone = rr->resrec.name; 1172 rr->nta = mDNSNULL; 1173 rr->tcp = mDNSNULL; 1174 rr->OrigRData = 0; 1175 rr->OrigRDLen = 0; 1176 rr->InFlightRData = 0; 1177 rr->InFlightRDLen = 0; 1178 rr->QueuedRData = 0; 1179 rr->QueuedRDLen = 0; 1180 //mDNSPlatformMemZero(&rr->NATinfo, sizeof(rr->NATinfo)); 1181 // We should be recording the actual internal port for this service record here. Once we initiate our NAT mapping 1182 // request we'll subsequently overwrite srv.port with the allocated external NAT port -- potentially multiple 1183 // times with different values if the external NAT port changes during the lifetime of the service registration. 1184 //if (rr->resrec.rrtype == kDNSType_SRV) rr->NATinfo.IntPort = rr->resrec.rdata->u.srv.port; 1185 1186 // rr->resrec.interface = already set in mDNS_SetupResourceRecord 1187 // rr->resrec.name->c = MUST be set by client 1188 // rr->resrec.rrtype = already set in mDNS_SetupResourceRecord 1189 // rr->resrec.rrclass = already set in mDNS_SetupResourceRecord 1190 // rr->resrec.rroriginalttl = already set in mDNS_SetupResourceRecord 1191 // rr->resrec.rdata = MUST be set by client, unless record type is CNAME or PTR and rr->HostTarget is set 1192 1193 // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct, 1194 // since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s". 1195 // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here. 1196 if (rr->resrec.rrtype == kDNSType_TXT && rr->resrec.rdlength == 0) { rr->resrec.rdlength = 1; rr->resrec.rdata->u.txt.c[0] = 0; } 1197 1198 if (rr->AutoTarget) 1199 { 1200 SetTargetToHostName(m, rr); // Also sets rdlength and rdestimate for us, and calls InitializeLastAPTime(); 1201 #ifndef UNICAST_DISABLED 1202 // If we have no target record yet, SetTargetToHostName will set rr->state == regState_NoTarget 1203 // In this case we leave the record half-formed in the list, and later we'll remove it from the list and re-add it properly. 1204 if (rr->state == regState_NoTarget) 1205 { 1206 // Initialize the target so that we don't crash while logging etc. 1207 domainname *tar = GetRRDomainNameTarget(&rr->resrec); 1208 if (tar) tar->c[0] = 0; 1209 LogInfo("mDNS_Register_internal: record %s in NoTarget state", ARDisplayString(m, rr)); 1210 } 1211 #endif 1212 } 1213 else 1214 { 1215 rr->resrec.rdlength = GetRDLength(&rr->resrec, mDNSfalse); 1216 rr->resrec.rdestimate = GetRDLength(&rr->resrec, mDNStrue); 1217 } 1218 1219 if (!ValidateDomainName(rr->resrec.name)) 1220 { LogMsg("Attempt to register record with invalid name: %s", ARDisplayString(m, rr)); return(mStatus_Invalid); } 1221 1222 // Don't do this until *after* we've set rr->resrec.rdlength 1223 if (!ValidateRData(rr->resrec.rrtype, rr->resrec.rdlength, rr->resrec.rdata)) 1224 { LogMsg("Attempt to register record with invalid rdata: %s", ARDisplayString(m, rr)); return(mStatus_Invalid); } 1225 1226 rr->resrec.namehash = DomainNameHashValue(rr->resrec.name); 1227 rr->resrec.rdatahash = target ? DomainNameHashValue(target) : RDataHashValue(&rr->resrec); 1228 1229 if (RRLocalOnly(rr)) 1230 { 1231 // If this is supposed to be unique, make sure we don't have any name conflicts. 1232 // If we found a conflict, we may still want to insert the record in the list but mark it appropriately 1233 // (kDNSRecordTypeDeregistering) so that we deliver RMV events to the application. But this causes more 1234 // complications and not clear whether there are any benefits. See rdar:9304275 for details. 1235 // Hence, just bail out. 1236 if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask) 1237 { 1238 if (CheckAuthRecordConflict(&m->rrauth, rr)) 1239 { 1240 LogInfo("mDNS_Register_internal: Name conflict %s (%p), InterfaceID %p", ARDisplayString(m, rr), rr, rr->resrec.InterfaceID); 1241 return mStatus_NameConflict; 1242 } 1243 } 1244 } 1245 1246 // For uDNS records, we don't support duplicate checks at this time. 1247 #ifndef UNICAST_DISABLED 1248 if (AuthRecord_uDNS(rr)) 1249 { 1250 if (!m->NewLocalRecords) m->NewLocalRecords = rr; 1251 // When we called SetTargetToHostName, it may have caused mDNS_Register_internal to be re-entered, appending new 1252 // records to the list, so we now need to update p to advance to the new end to the list before appending our new record. 1253 // Note that for AutoTunnel this should never happen, but this check makes the code future-proof. 1254 while (*p) p=&(*p)->next; 1255 *p = rr; 1256 if (rr->resrec.RecordType == kDNSRecordTypeUnique) rr->resrec.RecordType = kDNSRecordTypeVerified; 1257 rr->ProbeCount = 0; 1258 rr->AnnounceCount = 0; 1259 if (rr->state != regState_NoTarget) ActivateUnicastRegistration(m, rr); 1260 return(mStatus_NoError); // <--- Note: For unicast records, code currently bails out at this point 1261 } 1262 #endif 1263 1264 // Now that we've finished building our new record, make sure it's not identical to one we already have 1265 if (RRLocalOnly(rr)) 1266 { 1267 rr->ProbeCount = 0; 1268 rr->AnnounceCount = 0; 1269 r = CheckAuthIdenticalRecord(&m->rrauth, rr); 1270 } 1271 else 1272 { 1273 for (r = m->ResourceRecords; r; r=r->next) 1274 if (RecordIsLocalDuplicate(r, rr)) 1275 { 1276 if (r->resrec.RecordType == kDNSRecordTypeDeregistering) r->AnnounceCount = 0; 1277 else break; 1278 } 1279 } 1280 1281 if (r) 1282 { 1283 debugf("mDNS_Register_internal:Adding to duplicate list %s", ARDisplayString(m,rr)); 1284 *d = rr; 1285 // If the previous copy of this record is already verified unique, 1286 // then indicate that we should move this record promptly to kDNSRecordTypeUnique state. 1287 // Setting ProbeCount to zero will cause SendQueries() to advance this record to 1288 // kDNSRecordTypeVerified state and call the client callback at the next appropriate time. 1289 if (rr->resrec.RecordType == kDNSRecordTypeUnique && r->resrec.RecordType == kDNSRecordTypeVerified) 1290 rr->ProbeCount = 0; 1291 } 1292 else 1293 { 1294 debugf("mDNS_Register_internal: Adding to active record list %s", ARDisplayString(m,rr)); 1295 if (RRLocalOnly(rr)) 1296 { 1297 AuthGroup *ag; 1298 ag = InsertAuthRecord(m, &m->rrauth, rr); 1299 if (ag && !ag->NewLocalOnlyRecords) { 1300 m->NewLocalOnlyRecords = mDNStrue; 1301 ag->NewLocalOnlyRecords = rr; 1302 } 1303 // No probing for LocalOnly records, Acknowledge them right away 1304 if (rr->resrec.RecordType == kDNSRecordTypeUnique) rr->resrec.RecordType = kDNSRecordTypeVerified; 1305 AcknowledgeRecord(m, rr); 1306 return(mStatus_NoError); 1307 } 1308 else 1309 { 1310 if (!m->NewLocalRecords) m->NewLocalRecords = rr; 1311 *p = rr; 1312 } 1313 } 1314 1315 if (!AuthRecord_uDNS(rr)) // This check is superfluous, given that for unicast records we (currently) bail out above 1316 { 1317 // For records that are not going to probe, acknowledge them right away 1318 if (rr->resrec.RecordType != kDNSRecordTypeUnique && rr->resrec.RecordType != kDNSRecordTypeDeregistering) 1319 AcknowledgeRecord(m, rr); 1320 1321 // Adding a record may affect whether or not we should sleep 1322 mDNS_UpdateAllowSleep(m); 1323 } 1324 1325 return(mStatus_NoError); 1326 } 1327 1328 mDNSlocal void RecordProbeFailure(mDNS *const m, const AuthRecord *const rr) 1329 { 1330 m->ProbeFailTime = m->timenow; 1331 m->NumFailedProbes++; 1332 // If we've had fifteen or more probe failures, rate-limit to one every five seconds. 1333 // If a bunch of hosts have all been configured with the same name, then they'll all 1334 // conflict and run through the same series of names: name-2, name-3, name-4, etc., 1335 // up to name-10. After that they'll start adding random increments in the range 1-100, 1336 // so they're more likely to branch out in the available namespace and settle on a set of 1337 // unique names quickly. If after five more tries the host is still conflicting, then we 1338 // may have a serious problem, so we start rate-limiting so we don't melt down the network. 1339 if (m->NumFailedProbes >= 15) 1340 { 1341 m->SuppressProbes = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 5); 1342 LogMsg("Excessive name conflicts (%lu) for %##s (%s); rate limiting in effect", 1343 m->NumFailedProbes, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 1344 } 1345 } 1346 1347 mDNSlocal void CompleteRDataUpdate(mDNS *const m, AuthRecord *const rr) 1348 { 1349 RData *OldRData = rr->resrec.rdata; 1350 mDNSu16 OldRDLen = rr->resrec.rdlength; 1351 SetNewRData(&rr->resrec, rr->NewRData, rr->newrdlength); // Update our rdata 1352 rr->NewRData = mDNSNULL; // Clear the NewRData pointer ... 1353 if (rr->UpdateCallback) 1354 rr->UpdateCallback(m, rr, OldRData, OldRDLen); // ... and let the client know 1355 } 1356 1357 // Note: mDNS_Deregister_internal can call a user callback, which may change the record list and/or question list. 1358 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this. 1359 // Exported so uDNS.c can call this 1360 mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr, mDNS_Dereg_type drt) 1361 { 1362 AuthRecord *r2; 1363 mDNSu8 RecordType = rr->resrec.RecordType; 1364 AuthRecord **p = &m->ResourceRecords; // Find this record in our list of active records 1365 mDNSBool dupList = mDNSfalse; 1366 1367 if (RRLocalOnly(rr)) 1368 { 1369 AuthGroup *a; 1370 AuthGroup **ag = &a; 1371 AuthRecord **rp; 1372 const mDNSu32 slot = AuthHashSlot(rr->resrec.name); 1373 1374 a = AuthGroupForRecord(&m->rrauth, slot, &rr->resrec); 1375 if (!a) return mDNSfalse; 1376 rp = &(*ag)->members; 1377 while (*rp && *rp != rr) rp=&(*rp)->next; 1378 p = rp; 1379 } 1380 else 1381 { 1382 while (*p && *p != rr) p=&(*p)->next; 1383 } 1384 1385 if (*p) 1386 { 1387 // We found our record on the main list. See if there are any duplicates that need special handling. 1388 if (drt == mDNS_Dereg_conflict) // If this was a conflict, see that all duplicates get the same treatment 1389 { 1390 // Scan for duplicates of rr, and mark them for deregistration at the end of this routine, after we've finished 1391 // deregistering rr. We need to do this scan *before* we give the client the chance to free and reuse the rr memory. 1392 for (r2 = m->DuplicateRecords; r2; r2=r2->next) if (RecordIsLocalDuplicate(r2, rr)) r2->ProbeCount = 0xFF; 1393 } 1394 else 1395 { 1396 // Before we delete the record (and potentially send a goodbye packet) 1397 // first see if we have a record on the duplicate list ready to take over from it. 1398 AuthRecord **d = &m->DuplicateRecords; 1399 while (*d && !RecordIsLocalDuplicate(*d, rr)) d=&(*d)->next; 1400 if (*d) 1401 { 1402 AuthRecord *dup = *d; 1403 debugf("mDNS_Register_internal: Duplicate record %p taking over from %p %##s (%s)", 1404 dup, rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 1405 *d = dup->next; // Cut replacement record from DuplicateRecords list 1406 if (RRLocalOnly(rr)) 1407 { 1408 dup->next = mDNSNULL; 1409 if (!InsertAuthRecord(m, &m->rrauth, dup)) LogMsg("mDNS_Deregister_internal: ERROR!! cannot insert %s", ARDisplayString(m, dup)); 1410 } 1411 else 1412 { 1413 dup->next = rr->next; // And then... 1414 rr->next = dup; // ... splice it in right after the record we're about to delete 1415 } 1416 dup->resrec.RecordType = rr->resrec.RecordType; 1417 dup->ProbeCount = rr->ProbeCount; 1418 dup->AnnounceCount = rr->AnnounceCount; 1419 dup->RequireGoodbye = rr->RequireGoodbye; 1420 dup->AnsweredLocalQ = rr->AnsweredLocalQ; 1421 dup->ImmedAnswer = rr->ImmedAnswer; 1422 dup->ImmedUnicast = rr->ImmedUnicast; 1423 dup->ImmedAdditional = rr->ImmedAdditional; 1424 dup->v4Requester = rr->v4Requester; 1425 dup->v6Requester = rr->v6Requester; 1426 dup->ThisAPInterval = rr->ThisAPInterval; 1427 dup->LastAPTime = rr->LastAPTime; 1428 dup->LastMCTime = rr->LastMCTime; 1429 dup->LastMCInterface = rr->LastMCInterface; 1430 dup->Private = rr->Private; 1431 dup->state = rr->state; 1432 rr->RequireGoodbye = mDNSfalse; 1433 rr->AnsweredLocalQ = mDNSfalse; 1434 } 1435 } 1436 } 1437 else 1438 { 1439 // We didn't find our record on the main list; try the DuplicateRecords list instead. 1440 p = &m->DuplicateRecords; 1441 while (*p && *p != rr) p=&(*p)->next; 1442 // If we found our record on the duplicate list, then make sure we don't send a goodbye for it 1443 if (*p) { rr->RequireGoodbye = mDNSfalse; dupList = mDNStrue; } 1444 if (*p) debugf("mDNS_Deregister_internal: Deleting DuplicateRecord %p %##s (%s)", 1445 rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 1446 } 1447 1448 if (!*p) 1449 { 1450 // No need to log an error message if we already know this is a potentially repeated deregistration 1451 if (drt != mDNS_Dereg_repeat) 1452 LogMsg("mDNS_Deregister_internal: Record %p not found in list %s", rr, ARDisplayString(m,rr)); 1453 return(mStatus_BadReferenceErr); 1454 } 1455 1456 // If this is a shared record and we've announced it at least once, 1457 // we need to retract that announcement before we delete the record 1458 1459 // If this is a record (including mDNSInterface_LocalOnly records) for which we've given local-only answers then 1460 // it's tempting to just do "AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNSfalse)" here, but that would not not be safe. 1461 // The AnswerAllLocalQuestionsWithLocalAuthRecord routine walks the question list invoking client callbacks, using the "m->CurrentQuestion" 1462 // mechanism to cope with the client callback modifying the question list while that's happening. 1463 // However, mDNS_Deregister could have been called from a client callback (e.g. from the domain enumeration callback FoundDomain) 1464 // which means that the "m->CurrentQuestion" mechanism is already in use to protect that list, so we can't use it twice. 1465 // More generally, if we invoke callbacks from within a client callback, then those callbacks could deregister other 1466 // records, thereby invoking yet more callbacks, without limit. 1467 // The solution is to defer delivering the "Remove" events until mDNS_Execute time, just like we do for sending 1468 // actual goodbye packets. 1469 1470 #ifndef UNICAST_DISABLED 1471 if (AuthRecord_uDNS(rr)) 1472 { 1473 if (rr->RequireGoodbye) 1474 { 1475 if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; } 1476 rr->resrec.RecordType = kDNSRecordTypeDeregistering; 1477 m->LocalRemoveEvents = mDNStrue; 1478 uDNS_DeregisterRecord(m, rr); 1479 // At this point unconditionally we bail out 1480 // Either uDNS_DeregisterRecord will have completed synchronously, and called CompleteDeregistration, 1481 // which calls us back here with RequireGoodbye set to false, or it will have initiated the deregistration 1482 // process and will complete asynchronously. Either way we don't need to do anything more here. 1483 return(mStatus_NoError); 1484 } 1485 // Sometimes the records don't complete proper deregistration i.e., don't wait for a response 1486 // from the server. In that case, if the records have been part of a group update, clear the 1487 // state here. Some recors e.g., AutoTunnel gets reused without ever being completely initialized 1488 rr->updateid = zeroID; 1489 1490 // We defer cleaning up NAT state only after sending goodbyes. This is important because 1491 // RecordRegistrationGotZoneData guards against creating NAT state if clientContext is non-NULL. 1492 // This happens today when we turn on/off interface where we get multiple network transitions 1493 // and RestartRecordGetZoneData triggers re-registration of the resource records even though 1494 // they may be in Registered state which causes NAT information to be setup multiple times. Defering 1495 // the cleanup here keeps clientContext non-NULL and hence prevents that. Note that cleaning up 1496 // NAT state here takes care of the case where we did not send goodbyes at all. 1497 if (rr->NATinfo.clientContext) 1498 { 1499 mDNS_StopNATOperation_internal(m, &rr->NATinfo); 1500 rr->NATinfo.clientContext = mDNSNULL; 1501 } 1502 if (rr->nta) { CancelGetZoneData(m, rr->nta); rr->nta = mDNSNULL; } 1503 if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; } 1504 } 1505 #endif // UNICAST_DISABLED 1506 1507 if (RecordType == kDNSRecordTypeUnregistered) 1508 LogMsg("mDNS_Deregister_internal: %s already marked kDNSRecordTypeUnregistered", ARDisplayString(m, rr)); 1509 else if (RecordType == kDNSRecordTypeDeregistering) 1510 { 1511 LogMsg("mDNS_Deregister_internal: %s already marked kDNSRecordTypeDeregistering", ARDisplayString(m, rr)); 1512 return(mStatus_BadReferenceErr); 1513 } 1514 1515 // <rdar://problem/7457925> Local-only questions don't get remove events for unique records 1516 // We may want to consider changing this code so that we generate local-only question "rmv" 1517 // events (and maybe goodbye packets too) for unique records as well as for shared records 1518 // Note: If we change the logic for this "if" statement, need to ensure that the code in 1519 // CompleteDeregistration() sets the appropriate state variables to gaurantee that "else" 1520 // clause will execute here and the record will be cut from the list. 1521 if (rr->WakeUp.HMAC.l[0] || 1522 (RecordType == kDNSRecordTypeShared && (rr->RequireGoodbye || rr->AnsweredLocalQ))) 1523 { 1524 verbosedebugf("mDNS_Deregister_internal: Starting deregistration for %s", ARDisplayString(m, rr)); 1525 rr->resrec.RecordType = kDNSRecordTypeDeregistering; 1526 rr->resrec.rroriginalttl = 0; 1527 rr->AnnounceCount = rr->WakeUp.HMAC.l[0] ? WakeupCount : (drt == mDNS_Dereg_rapid) ? 1 : GoodbyeCount; 1528 rr->ThisAPInterval = mDNSPlatformOneSecond * 2; 1529 rr->LastAPTime = m->timenow - rr->ThisAPInterval; 1530 m->LocalRemoveEvents = mDNStrue; 1531 if (m->NextScheduledResponse - (m->timenow + mDNSPlatformOneSecond/10) >= 0) 1532 m->NextScheduledResponse = (m->timenow + mDNSPlatformOneSecond/10); 1533 } 1534 else 1535 { 1536 if (!dupList && RRLocalOnly(rr)) 1537 { 1538 AuthGroup *ag = RemoveAuthRecord(m, &m->rrauth, rr); 1539 if (ag->NewLocalOnlyRecords == rr) ag->NewLocalOnlyRecords = rr->next; 1540 } 1541 else 1542 { 1543 *p = rr->next; // Cut this record from the list 1544 if (m->NewLocalRecords == rr) m->NewLocalRecords = rr->next; 1545 } 1546 // If someone is about to look at this, bump the pointer forward 1547 if (m->CurrentRecord == rr) m->CurrentRecord = rr->next; 1548 rr->next = mDNSNULL; 1549 1550 // Should we generate local remove events here? 1551 // i.e. something like: 1552 // if (rr->AnsweredLocalQ) { AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNSfalse); rr->AnsweredLocalQ = mDNSfalse; } 1553 1554 verbosedebugf("mDNS_Deregister_internal: Deleting record for %s", ARDisplayString(m, rr)); 1555 rr->resrec.RecordType = kDNSRecordTypeUnregistered; 1556 1557 if ((drt == mDNS_Dereg_conflict || drt == mDNS_Dereg_repeat) && RecordType == kDNSRecordTypeShared) 1558 debugf("mDNS_Deregister_internal: Cannot have a conflict on a shared record! %##s (%s)", 1559 rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 1560 1561 // If we have an update queued up which never executed, give the client a chance to free that memory 1562 if (rr->NewRData) CompleteRDataUpdate(m, rr); // Update our rdata, clear the NewRData pointer, and return memory to the client 1563 1564 1565 // CAUTION: MUST NOT do anything more with rr after calling rr->Callback(), because the client's callback function 1566 // is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc. 1567 // In this case the likely client action to the mStatus_MemFree message is to free the memory, 1568 // so any attempt to touch rr after this is likely to lead to a crash. 1569 if (drt != mDNS_Dereg_conflict) 1570 { 1571 mDNS_DropLockBeforeCallback(); // Allow client to legally make mDNS API calls from the callback 1572 LogInfo("mDNS_Deregister_internal: mStatus_MemFree for %s", ARDisplayString(m, rr)); 1573 if (rr->RecordCallback) 1574 rr->RecordCallback(m, rr, mStatus_MemFree); // MUST NOT touch rr after this 1575 mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again 1576 } 1577 else 1578 { 1579 RecordProbeFailure(m, rr); 1580 mDNS_DropLockBeforeCallback(); // Allow client to legally make mDNS API calls from the callback 1581 if (rr->RecordCallback) 1582 rr->RecordCallback(m, rr, mStatus_NameConflict); // MUST NOT touch rr after this 1583 mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again 1584 // Now that we've finished deregistering rr, check our DuplicateRecords list for any that we marked previously. 1585 // Note that with all the client callbacks going on, by the time we get here all the 1586 // records we marked may have been explicitly deregistered by the client anyway. 1587 r2 = m->DuplicateRecords; 1588 while (r2) 1589 { 1590 if (r2->ProbeCount != 0xFF) r2 = r2->next; 1591 else { mDNS_Deregister_internal(m, r2, mDNS_Dereg_conflict); r2 = m->DuplicateRecords; } 1592 } 1593 } 1594 } 1595 mDNS_UpdateAllowSleep(m); 1596 return(mStatus_NoError); 1597 } 1598 1599 // *************************************************************************** 1600 #if COMPILER_LIKES_PRAGMA_MARK 1601 #pragma mark - 1602 #pragma mark - Packet Sending Functions 1603 #endif 1604 1605 mDNSlocal void AddRecordToResponseList(AuthRecord ***nrpp, AuthRecord *rr, AuthRecord *add) 1606 { 1607 if (rr->NextResponse == mDNSNULL && *nrpp != &rr->NextResponse) 1608 { 1609 **nrpp = rr; 1610 // NR_AdditionalTo must point to a record with NR_AnswerTo set (and not NR_AdditionalTo) 1611 // If 'add' does not meet this requirement, then follow its NR_AdditionalTo pointer to a record that does 1612 // The referenced record will definitely be acceptable (by recursive application of this rule) 1613 if (add && add->NR_AdditionalTo) add = add->NR_AdditionalTo; 1614 rr->NR_AdditionalTo = add; 1615 *nrpp = &rr->NextResponse; 1616 } 1617 debugf("AddRecordToResponseList: %##s (%s) already in list", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 1618 } 1619 1620 mDNSlocal void AddAdditionalsToResponseList(mDNS *const m, AuthRecord *ResponseRecords, AuthRecord ***nrpp, const mDNSInterfaceID InterfaceID) 1621 { 1622 AuthRecord *rr, *rr2; 1623 for (rr=ResponseRecords; rr; rr=rr->NextResponse) // For each record we plan to put 1624 { 1625 // (Note: This is an "if", not a "while". If we add a record, we'll find it again 1626 // later in the "for" loop, and we will follow further "additional" links then.) 1627 if (rr->Additional1 && ResourceRecordIsValidInterfaceAnswer(rr->Additional1, InterfaceID)) 1628 AddRecordToResponseList(nrpp, rr->Additional1, rr); 1629 1630 if (rr->Additional2 && ResourceRecordIsValidInterfaceAnswer(rr->Additional2, InterfaceID)) 1631 AddRecordToResponseList(nrpp, rr->Additional2, rr); 1632 1633 // For SRV records, automatically add the Address record(s) for the target host 1634 if (rr->resrec.rrtype == kDNSType_SRV) 1635 { 1636 for (rr2=m->ResourceRecords; rr2; rr2=rr2->next) // Scan list of resource records 1637 if (RRTypeIsAddressType(rr2->resrec.rrtype) && // For all address records (A/AAAA) ... 1638 ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) && // ... which are valid for answer ... 1639 rr->resrec.rdatahash == rr2->resrec.namehash && // ... whose name is the name of the SRV target 1640 SameDomainName(&rr->resrec.rdata->u.srv.target, rr2->resrec.name)) 1641 AddRecordToResponseList(nrpp, rr2, rr); 1642 } 1643 else if (RRTypeIsAddressType(rr->resrec.rrtype)) // For A or AAAA, put counterpart as additional 1644 { 1645 for (rr2=m->ResourceRecords; rr2; rr2=rr2->next) // Scan list of resource records 1646 if (RRTypeIsAddressType(rr2->resrec.rrtype) && // For all address records (A/AAAA) ... 1647 ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) && // ... which are valid for answer ... 1648 rr->resrec.namehash == rr2->resrec.namehash && // ... and have the same name 1649 SameDomainName(rr->resrec.name, rr2->resrec.name)) 1650 AddRecordToResponseList(nrpp, rr2, rr); 1651 } 1652 else if (rr->resrec.rrtype == kDNSType_PTR) // For service PTR, see if we want to add DeviceInfo record 1653 { 1654 if (ResourceRecordIsValidInterfaceAnswer(&m->DeviceInfo, InterfaceID) && 1655 SameDomainLabel(rr->resrec.rdata->u.name.c, m->DeviceInfo.resrec.name->c)) 1656 AddRecordToResponseList(nrpp, &m->DeviceInfo, rr); 1657 } 1658 } 1659 } 1660 1661 mDNSlocal void SendDelayedUnicastResponse(mDNS *const m, const mDNSAddr *const dest, const mDNSInterfaceID InterfaceID) 1662 { 1663 AuthRecord *rr; 1664 AuthRecord *ResponseRecords = mDNSNULL; 1665 AuthRecord **nrp = &ResponseRecords; 1666 NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID); 1667 1668 // Make a list of all our records that need to be unicast to this destination 1669 for (rr = m->ResourceRecords; rr; rr=rr->next) 1670 { 1671 // If we find we can no longer unicast this answer, clear ImmedUnicast 1672 if (rr->ImmedAnswer == mDNSInterfaceMark || 1673 mDNSSameIPv4Address(rr->v4Requester, onesIPv4Addr) || 1674 mDNSSameIPv6Address(rr->v6Requester, onesIPv6Addr) ) 1675 rr->ImmedUnicast = mDNSfalse; 1676 1677 if (rr->ImmedUnicast && rr->ImmedAnswer == InterfaceID) 1678 { 1679 if ((dest->type == mDNSAddrType_IPv4 && mDNSSameIPv4Address(rr->v4Requester, dest->ip.v4)) || 1680 (dest->type == mDNSAddrType_IPv6 && mDNSSameIPv6Address(rr->v6Requester, dest->ip.v6))) 1681 { 1682 rr->ImmedAnswer = mDNSNULL; // Clear the state fields 1683 rr->ImmedUnicast = mDNSfalse; 1684 rr->v4Requester = zerov4Addr; 1685 rr->v6Requester = zerov6Addr; 1686 1687 // Only sent records registered for P2P over P2P interfaces 1688 if (intf && !mDNSPlatformValidRecordForInterface(rr, intf)) 1689 { 1690 LogInfo("SendDelayedUnicastResponse: Not sending %s, on %s", ARDisplayString(m, rr), InterfaceNameForID(m, InterfaceID)); 1691 continue; 1692 } 1693 1694 if (rr->NextResponse == mDNSNULL && nrp != &rr->NextResponse) // rr->NR_AnswerTo 1695 { rr->NR_AnswerTo = (mDNSu8*)~0; *nrp = rr; nrp = &rr->NextResponse; } 1696 } 1697 } 1698 } 1699 1700 AddAdditionalsToResponseList(m, ResponseRecords, &nrp, InterfaceID); 1701 1702 while (ResponseRecords) 1703 { 1704 mDNSu8 *responseptr = m->omsg.data; 1705 mDNSu8 *newptr; 1706 InitializeDNSMessage(&m->omsg.h, zeroID, ResponseFlags); 1707 1708 // Put answers in the packet 1709 while (ResponseRecords && ResponseRecords->NR_AnswerTo) 1710 { 1711 rr = ResponseRecords; 1712 if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask) 1713 rr->resrec.rrclass |= kDNSClass_UniqueRRSet; // Temporarily set the cache flush bit so PutResourceRecord will set it 1714 newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAnswers, &rr->resrec); 1715 rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet; // Make sure to clear cache flush bit back to normal state 1716 if (!newptr && m->omsg.h.numAnswers) break; // If packet full, send it now 1717 if (newptr) responseptr = newptr; 1718 ResponseRecords = rr->NextResponse; 1719 rr->NextResponse = mDNSNULL; 1720 rr->NR_AnswerTo = mDNSNULL; 1721 rr->NR_AdditionalTo = mDNSNULL; 1722 rr->RequireGoodbye = mDNStrue; 1723 } 1724 1725 // Add additionals, if there's space 1726 while (ResponseRecords && !ResponseRecords->NR_AnswerTo) 1727 { 1728 rr = ResponseRecords; 1729 if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask) 1730 rr->resrec.rrclass |= kDNSClass_UniqueRRSet; // Temporarily set the cache flush bit so PutResourceRecord will set it 1731 newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAdditionals, &rr->resrec); 1732 rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet; // Make sure to clear cache flush bit back to normal state 1733 1734 if (newptr) responseptr = newptr; 1735 if (newptr && m->omsg.h.numAnswers) rr->RequireGoodbye = mDNStrue; 1736 else if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask) rr->ImmedAnswer = mDNSInterfaceMark; 1737 ResponseRecords = rr->NextResponse; 1738 rr->NextResponse = mDNSNULL; 1739 rr->NR_AnswerTo = mDNSNULL; 1740 rr->NR_AdditionalTo = mDNSNULL; 1741 } 1742 1743 if (m->omsg.h.numAnswers) 1744 mDNSSendDNSMessage(m, &m->omsg, responseptr, InterfaceID, mDNSNULL, dest, MulticastDNSPort, mDNSNULL, mDNSNULL); 1745 } 1746 } 1747 1748 // CompleteDeregistration guarantees that on exit the record will have been cut from the m->ResourceRecords list 1749 // and the client's mStatus_MemFree callback will have been invoked 1750 mDNSexport void CompleteDeregistration(mDNS *const m, AuthRecord *rr) 1751 { 1752 LogInfo("CompleteDeregistration: called for Resource record %s", ARDisplayString(m, rr)); 1753 // Clearing rr->RequireGoodbye signals mDNS_Deregister_internal() that 1754 // it should go ahead and immediately dispose of this registration 1755 rr->resrec.RecordType = kDNSRecordTypeShared; 1756 rr->RequireGoodbye = mDNSfalse; 1757 rr->WakeUp.HMAC = zeroEthAddr; 1758 if (rr->AnsweredLocalQ) { AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNSfalse); rr->AnsweredLocalQ = mDNSfalse; } 1759 mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal); // Don't touch rr after this 1760 } 1761 1762 // DiscardDeregistrations is used on shutdown and sleep to discard (forcibly and immediately) 1763 // any deregistering records that remain in the m->ResourceRecords list. 1764 // DiscardDeregistrations calls mDNS_Deregister_internal which can call a user callback, 1765 // which may change the record list and/or question list. 1766 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this. 1767 mDNSlocal void DiscardDeregistrations(mDNS *const m) 1768 { 1769 if (m->CurrentRecord) 1770 LogMsg("DiscardDeregistrations ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord)); 1771 m->CurrentRecord = m->ResourceRecords; 1772 1773 while (m->CurrentRecord) 1774 { 1775 AuthRecord *rr = m->CurrentRecord; 1776 if (!AuthRecord_uDNS(rr) && rr->resrec.RecordType == kDNSRecordTypeDeregistering) 1777 CompleteDeregistration(m, rr); // Don't touch rr after this 1778 else 1779 m->CurrentRecord = rr->next; 1780 } 1781 } 1782 1783 mDNSlocal mStatus GetLabelDecimalValue(const mDNSu8 *const src, mDNSu8 *dst) 1784 { 1785 int i, val = 0; 1786 if (src[0] < 1 || src[0] > 3) return(mStatus_Invalid); 1787 for (i=1; i<=src[0]; i++) 1788 { 1789 if (src[i] < '0' || src[i] > '9') return(mStatus_Invalid); 1790 val = val * 10 + src[i] - '0'; 1791 } 1792 if (val > 255) return(mStatus_Invalid); 1793 *dst = (mDNSu8)val; 1794 return(mStatus_NoError); 1795 } 1796 1797 mDNSlocal mStatus GetIPv4FromName(mDNSAddr *const a, const domainname *const name) 1798 { 1799 int skip = CountLabels(name) - 6; 1800 if (skip < 0) { LogMsg("GetIPFromName: Need six labels in IPv4 reverse mapping name %##s", name); return mStatus_Invalid; } 1801 if (GetLabelDecimalValue(SkipLeadingLabels(name, skip+3)->c, &a->ip.v4.b[0]) || 1802 GetLabelDecimalValue(SkipLeadingLabels(name, skip+2)->c, &a->ip.v4.b[1]) || 1803 GetLabelDecimalValue(SkipLeadingLabels(name, skip+1)->c, &a->ip.v4.b[2]) || 1804 GetLabelDecimalValue(SkipLeadingLabels(name, skip+0)->c, &a->ip.v4.b[3])) return mStatus_Invalid; 1805 a->type = mDNSAddrType_IPv4; 1806 return(mStatus_NoError); 1807 } 1808 1809 #define HexVal(X) ( ((X) >= '0' && (X) <= '9') ? ((X) - '0' ) : \ 1810 ((X) >= 'A' && (X) <= 'F') ? ((X) - 'A' + 10) : \ 1811 ((X) >= 'a' && (X) <= 'f') ? ((X) - 'a' + 10) : -1) 1812 1813 mDNSlocal mStatus GetIPv6FromName(mDNSAddr *const a, const domainname *const name) 1814 { 1815 int i, h, l; 1816 const domainname *n; 1817 1818 int skip = CountLabels(name) - 34; 1819 if (skip < 0) { LogMsg("GetIPFromName: Need 34 labels in IPv6 reverse mapping name %##s", name); return mStatus_Invalid; } 1820 1821 n = SkipLeadingLabels(name, skip); 1822 for (i=0; i<16; i++) 1823 { 1824 if (n->c[0] != 1) return mStatus_Invalid; 1825 l = HexVal(n->c[1]); 1826 n = (const domainname *)(n->c + 2); 1827 1828 if (n->c[0] != 1) return mStatus_Invalid; 1829 h = HexVal(n->c[1]); 1830 n = (const domainname *)(n->c + 2); 1831 1832 if (l<0 || h<0) return mStatus_Invalid; 1833 a->ip.v6.b[15-i] = (mDNSu8)((h << 4) | l); 1834 } 1835 1836 a->type = mDNSAddrType_IPv6; 1837 return(mStatus_NoError); 1838 } 1839 1840 mDNSlocal mDNSs32 ReverseMapDomainType(const domainname *const name) 1841 { 1842 int skip = CountLabels(name) - 2; 1843 if (skip >= 0) 1844 { 1845 const domainname *suffix = SkipLeadingLabels(name, skip); 1846 if (SameDomainName(suffix, (const domainname*)"\x7" "in-addr" "\x4" "arpa")) return mDNSAddrType_IPv4; 1847 if (SameDomainName(suffix, (const domainname*)"\x3" "ip6" "\x4" "arpa")) return mDNSAddrType_IPv6; 1848 } 1849 return(mDNSAddrType_None); 1850 } 1851 1852 mDNSlocal void SendARP(mDNS *const m, const mDNSu8 op, const AuthRecord *const rr, 1853 const mDNSv4Addr *const spa, const mDNSEthAddr *const tha, const mDNSv4Addr *const tpa, const mDNSEthAddr *const dst) 1854 { 1855 int i; 1856 mDNSu8 *ptr = m->omsg.data; 1857 NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID); 1858 if (!intf) { LogMsg("SendARP: No interface with InterfaceID %p found %s", rr->resrec.InterfaceID, ARDisplayString(m,rr)); return; } 1859 1860 // 0x00 Destination address 1861 for (i=0; i<6; i++) *ptr++ = dst->b[i]; 1862 1863 // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option, BPF will fill in the real interface address for us) 1864 for (i=0; i<6; i++) *ptr++ = intf->MAC.b[0]; 1865 1866 // 0x0C ARP Ethertype (0x0806) 1867 *ptr++ = 0x08; *ptr++ = 0x06; 1868 1869 // 0x0E ARP header 1870 *ptr++ = 0x00; *ptr++ = 0x01; // Hardware address space; Ethernet = 1 1871 *ptr++ = 0x08; *ptr++ = 0x00; // Protocol address space; IP = 0x0800 1872 *ptr++ = 6; // Hardware address length 1873 *ptr++ = 4; // Protocol address length 1874 *ptr++ = 0x00; *ptr++ = op; // opcode; Request = 1, Response = 2 1875 1876 // 0x16 Sender hardware address (our MAC address) 1877 for (i=0; i<6; i++) *ptr++ = intf->MAC.b[i]; 1878 1879 // 0x1C Sender protocol address 1880 for (i=0; i<4; i++) *ptr++ = spa->b[i]; 1881 1882 // 0x20 Target hardware address 1883 for (i=0; i<6; i++) *ptr++ = tha->b[i]; 1884 1885 // 0x26 Target protocol address 1886 for (i=0; i<4; i++) *ptr++ = tpa->b[i]; 1887 1888 // 0x2A Total ARP Packet length 42 bytes 1889 mDNSPlatformSendRawPacket(m->omsg.data, ptr, rr->resrec.InterfaceID); 1890 } 1891 1892 mDNSlocal mDNSu16 CheckSum(const void *const data, mDNSs32 length, mDNSu32 sum) 1893 { 1894 const mDNSu16 *ptr = data; 1895 while (length > 0) { length -= 2; sum += *ptr++; } 1896 sum = (sum & 0xFFFF) + (sum >> 16); 1897 sum = (sum & 0xFFFF) + (sum >> 16); 1898 return(sum != 0xFFFF ? sum : 0); 1899 } 1900 1901 mDNSlocal mDNSu16 IPv6CheckSum(const mDNSv6Addr *const src, const mDNSv6Addr *const dst, const mDNSu8 protocol, const void *const data, const mDNSu32 length) 1902 { 1903 IPv6PseudoHeader ph; 1904 ph.src = *src; 1905 ph.dst = *dst; 1906 ph.len.b[0] = length >> 24; 1907 ph.len.b[1] = length >> 16; 1908 ph.len.b[2] = length >> 8; 1909 ph.len.b[3] = length; 1910 ph.pro.b[0] = 0; 1911 ph.pro.b[1] = 0; 1912 ph.pro.b[2] = 0; 1913 ph.pro.b[3] = protocol; 1914 return CheckSum(&ph, sizeof(ph), CheckSum(data, length, 0)); 1915 } 1916 1917 mDNSlocal void SendNDP(mDNS *const m, const mDNSu8 op, const mDNSu8 flags, const AuthRecord *const rr, 1918 const mDNSv6Addr *const spa, const mDNSEthAddr *const tha, const mDNSv6Addr *const tpa, const mDNSEthAddr *const dst) 1919 { 1920 int i; 1921 mDNSOpaque16 checksum; 1922 mDNSu8 *ptr = m->omsg.data; 1923 // Some recipient hosts seem to ignore Neighbor Solicitations if the IPv6-layer destination address is not the 1924 // appropriate IPv6 solicited node multicast address, so we use that IPv6-layer destination address, even though 1925 // at the Ethernet-layer we unicast the packet to the intended target, to avoid wasting network bandwidth. 1926 const mDNSv6Addr mc = { { 0xFF,0x02,0x00,0x00, 0,0,0,0, 0,0,0,1, 0xFF,tpa->b[0xD],tpa->b[0xE],tpa->b[0xF] } }; 1927 const mDNSv6Addr *const v6dst = (op == NDP_Sol) ? &mc : tpa; 1928 NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID); 1929 if (!intf) { LogMsg("SendNDP: No interface with InterfaceID %p found %s", rr->resrec.InterfaceID, ARDisplayString(m,rr)); return; } 1930 1931 // 0x00 Destination address 1932 for (i=0; i<6; i++) *ptr++ = dst->b[i]; 1933 // Right now we only send Neighbor Solicitations to verify whether the host we're proxying for has gone to sleep yet. 1934 // Since we know who we're looking for, we send it via Ethernet-layer unicast, rather than bothering every host on the 1935 // link with a pointless link-layer multicast. 1936 // Should we want to send traditional Neighbor Solicitations in the future, where we really don't know in advance what 1937 // Ethernet-layer address we're looking for, we'll need to send to the appropriate Ethernet-layer multicast address: 1938 // *ptr++ = 0x33; 1939 // *ptr++ = 0x33; 1940 // *ptr++ = 0xFF; 1941 // *ptr++ = tpa->b[0xD]; 1942 // *ptr++ = tpa->b[0xE]; 1943 // *ptr++ = tpa->b[0xF]; 1944 1945 // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option, BPF will fill in the real interface address for us) 1946 for (i=0; i<6; i++) *ptr++ = (tha ? *tha : intf->MAC).b[i]; 1947 1948 // 0x0C IPv6 Ethertype (0x86DD) 1949 *ptr++ = 0x86; *ptr++ = 0xDD; 1950 1951 // 0x0E IPv6 header 1952 *ptr++ = 0x60; *ptr++ = 0x00; *ptr++ = 0x00; *ptr++ = 0x00; // Version, Traffic Class, Flow Label 1953 *ptr++ = 0x00; *ptr++ = 0x20; // Length 1954 *ptr++ = 0x3A; // Protocol == ICMPv6 1955 *ptr++ = 0xFF; // Hop Limit 1956 1957 // 0x16 Sender IPv6 address 1958 for (i=0; i<16; i++) *ptr++ = spa->b[i]; 1959 1960 // 0x26 Destination IPv6 address 1961 for (i=0; i<16; i++) *ptr++ = v6dst->b[i]; 1962 1963 // 0x36 NDP header 1964 *ptr++ = op; // 0x87 == Neighbor Solicitation, 0x88 == Neighbor Advertisement 1965 *ptr++ = 0x00; // Code 1966 *ptr++ = 0x00; *ptr++ = 0x00; // Checksum placeholder (0x38, 0x39) 1967 *ptr++ = flags; 1968 *ptr++ = 0x00; *ptr++ = 0x00; *ptr++ = 0x00; 1969 1970 if (op == NDP_Sol) // Neighbor Solicitation. The NDP "target" is the address we seek. 1971 { 1972 // 0x3E NDP target. 1973 for (i=0; i<16; i++) *ptr++ = tpa->b[i]; 1974 // 0x4E Source Link-layer Address 1975 // <http://www.ietf.org/rfc/rfc2461.txt> 1976 // MUST NOT be included when the source IP address is the unspecified address. 1977 // Otherwise, on link layers that have addresses this option MUST be included 1978 // in multicast solicitations and SHOULD be included in unicast solicitations. 1979 if (!mDNSIPv6AddressIsZero(*spa)) 1980 { 1981 *ptr++ = NDP_SrcLL; // Option Type 1 == Source Link-layer Address 1982 *ptr++ = 0x01; // Option length 1 (in units of 8 octets) 1983 for (i=0; i<6; i++) *ptr++ = (tha ? *tha : intf->MAC).b[i]; 1984 } 1985 } 1986 else // Neighbor Advertisement. The NDP "target" is the address we're giving information about. 1987 { 1988 // 0x3E NDP target. 1989 for (i=0; i<16; i++) *ptr++ = spa->b[i]; 1990 // 0x4E Target Link-layer Address 1991 *ptr++ = NDP_TgtLL; // Option Type 2 == Target Link-layer Address 1992 *ptr++ = 0x01; // Option length 1 (in units of 8 octets) 1993 for (i=0; i<6; i++) *ptr++ = (tha ? *tha : intf->MAC).b[i]; 1994 } 1995 1996 // 0x4E or 0x56 Total NDP Packet length 78 or 86 bytes 1997 m->omsg.data[0x13] = ptr - &m->omsg.data[0x36]; // Compute actual length 1998 checksum.NotAnInteger = ~IPv6CheckSum(spa, v6dst, 0x3A, &m->omsg.data[0x36], m->omsg.data[0x13]); 1999 m->omsg.data[0x38] = checksum.b[0]; 2000 m->omsg.data[0x39] = checksum.b[1]; 2001 2002 mDNSPlatformSendRawPacket(m->omsg.data, ptr, rr->resrec.InterfaceID); 2003 } 2004 2005 mDNSlocal void SetupOwnerOpt(const mDNS *const m, const NetworkInterfaceInfo *const intf, rdataOPT *const owner) 2006 { 2007 owner->u.owner.vers = 0; 2008 owner->u.owner.seq = m->SleepSeqNum; 2009 owner->u.owner.HMAC = m->PrimaryMAC; 2010 owner->u.owner.IMAC = intf->MAC; 2011 owner->u.owner.password = zeroEthAddr; 2012 2013 // Don't try to compute the optlen until *after* we've set up the data fields 2014 // Right now the DNSOpt_Owner_Space macro does not depend on the owner->u.owner being set up correctly, but in the future it might 2015 owner->opt = kDNSOpt_Owner; 2016 owner->optlen = DNSOpt_Owner_Space(&m->PrimaryMAC, &intf->MAC) - 4; 2017 } 2018 2019 mDNSlocal void GrantUpdateCredit(AuthRecord *rr) 2020 { 2021 if (++rr->UpdateCredits >= kMaxUpdateCredits) rr->NextUpdateCredit = 0; 2022 else rr->NextUpdateCredit = NonZeroTime(rr->NextUpdateCredit + kUpdateCreditRefreshInterval); 2023 } 2024 2025 // Note about acceleration of announcements to facilitate automatic coalescing of 2026 // multiple independent threads of announcements into a single synchronized thread: 2027 // The announcements in the packet may be at different stages of maturity; 2028 // One-second interval, two-second interval, four-second interval, and so on. 2029 // After we've put in all the announcements that are due, we then consider 2030 // whether there are other nearly-due announcements that are worth accelerating. 2031 // To be eligible for acceleration, a record MUST NOT be older (further along 2032 // its timeline) than the most mature record we've already put in the packet. 2033 // In other words, younger records can have their timelines accelerated to catch up 2034 // with their elder bretheren; this narrows the age gap and helps them eventually get in sync. 2035 // Older records cannot have their timelines accelerated; this would just widen 2036 // the gap between them and their younger bretheren and get them even more out of sync. 2037 2038 // Note: SendResponses calls mDNS_Deregister_internal which can call a user callback, which may change 2039 // the record list and/or question list. 2040 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this. 2041 mDNSlocal void SendResponses(mDNS *const m) 2042 { 2043 int pktcount = 0; 2044 AuthRecord *rr, *r2; 2045 mDNSs32 maxExistingAnnounceInterval = 0; 2046 const NetworkInterfaceInfo *intf = GetFirstActiveInterface(m->HostInterfaces); 2047 2048 m->NextScheduledResponse = m->timenow + 0x78000000; 2049 2050 if (m->SleepState == SleepState_Transferring) RetrySPSRegistrations(m); 2051 2052 for (rr = m->ResourceRecords; rr; rr=rr->next) 2053 if (rr->ImmedUnicast) 2054 { 2055 mDNSAddr v4 = { mDNSAddrType_IPv4, {{{0}}} }; 2056 mDNSAddr v6 = { mDNSAddrType_IPv6, {{{0}}} }; 2057 v4.ip.v4 = rr->v4Requester; 2058 v6.ip.v6 = rr->v6Requester; 2059 if (!mDNSIPv4AddressIsZero(rr->v4Requester)) SendDelayedUnicastResponse(m, &v4, rr->ImmedAnswer); 2060 if (!mDNSIPv6AddressIsZero(rr->v6Requester)) SendDelayedUnicastResponse(m, &v6, rr->ImmedAnswer); 2061 if (rr->ImmedUnicast) 2062 { 2063 LogMsg("SendResponses: ERROR: rr->ImmedUnicast still set: %s", ARDisplayString(m, rr)); 2064 rr->ImmedUnicast = mDNSfalse; 2065 } 2066 } 2067 2068 // *** 2069 // *** 1. Setup: Set the SendRNow and ImmedAnswer fields to indicate which interface(s) the records need to be sent on 2070 // *** 2071 2072 // Run through our list of records, and decide which ones we're going to announce on all interfaces 2073 for (rr = m->ResourceRecords; rr; rr=rr->next) 2074 { 2075 while (rr->NextUpdateCredit && m->timenow - rr->NextUpdateCredit >= 0) GrantUpdateCredit(rr); 2076 if (TimeToAnnounceThisRecord(rr, m->timenow)) 2077 { 2078 if (rr->resrec.RecordType == kDNSRecordTypeDeregistering) 2079 { 2080 if (!rr->WakeUp.HMAC.l[0]) 2081 { 2082 if (rr->AnnounceCount) rr->ImmedAnswer = mDNSInterfaceMark; // Send goodbye packet on all interfaces 2083 } 2084 else 2085 { 2086 LogSPS("SendResponses: Sending wakeup %2d for %.6a %s", rr->AnnounceCount-3, &rr->WakeUp.IMAC, ARDisplayString(m, rr)); 2087 SendWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.IMAC, &rr->WakeUp.password); 2088 for (r2 = rr; r2; r2=r2->next) 2089 if (r2->AnnounceCount && r2->resrec.InterfaceID == rr->resrec.InterfaceID && mDNSSameEthAddress(&r2->WakeUp.IMAC, &rr->WakeUp.IMAC)) 2090 { 2091 // For now we only want to send a single Unsolicited Neighbor Advertisement restoring the address to the original 2092 // owner, because these packets can cause some IPv6 stacks to falsely conclude that there's an address conflict. 2093 if (r2->AddressProxy.type == mDNSAddrType_IPv6 && r2->AnnounceCount == WakeupCount) 2094 { 2095 LogSPS("NDP Announcement %2d Releasing traffic for H-MAC %.6a I-MAC %.6a %s", 2096 r2->AnnounceCount-3, &r2->WakeUp.HMAC, &r2->WakeUp.IMAC, ARDisplayString(m,r2)); 2097 SendNDP(m, NDP_Adv, NDP_Override, r2, &r2->AddressProxy.ip.v6, &r2->WakeUp.IMAC, &AllHosts_v6, &AllHosts_v6_Eth); 2098 } 2099 r2->LastAPTime = m->timenow; 2100 // After 15 wakeups without success (maybe host has left the network) send three goodbyes instead 2101 if (--r2->AnnounceCount <= GoodbyeCount) r2->WakeUp.HMAC = zeroEthAddr; 2102 } 2103 } 2104 } 2105 else if (ResourceRecordIsValidAnswer(rr)) 2106 { 2107 if (rr->AddressProxy.type) 2108 { 2109 rr->AnnounceCount--; 2110 rr->ThisAPInterval *= 2; 2111 rr->LastAPTime = m->timenow; 2112 if (rr->AddressProxy.type == mDNSAddrType_IPv4) 2113 { 2114 LogSPS("ARP Announcement %2d Capturing traffic for H-MAC %.6a I-MAC %.6a %s", 2115 rr->AnnounceCount, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m,rr)); 2116 SendARP(m, 1, rr, &rr->AddressProxy.ip.v4, &zeroEthAddr, &rr->AddressProxy.ip.v4, &onesEthAddr); 2117 } 2118 else if (rr->AddressProxy.type == mDNSAddrType_IPv6) 2119 { 2120 LogSPS("NDP Announcement %2d Capturing traffic for H-MAC %.6a I-MAC %.6a %s", 2121 rr->AnnounceCount, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m,rr)); 2122 SendNDP(m, NDP_Adv, NDP_Override, rr, &rr->AddressProxy.ip.v6, mDNSNULL, &AllHosts_v6, &AllHosts_v6_Eth); 2123 } 2124 } 2125 else 2126 { 2127 rr->ImmedAnswer = mDNSInterfaceMark; // Send on all interfaces 2128 if (maxExistingAnnounceInterval < rr->ThisAPInterval) 2129 maxExistingAnnounceInterval = rr->ThisAPInterval; 2130 if (rr->UpdateBlocked) rr->UpdateBlocked = 0; 2131 } 2132 } 2133 } 2134 } 2135 2136 // Any interface-specific records we're going to send are marked as being sent on all appropriate interfaces (which is just one) 2137 // Eligible records that are more than half-way to their announcement time are accelerated 2138 for (rr = m->ResourceRecords; rr; rr=rr->next) 2139 if ((rr->resrec.InterfaceID && rr->ImmedAnswer) || 2140 (rr->ThisAPInterval <= maxExistingAnnounceInterval && 2141 TimeToAnnounceThisRecord(rr, m->timenow + rr->ThisAPInterval/2) && 2142 !rr->AddressProxy.type && // Don't include ARP Annoucements when considering which records to accelerate 2143 ResourceRecordIsValidAnswer(rr))) 2144 rr->ImmedAnswer = mDNSInterfaceMark; // Send on all interfaces 2145 2146 // When sending SRV records (particularly when announcing a new service) automatically add related Address record(s) as additionals 2147 // Note: Currently all address records are interface-specific, so it's safe to set ImmedAdditional to their InterfaceID, 2148 // which will be non-null. If by some chance there is an address record that's not interface-specific (should never happen) 2149 // then all that means is that it won't get sent -- which would not be the end of the world. 2150 for (rr = m->ResourceRecords; rr; rr=rr->next) 2151 { 2152 if (rr->ImmedAnswer && rr->resrec.rrtype == kDNSType_SRV) 2153 for (r2=m->ResourceRecords; r2; r2=r2->next) // Scan list of resource records 2154 if (RRTypeIsAddressType(r2->resrec.rrtype) && // For all address records (A/AAAA) ... 2155 ResourceRecordIsValidAnswer(r2) && // ... which are valid for answer ... 2156 rr->LastMCTime - r2->LastMCTime >= 0 && // ... which we have not sent recently ... 2157 rr->resrec.rdatahash == r2->resrec.namehash && // ... whose name is the name of the SRV target 2158 SameDomainName(&rr->resrec.rdata->u.srv.target, r2->resrec.name) && 2159 (rr->ImmedAnswer == mDNSInterfaceMark || rr->ImmedAnswer == r2->resrec.InterfaceID)) 2160 r2->ImmedAdditional = r2->resrec.InterfaceID; // ... then mark this address record for sending too 2161 // We also make sure we send the DeviceInfo TXT record too, if necessary 2162 // We check for RecordType == kDNSRecordTypeShared because we don't want to tag the 2163 // DeviceInfo TXT record onto a goodbye packet (RecordType == kDNSRecordTypeDeregistering). 2164 if (rr->ImmedAnswer && rr->resrec.RecordType == kDNSRecordTypeShared && rr->resrec.rrtype == kDNSType_PTR) 2165 if (ResourceRecordIsValidAnswer(&m->DeviceInfo) && SameDomainLabel(rr->resrec.rdata->u.name.c, m->DeviceInfo.resrec.name->c)) 2166 { 2167 if (!m->DeviceInfo.ImmedAnswer) m->DeviceInfo.ImmedAnswer = rr->ImmedAnswer; 2168 else m->DeviceInfo.ImmedAnswer = mDNSInterfaceMark; 2169 } 2170 } 2171 2172 // If there's a record which is supposed to be unique that we're going to send, then make sure that we give 2173 // the whole RRSet as an atomic unit. That means that if we have any other records with the same name/type/class 2174 // then we need to mark them for sending too. Otherwise, if we set the kDNSClass_UniqueRRSet bit on a 2175 // record, then other RRSet members that have not been sent recently will get flushed out of client caches. 2176 // -- If a record is marked to be sent on a certain interface, make sure the whole set is marked to be sent on that interface 2177 // -- If any record is marked to be sent on all interfaces, make sure the whole set is marked to be sent on all interfaces 2178 for (rr = m->ResourceRecords; rr; rr=rr->next) 2179 if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask) 2180 { 2181 if (rr->ImmedAnswer) // If we're sending this as answer, see that its whole RRSet is similarly marked 2182 { 2183 for (r2 = m->ResourceRecords; r2; r2=r2->next) 2184 if (ResourceRecordIsValidAnswer(r2)) 2185 if (r2->ImmedAnswer != mDNSInterfaceMark && 2186 r2->ImmedAnswer != rr->ImmedAnswer && SameResourceRecordSignature(r2, rr)) 2187 r2->ImmedAnswer = !r2->ImmedAnswer ? rr->ImmedAnswer : mDNSInterfaceMark; 2188 } 2189 else if (rr->ImmedAdditional) // If we're sending this as additional, see that its whole RRSet is similarly marked 2190 { 2191 for (r2 = m->ResourceRecords; r2; r2=r2->next) 2192 if (ResourceRecordIsValidAnswer(r2)) 2193 if (r2->ImmedAdditional != rr->ImmedAdditional && SameResourceRecordSignature(r2, rr)) 2194 r2->ImmedAdditional = rr->ImmedAdditional; 2195 } 2196 } 2197 2198 // Now set SendRNow state appropriately 2199 for (rr = m->ResourceRecords; rr; rr=rr->next) 2200 { 2201 if (rr->ImmedAnswer == mDNSInterfaceMark) // Sending this record on all appropriate interfaces 2202 { 2203 rr->SendRNow = !intf ? mDNSNULL : (rr->resrec.InterfaceID) ? rr->resrec.InterfaceID : intf->InterfaceID; 2204 rr->ImmedAdditional = mDNSNULL; // No need to send as additional if sending as answer 2205 rr->LastMCTime = m->timenow; 2206 rr->LastMCInterface = rr->ImmedAnswer; 2207 // If we're announcing this record, and it's at least half-way to its ordained time, then consider this announcement done 2208 if (TimeToAnnounceThisRecord(rr, m->timenow + rr->ThisAPInterval/2)) 2209 { 2210 rr->AnnounceCount--; 2211 if (rr->resrec.RecordType != kDNSRecordTypeDeregistering) 2212 rr->ThisAPInterval *= 2; 2213 rr->LastAPTime = m->timenow; 2214 debugf("Announcing %##s (%s) %d", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->AnnounceCount); 2215 } 2216 } 2217 else if (rr->ImmedAnswer) // Else, just respond to a single query on single interface: 2218 { 2219 rr->SendRNow = rr->ImmedAnswer; // Just respond on that interface 2220 rr->ImmedAdditional = mDNSNULL; // No need to send as additional too 2221 rr->LastMCTime = m->timenow; 2222 rr->LastMCInterface = rr->ImmedAnswer; 2223 } 2224 SetNextAnnounceProbeTime(m, rr); 2225 //if (rr->SendRNow) LogMsg("%-15.4a %s", &rr->v4Requester, ARDisplayString(m, rr)); 2226 } 2227 2228 // *** 2229 // *** 2. Loop through interface list, sending records as appropriate 2230 // *** 2231 2232 while (intf) 2233 { 2234 const int OwnerRecordSpace = (m->AnnounceOwner && intf->MAC.l[0]) ? DNSOpt_Header_Space + DNSOpt_Owner_Space(&m->PrimaryMAC, &intf->MAC) : 0; 2235 int numDereg = 0; 2236 int numAnnounce = 0; 2237 int numAnswer = 0; 2238 mDNSu8 *responseptr = m->omsg.data; 2239 mDNSu8 *newptr;