1 /* -*- Mode: C; tab-width: 4 -*- 2 * 3 * Copyright (c) 2002-2013 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 26 #include "DNSCommon.h" // Defines general DNS utility routines 27 #include "uDNS.h" // Defines entry points into unicast-specific routines 28 #include "nsec.h" 29 #include "dnssec.h" 30 #include "anonymous.h" 31 32 // Disable certain benign warnings with Microsoft compilers 33 #if (defined(_MSC_VER)) 34 // Disable "conditional expression is constant" warning for debug macros. 35 // Otherwise, this generates warnings for the perfectly natural construct "while(1)" 36 // If someone knows a variant way of writing "while(1)" that doesn't generate warning messages, please let us know 37 #pragma warning(disable:4127) 38 39 // Disable "assignment within conditional expression". 40 // Other compilers understand the convention that if you place the assignment expression within an extra pair 41 // of parentheses, this signals to the compiler that you really intended an assignment and no warning is necessary. 42 // The Microsoft compiler doesn't understand this convention, so in the absense of any other way to signal 43 // to the compiler that the assignment is intentional, we have to just turn this warning off completely. 44 #pragma warning(disable:4706) 45 #endif 46 47 #include "dns_sd.h" // for kDNSServiceFlags* definitions 48 49 #if APPLE_OSX_mDNSResponder 50 51 #include <WebFilterDNS/WebFilterDNS.h> 52 53 #if !NO_WCF 54 WCFConnection *WCFConnectionNew(void) __attribute__((weak_import)); 55 void WCFConnectionDealloc(WCFConnection* c) __attribute__((weak_import)); 56 57 // Do we really need to define a macro for "if"? 58 #define CHECK_WCF_FUNCTION(X) if (X) 59 #endif // ! NO_WCF 60 61 #else 62 63 #define NO_WCF 1 64 #endif // APPLE_OSX_mDNSResponder 65 66 // Forward declarations 67 mDNSlocal void BeginSleepProcessing(mDNS *const m); 68 mDNSlocal void RetrySPSRegistrations(mDNS *const m); 69 mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password); 70 mDNSlocal mDNSBool CacheRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q); 71 mDNSlocal mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q); 72 mDNSlocal void mDNS_PurgeForQuestion(mDNS *const m, DNSQuestion *q); 73 mDNSlocal void CheckForDNSSECRecords(mDNS *const m, DNSQuestion *q); 74 mDNSlocal void mDNS_SendKeepalives(mDNS *const m); 75 mDNSlocal void mDNS_ExtractKeepaliveInfo(AuthRecord *ar, mDNSu32 *timeout, mDNSAddr *laddr, mDNSAddr *raddr, mDNSEthAddr *eth, 76 mDNSu32 *seq, mDNSu32 *ack, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu16 *win); 77 78 mDNSlocal void AdvertiseAllInterfaceRecords(mDNS *const m); 79 mDNSlocal void DeadvertiseAllInterfaceRecords(mDNS *const m); 80 mDNSlocal void FreeNSECRecords(mDNS *const m, CacheRecord *NSECRecords); 81 mDNSlocal void mDNSParseNSEC3Records(mDNS *const m, const DNSMessage *const response, const mDNSu8 *end, 82 const mDNSInterfaceID InterfaceID, CacheRecord **NSEC3Records); 83 84 85 // *************************************************************************** 86 #if COMPILER_LIKES_PRAGMA_MARK 87 #pragma mark - Program Constants 88 #endif 89 90 // To Turn OFF mDNS_Tracer set MDNS_TRACER to 0 or undef it 91 #define MDNS_TRACER 1 92 93 #define NO_HINFO 1 94 95 // Any records bigger than this are considered 'large' records 96 #define SmallRecordLimit 1024 97 98 #define kMaxUpdateCredits 10 99 #define kUpdateCreditRefreshInterval (mDNSPlatformOneSecond * 6) 100 101 // define special NR_AnswerTo values 102 #define NR_AnswerMulticast (mDNSu8*)~0 103 #define NR_AnswerUnicast (mDNSu8*)~1 104 105 // Defined to set the kDNSQClass_UnicastResponse bit in the first four query packets. 106 // else, it's just set it the first query. 107 #define mDNS_REQUEST_UNICAST_RESPONSE 0 108 109 // The code (see SendQueries() and BuildQuestion()) needs to have the 110 // RequestUnicast value set to a value one greater than the number of times you want the query 111 // sent with the "request unicast response" (QU) bit set. 112 #define SET_QU_IN_FIRST_QUERY 2 113 #define SET_QU_IN_FIRST_FOUR_QUERIES 5 114 115 116 mDNSexport const char *const mDNS_DomainTypeNames[] = 117 { 118 "b._dns-sd._udp.", // Browse 119 "db._dns-sd._udp.", // Default Browse 120 "lb._dns-sd._udp.", // Automatic Browse 121 "r._dns-sd._udp.", // Registration 122 "dr._dns-sd._udp." // Default Registration 123 }; 124 125 #ifdef UNICAST_DISABLED 126 #define uDNS_IsActiveQuery(q, u) mDNSfalse 127 #endif 128 129 // *************************************************************************** 130 #if COMPILER_LIKES_PRAGMA_MARK 131 #pragma mark - 132 #pragma mark - General Utility Functions 133 #endif 134 135 // Returns true if this is a unique, authoritative LocalOnly record that answers questions of type 136 // A, AAAA , CNAME, or PTR. The caller should answer the question with this record and not send out 137 // the question on the wire if LocalOnlyRecordAnswersQuestion() also returns true. 138 // Main use is to handle /etc/hosts records and the LocalOnly PTR records created for localhost. 139 #define UniqueLocalOnlyRecord(rr) ((rr)->ARType == AuthRecordLocalOnly && \ 140 (rr)->resrec.RecordType & kDNSRecordTypeUniqueMask && \ 141 ((rr)->resrec.rrtype == kDNSType_A || (rr)->resrec.rrtype == kDNSType_AAAA || \ 142 (rr)->resrec.rrtype == kDNSType_CNAME || \ 143 (rr)->resrec.rrtype == kDNSType_PTR)) 144 145 mDNSlocal void SetNextQueryStopTime(mDNS *const m, const DNSQuestion *const q) 146 { 147 mDNS_CheckLock(m); 148 149 #if ForceAlerts 150 if (m->mDNS_busy != m->mDNS_reentrancy+1) *(long*)0 = 0; 151 #endif 152 153 if (m->NextScheduledStopTime - q->StopTime > 0) 154 m->NextScheduledStopTime = q->StopTime; 155 } 156 157 mDNSexport void SetNextQueryTime(mDNS *const m, const DNSQuestion *const q) 158 { 159 mDNS_CheckLock(m); 160 161 #if ForceAlerts 162 if (m->mDNS_busy != m->mDNS_reentrancy+1) *(long*)0 = 0; 163 #endif 164 165 if (ActiveQuestion(q)) 166 { 167 // Depending on whether this is a multicast or unicast question we want to set either: 168 // m->NextScheduledQuery = NextQSendTime(q) or 169 // m->NextuDNSEvent = NextQSendTime(q) 170 mDNSs32 *const timer = mDNSOpaque16IsZero(q->TargetQID) ? &m->NextScheduledQuery : &m->NextuDNSEvent; 171 if (*timer - NextQSendTime(q) > 0) 172 *timer = NextQSendTime(q); 173 } 174 } 175 176 mDNSlocal void ReleaseAuthEntity(AuthHash *r, AuthEntity *e) 177 { 178 #if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING >= 1 179 unsigned int i; 180 for (i=0; i<sizeof(*e); i++) ((char*)e)[i] = 0xFF; 181 #endif 182 e->next = r->rrauth_free; 183 r->rrauth_free = e; 184 r->rrauth_totalused--; 185 } 186 187 mDNSlocal void ReleaseAuthGroup(AuthHash *r, AuthGroup **cp) 188 { 189 AuthEntity *e = (AuthEntity *)(*cp); 190 LogMsg("ReleaseAuthGroup: Releasing AuthGroup %##s", (*cp)->name->c); 191 if ((*cp)->rrauth_tail != &(*cp)->members) 192 LogMsg("ERROR: (*cp)->members == mDNSNULL but (*cp)->rrauth_tail != &(*cp)->members)"); 193 if ((*cp)->name != (domainname*)((*cp)->namestorage)) mDNSPlatformMemFree((*cp)->name); 194 (*cp)->name = mDNSNULL; 195 *cp = (*cp)->next; // Cut record from list 196 ReleaseAuthEntity(r, e); 197 } 198 199 mDNSlocal AuthEntity *GetAuthEntity(AuthHash *r, const AuthGroup *const PreserveAG) 200 { 201 AuthEntity *e = mDNSNULL; 202 203 if (r->rrauth_lock) { LogMsg("GetFreeCacheRR ERROR! Cache already locked!"); return(mDNSNULL); } 204 r->rrauth_lock = 1; 205 206 if (!r->rrauth_free) 207 { 208 // We allocate just one AuthEntity at a time because we need to be able 209 // free them all individually which normally happens when we parse /etc/hosts into 210 // AuthHash where we add the "new" entries and discard (free) the already added 211 // entries. If we allocate as chunks, we can't free them individually. 212 AuthEntity *storage = mDNSPlatformMemAllocate(sizeof(AuthEntity)); 213 storage->next = mDNSNULL; 214 r->rrauth_free = storage; 215 } 216 217 // If we still have no free records, recycle all the records we can. 218 // Enumerating the entire auth is moderately expensive, so when we do it, we reclaim all the records we can in one pass. 219 if (!r->rrauth_free) 220 { 221 mDNSu32 oldtotalused = r->rrauth_totalused; 222 mDNSu32 slot; 223 for (slot = 0; slot < AUTH_HASH_SLOTS; slot++) 224 { 225 AuthGroup **cp = &r->rrauth_hash[slot]; 226 while (*cp) 227 { 228 if ((*cp)->members || (*cp)==PreserveAG) cp=&(*cp)->next; 229 else ReleaseAuthGroup(r, cp); 230 } 231 } 232 LogInfo("GetAuthEntity: Recycled %d records to reduce auth cache from %d to %d", 233 oldtotalused - r->rrauth_totalused, oldtotalused, r->rrauth_totalused); 234 } 235 236 if (r->rrauth_free) // If there are records in the free list, take one 237 { 238 e = r->rrauth_free; 239 r->rrauth_free = e->next; 240 if (++r->rrauth_totalused >= r->rrauth_report) 241 { 242 LogInfo("RR Auth now using %ld objects", r->rrauth_totalused); 243 if (r->rrauth_report < 100) r->rrauth_report += 10; 244 else if (r->rrauth_report < 1000) r->rrauth_report += 100; 245 else r->rrauth_report += 1000; 246 } 247 mDNSPlatformMemZero(e, sizeof(*e)); 248 } 249 250 r->rrauth_lock = 0; 251 252 return(e); 253 } 254 255 mDNSexport AuthGroup *AuthGroupForName(AuthHash *r, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name) 256 { 257 AuthGroup *ag; 258 for (ag = r->rrauth_hash[slot]; ag; ag=ag->next) 259 if (ag->namehash == namehash && SameDomainName(ag->name, name)) 260 break; 261 return(ag); 262 } 263 264 mDNSexport AuthGroup *AuthGroupForRecord(AuthHash *r, const mDNSu32 slot, const ResourceRecord *const rr) 265 { 266 return(AuthGroupForName(r, slot, rr->namehash, rr->name)); 267 } 268 269 mDNSlocal AuthGroup *GetAuthGroup(AuthHash *r, const mDNSu32 slot, const ResourceRecord *const rr) 270 { 271 mDNSu16 namelen = DomainNameLength(rr->name); 272 AuthGroup *ag = (AuthGroup*)GetAuthEntity(r, mDNSNULL); 273 if (!ag) { LogMsg("GetAuthGroup: Failed to allocate memory for %##s", rr->name->c); return(mDNSNULL); } 274 ag->next = r->rrauth_hash[slot]; 275 ag->namehash = rr->namehash; 276 ag->members = mDNSNULL; 277 ag->rrauth_tail = &ag->members; 278 ag->NewLocalOnlyRecords = mDNSNULL; 279 if (namelen > sizeof(ag->namestorage)) 280 ag->name = mDNSPlatformMemAllocate(namelen); 281 else 282 ag->name = (domainname*)ag->namestorage; 283 if (!ag->name) 284 { 285 LogMsg("GetAuthGroup: Failed to allocate name storage for %##s", rr->name->c); 286 ReleaseAuthEntity(r, (AuthEntity*)ag); 287 return(mDNSNULL); 288 } 289 AssignDomainName(ag->name, rr->name); 290 291 if (AuthGroupForRecord(r, slot, rr)) LogMsg("GetAuthGroup: Already have AuthGroup for %##s", rr->name->c); 292 r->rrauth_hash[slot] = ag; 293 if (AuthGroupForRecord(r, slot, rr) != ag) LogMsg("GetAuthGroup: Not finding AuthGroup for %##s", rr->name->c); 294 295 return(ag); 296 } 297 298 // Returns the AuthGroup in which the AuthRecord was inserted 299 mDNSexport AuthGroup *InsertAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr) 300 { 301 AuthGroup *ag; 302 const mDNSu32 slot = AuthHashSlot(rr->resrec.name); 303 ag = AuthGroupForRecord(r, slot, &rr->resrec); 304 if (!ag) ag = GetAuthGroup(r, slot, &rr->resrec); // If we don't have a AuthGroup for this name, make one now 305 if (ag) 306 { 307 LogInfo("InsertAuthRecord: inserting auth record %s from table", ARDisplayString(m, rr)); 308 *(ag->rrauth_tail) = rr; // Append this record to tail of cache slot list 309 ag->rrauth_tail = &(rr->next); // Advance tail pointer 310 } 311 return ag; 312 } 313 314 mDNSexport AuthGroup *RemoveAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr) 315 { 316 AuthGroup *a; 317 AuthGroup **ag = &a; 318 AuthRecord **rp; 319 const mDNSu32 slot = AuthHashSlot(rr->resrec.name); 320 321 a = AuthGroupForRecord(r, slot, &rr->resrec); 322 if (!a) { LogMsg("RemoveAuthRecord: ERROR!! AuthGroup not found for %s", ARDisplayString(m, rr)); return mDNSNULL; } 323 rp = &(*ag)->members; 324 while (*rp) 325 { 326 if (*rp != rr) 327 rp=&(*rp)->next; 328 else 329 { 330 // We don't break here, so that we can set the tail below without tracking "prev" pointers 331 332 LogInfo("RemoveAuthRecord: removing auth record %s from table", ARDisplayString(m, rr)); 333 *rp = (*rp)->next; // Cut record from list 334 } 335 } 336 // TBD: If there are no more members, release authgroup ? 337 (*ag)->rrauth_tail = rp; 338 return a; 339 } 340 341 mDNSexport CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name) 342 { 343 CacheGroup *cg; 344 for (cg = m->rrcache_hash[slot]; cg; cg=cg->next) 345 if (cg->namehash == namehash && SameDomainName(cg->name, name)) 346 break; 347 return(cg); 348 } 349 350 mDNSlocal CacheGroup *CacheGroupForRecord(const mDNS *const m, const mDNSu32 slot, const ResourceRecord *const rr) 351 { 352 return(CacheGroupForName(m, slot, rr->namehash, rr->name)); 353 } 354 355 mDNSexport mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr, mDNSBool *myself) 356 { 357 NetworkInterfaceInfo *intf; 358 359 if (addr->type == mDNSAddrType_IPv4) 360 { 361 // Normally we resist touching the NotAnInteger fields, but here we're doing tricky bitwise masking so we make an exception 362 if (mDNSv4AddressIsLinkLocal(&addr->ip.v4)) return(mDNStrue); 363 for (intf = m->HostInterfaces; intf; intf = intf->next) 364 if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID && intf->McastTxRx) 365 if (((intf->ip.ip.v4.NotAnInteger ^ addr->ip.v4.NotAnInteger) & intf->mask.ip.v4.NotAnInteger) == 0) 366 { 367 if (myself) 368 { 369 if (mDNSSameIPv4Address(intf->ip.ip.v4, addr->ip.v4)) 370 *myself = mDNStrue; 371 else 372 *myself = mDNSfalse; 373 if (*myself) 374 debugf("mDNS_AddressIsLocalSubnet: IPv4 %#a returning true", addr); 375 else 376 debugf("mDNS_AddressIsLocalSubnet: IPv4 %#a returning false", addr); 377 } 378 return(mDNStrue); 379 } 380 } 381 382 if (addr->type == mDNSAddrType_IPv6) 383 { 384 for (intf = m->HostInterfaces; intf; intf = intf->next) 385 if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID && intf->McastTxRx) 386 if ((((intf->ip.ip.v6.l[0] ^ addr->ip.v6.l[0]) & intf->mask.ip.v6.l[0]) == 0) && 387 (((intf->ip.ip.v6.l[1] ^ addr->ip.v6.l[1]) & intf->mask.ip.v6.l[1]) == 0) && 388 (((intf->ip.ip.v6.l[2] ^ addr->ip.v6.l[2]) & intf->mask.ip.v6.l[2]) == 0) && 389 (((intf->ip.ip.v6.l[3] ^ addr->ip.v6.l[3]) & intf->mask.ip.v6.l[3]) == 0)) 390 { 391 if (myself) 392 { 393 if (mDNSSameIPv6Address(intf->ip.ip.v6, addr->ip.v6)) 394 *myself = mDNStrue; 395 else 396 *myself = mDNSfalse; 397 if (*myself) 398 debugf("mDNS_AddressIsLocalSubnet: IPv6 %#a returning true", addr); 399 else 400 debugf("mDNS_AddressIsLocalSubnet: IPv6 %#a returning false", addr); 401 } 402 return(mDNStrue); 403 } 404 } 405 406 return(mDNSfalse); 407 } 408 409 mDNSlocal NetworkInterfaceInfo *FirstInterfaceForID(mDNS *const m, const mDNSInterfaceID InterfaceID) 410 { 411 NetworkInterfaceInfo *intf = m->HostInterfaces; 412 while (intf && intf->InterfaceID != InterfaceID) intf = intf->next; 413 return(intf); 414 } 415 416 mDNSlocal NetworkInterfaceInfo *FirstIPv4LLInterfaceForID(mDNS *const m, const mDNSInterfaceID InterfaceID) 417 { 418 NetworkInterfaceInfo *intf; 419 420 if (!InterfaceID) 421 return mDNSNULL; 422 423 // Note: We don't check for InterfaceActive, as the active interface could be IPv6 and 424 // we still want to find the first IPv4 Link-Local interface 425 for (intf = m->HostInterfaces; intf; intf = intf->next) 426 { 427 if (intf->InterfaceID == InterfaceID && 428 intf->ip.type == mDNSAddrType_IPv4 && mDNSv4AddressIsLinkLocal(&intf->ip.ip.v4)) 429 { 430 debugf("FirstIPv4LLInterfaceForID: found LL interface with address %.4a", &intf->ip.ip.v4); 431 return intf; 432 } 433 } 434 return (mDNSNULL); 435 } 436 437 mDNSexport char *InterfaceNameForID(mDNS *const m, const mDNSInterfaceID InterfaceID) 438 { 439 NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID); 440 return(intf ? intf->ifname : mDNSNULL); 441 } 442 443 // Caller should hold the lock 444 mDNSlocal void GenerateNegativeResponse(mDNS *const m, QC_result qc) 445 { 446 DNSQuestion *q; 447 if (!m->CurrentQuestion) { LogMsg("GenerateNegativeResponse: ERROR!! CurrentQuestion not set"); return; } 448 q = m->CurrentQuestion; 449 LogInfo("GenerateNegativeResponse: Generating negative response for question %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 450 451 MakeNegativeCacheRecord(m, &m->rec.r, &q->qname, q->qnamehash, q->qtype, q->qclass, 60, mDNSInterface_Any, mDNSNULL); 452 // We need to force the response through in the following cases 453 // 454 // a) SuppressUnusable questions that are suppressed 455 // b) Append search domains and retry the question 456 // 457 // The question may not have set Intermediates in which case we don't deliver negative responses. So, to force 458 // through we use "QC_forceresponse". 459 AnswerCurrentQuestionWithResourceRecord(m, &m->rec.r, qc); 460 if (m->CurrentQuestion == q) { q->ThisQInterval = 0; } // Deactivate this question 461 // Don't touch the question after this 462 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 463 } 464 465 mDNSexport void AnswerQuestionByFollowingCNAME(mDNS *const m, DNSQuestion *q, ResourceRecord *rr) 466 { 467 const mDNSBool selfref = SameDomainName(&q->qname, &rr->rdata->u.name); 468 if (q->CNAMEReferrals >= 10 || selfref) 469 { 470 LogMsg("AnswerQuestionByFollowingCNAME: %p %##s (%s) NOT following CNAME referral %d%s for %s", 471 q, q->qname.c, DNSTypeName(q->qtype), q->CNAMEReferrals, selfref ? " (Self-Referential)" : "", RRDisplayString(m, rr)); 472 } 473 else 474 { 475 const mDNSu32 c = q->CNAMEReferrals + 1; // Stash a copy of the new q->CNAMEReferrals value 476 UDPSocket *sock = q->LocalSocket; 477 mDNSOpaque16 id = q->TargetQID; 478 479 // if there is a message waiting at the socket, we want to process that instead 480 // of throwing it away. If we have a CNAME response that answers 481 // both A and AAAA question and while answering it we don't want to throw 482 // away the response where the actual addresses are present. 483 if (mDNSPlatformPeekUDP(m, q->LocalSocket)) 484 { 485 LogInfo("AnswerQuestionByFollowingCNAME: Preserving UDP socket for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 486 q->LocalSocket = mDNSNULL; 487 } 488 else 489 { 490 sock = mDNSNULL; 491 } 492 493 // The SameDomainName check above is to ignore bogus CNAME records that point right back at 494 // themselves. Without that check we can get into a case where we have two duplicate questions, 495 // A and B, and when we stop question A, UpdateQuestionDuplicates copies the value of CNAMEReferrals 496 // from A to B, and then A is re-appended to the end of the list as a duplicate of B (because 497 // the target name is still the same), and then when we stop question B, UpdateQuestionDuplicates 498 // copies the B's value of CNAMEReferrals back to A, and we end up not incrementing CNAMEReferrals 499 // for either of them. This is not a problem for CNAME loops of two or more records because in 500 // those cases the newly re-appended question A has a different target name and therefore cannot be 501 // a duplicate of any other question ('B') which was itself a duplicate of the previous question A. 502 503 // Right now we just stop and re-use the existing query. If we really wanted to be 100% perfect, 504 // and track CNAMEs coming and going, we should really create a subordinate query here, 505 // which we would subsequently cancel and retract if the CNAME referral record were removed. 506 // In reality this is such a corner case we'll ignore it until someone actually needs it. 507 508 LogInfo("AnswerQuestionByFollowingCNAME: %p %##s (%s) following CNAME referral %d for %s", 509 q, q->qname.c, DNSTypeName(q->qtype), q->CNAMEReferrals, RRDisplayString(m, rr)); 510 511 mDNS_StopQuery_internal(m, q); // Stop old query 512 AssignDomainName(&q->qname, &rr->rdata->u.name); // Update qname 513 q->qnamehash = DomainNameHashValue(&q->qname); // and namehash 514 // If a unicast query results in a CNAME that points to a .local, we need to re-try 515 // this as unicast. Setting the mDNSInterface_Unicast tells mDNS_StartQuery_internal 516 // to try this as unicast query even though it is a .local name 517 if (!mDNSOpaque16IsZero(q->TargetQID) && IsLocalDomain(&q->qname)) 518 { 519 LogInfo("AnswerQuestionByFollowingCNAME: Resolving a .local CNAME %p %##s (%s) Record %s", 520 q, q->qname.c, DNSTypeName(q->qtype), RRDisplayString(m, rr)); 521 q->InterfaceID = mDNSInterface_Unicast; 522 } 523 mDNS_StartQuery_internal(m, q); // start new query 524 // Record how many times we've done this. We need to do this *after* mDNS_StartQuery_internal, 525 // because mDNS_StartQuery_internal re-initializes CNAMEReferrals to zero 526 q->CNAMEReferrals = c; 527 if (sock) 528 { 529 // We have a message waiting and that should answer this question. 530 if (q->LocalSocket) 531 mDNSPlatformUDPClose(q->LocalSocket); 532 q->LocalSocket = sock; 533 q->TargetQID = id; 534 } 535 } 536 } 537 538 // For a single given DNSQuestion pointed to by CurrentQuestion, deliver an add/remove result for the single given AuthRecord 539 // Note: All the callers should use the m->CurrentQuestion to see if the question is still valid or not 540 mDNSlocal void AnswerLocalQuestionWithLocalAuthRecord(mDNS *const m, AuthRecord *rr, QC_result AddRecord) 541 { 542 DNSQuestion *q = m->CurrentQuestion; 543 mDNSBool followcname; 544 545 if (!q) 546 { 547 LogMsg("AnswerLocalQuestionWithLocalAuthRecord: ERROR!! CurrentQuestion NULL while answering with %s", ARDisplayString(m, rr)); 548 return; 549 } 550 551 followcname = FollowCNAME(q, &rr->resrec, AddRecord); 552 553 // We should not be delivering results for record types Unregistered, Deregistering, and (unverified) Unique 554 if (!(rr->resrec.RecordType & kDNSRecordTypeActiveMask)) 555 { 556 LogMsg("AnswerLocalQuestionWithLocalAuthRecord: *NOT* delivering %s event for local record type %X %s", 557 AddRecord ? "Add" : "Rmv", rr->resrec.RecordType, ARDisplayString(m, rr)); 558 return; 559 } 560 561 // Indicate that we've given at least one positive answer for this record, so we should be prepared to send a goodbye for it 562 if (AddRecord) rr->AnsweredLocalQ = mDNStrue; 563 mDNS_DropLockBeforeCallback(); // Allow client to legally make mDNS API calls from the callback 564 if (q->QuestionCallback && !q->NoAnswer) 565 { 566 q->CurrentAnswers += AddRecord ? 1 : -1; 567 if (UniqueLocalOnlyRecord(rr)) 568 { 569 if (!followcname || q->ReturnIntermed) 570 { 571 // Don't send this packet on the wire as we answered from /etc/hosts 572 q->ThisQInterval = 0; 573 q->LOAddressAnswers += AddRecord ? 1 : -1; 574 q->QuestionCallback(m, q, &rr->resrec, AddRecord); 575 } 576 mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again 577 // The callback above could have caused the question to stop. Detect that 578 // using m->CurrentQuestion 579 if (followcname && m->CurrentQuestion == q) 580 AnswerQuestionByFollowingCNAME(m, q, &rr->resrec); 581 return; 582 } 583 else 584 { 585 q->QuestionCallback(m, q, &rr->resrec, AddRecord); 586 } 587 } 588 mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again 589 } 590 591 mDNSlocal void AnswerInterfaceAnyQuestionsWithLocalAuthRecord(mDNS *const m, AuthRecord *rr, QC_result AddRecord) 592 { 593 if (m->CurrentQuestion) 594 LogMsg("AnswerInterfaceAnyQuestionsWithLocalAuthRecord: ERROR m->CurrentQuestion already set: %##s (%s)", 595 m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype)); 596 m->CurrentQuestion = m->Questions; 597 while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions) 598 { 599 mDNSBool answered; 600 DNSQuestion *q = m->CurrentQuestion; 601 if (RRAny(rr)) 602 answered = ResourceRecordAnswersQuestion(&rr->resrec, q); 603 else 604 answered = LocalOnlyRecordAnswersQuestion(rr, q); 605 if (answered) 606 AnswerLocalQuestionWithLocalAuthRecord(m, rr, AddRecord); // MUST NOT dereference q again 607 if (m->CurrentQuestion == q) // If m->CurrentQuestion was not auto-advanced, do it ourselves now 608 m->CurrentQuestion = q->next; 609 } 610 m->CurrentQuestion = mDNSNULL; 611 } 612 613 // When a new local AuthRecord is created or deleted, AnswerAllLocalQuestionsWithLocalAuthRecord() 614 // delivers the appropriate add/remove events to listening questions: 615 // 1. It runs though all our LocalOnlyQuestions delivering answers as appropriate, 616 // stopping if it reaches a NewLocalOnlyQuestion -- brand-new questions are handled by AnswerNewLocalOnlyQuestion(). 617 // 2. If the AuthRecord is marked mDNSInterface_LocalOnly or mDNSInterface_P2P, then it also runs though 618 // our main question list, delivering answers to mDNSInterface_Any questions as appropriate, 619 // stopping if it reaches a NewQuestion -- brand-new questions are handled by AnswerNewQuestion(). 620 // 621 // AnswerAllLocalQuestionsWithLocalAuthRecord is used by the m->NewLocalRecords loop in mDNS_Execute(), 622 // and by mDNS_Deregister_internal() 623 624 mDNSlocal void AnswerAllLocalQuestionsWithLocalAuthRecord(mDNS *const m, AuthRecord *rr, QC_result AddRecord) 625 { 626 if (m->CurrentQuestion) 627 LogMsg("AnswerAllLocalQuestionsWithLocalAuthRecord ERROR m->CurrentQuestion already set: %##s (%s)", 628 m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype)); 629 630 m->CurrentQuestion = m->LocalOnlyQuestions; 631 while (m->CurrentQuestion && m->CurrentQuestion != m->NewLocalOnlyQuestions) 632 { 633 mDNSBool answered; 634 DNSQuestion *q = m->CurrentQuestion; 635 // We are called with both LocalOnly/P2P record or a regular AuthRecord 636 if (RRAny(rr)) 637 answered = ResourceRecordAnswersQuestion(&rr->resrec, q); 638 else 639 answered = LocalOnlyRecordAnswersQuestion(rr, q); 640 if (answered) 641 AnswerLocalQuestionWithLocalAuthRecord(m, rr, AddRecord); // MUST NOT dereference q again 642 if (m->CurrentQuestion == q) // If m->CurrentQuestion was not auto-advanced, do it ourselves now 643 m->CurrentQuestion = q->next; 644 } 645 646 m->CurrentQuestion = mDNSNULL; 647 648 // If this AuthRecord is marked LocalOnly or P2P, then we want to deliver it to all local 'mDNSInterface_Any' questions 649 if (rr->ARType == AuthRecordLocalOnly || rr->ARType == AuthRecordP2P) 650 AnswerInterfaceAnyQuestionsWithLocalAuthRecord(m, rr, AddRecord); 651 652 } 653 654 // *************************************************************************** 655 #if COMPILER_LIKES_PRAGMA_MARK 656 #pragma mark - 657 #pragma mark - Resource Record Utility Functions 658 #endif 659 660 #define RRTypeIsAddressType(T) ((T) == kDNSType_A || (T) == kDNSType_AAAA) 661 662 #define ResourceRecordIsValidAnswer(RR) ( ((RR)->resrec.RecordType & kDNSRecordTypeActiveMask) && \ 663 ((RR)->Additional1 == mDNSNULL || ((RR)->Additional1->resrec.RecordType & kDNSRecordTypeActiveMask)) && \ 664 ((RR)->Additional2 == mDNSNULL || ((RR)->Additional2->resrec.RecordType & kDNSRecordTypeActiveMask)) && \ 665 ((RR)->DependentOn == mDNSNULL || ((RR)->DependentOn->resrec.RecordType & kDNSRecordTypeActiveMask)) ) 666 667 #define ResourceRecordIsValidInterfaceAnswer(RR, INTID) \ 668 (ResourceRecordIsValidAnswer(RR) && \ 669 ((RR)->resrec.InterfaceID == mDNSInterface_Any || (RR)->resrec.InterfaceID == (INTID))) 670 671 #define DefaultProbeCountForTypeUnique ((mDNSu8)3) 672 #define DefaultProbeCountForRecordType(X) ((X) == kDNSRecordTypeUnique ? DefaultProbeCountForTypeUnique : (mDNSu8)0) 673 674 // See RFC 6762: "8.3 Announcing" 675 // "The Multicast DNS responder MUST send at least two unsolicited responses, one second apart." 676 // Send 4, which is really 8 since we send on both IPv4 and IPv6. 677 #define InitialAnnounceCount ((mDNSu8)4) 678 679 // For goodbye packets we set the count to 3, and for wakeups we set it to 18 680 // (which will be up to 15 wakeup attempts over the course of 30 seconds, 681 // and then if the machine fails to wake, 3 goodbye packets). 682 #define GoodbyeCount ((mDNSu8)3) 683 #define WakeupCount ((mDNSu8)18) 684 #define MAX_PROBE_RESTARTS ((mDNSu8)20) 685 686 // Number of wakeups we send if WakeOnResolve is set in the question 687 #define InitialWakeOnResolveCount ((mDNSu8)3) 688 689 // Note that the announce intervals use exponential backoff, doubling each time. The probe intervals do not. 690 // This means that because the announce interval is doubled after sending the first packet, the first 691 // observed on-the-wire inter-packet interval between announcements is actually one second. 692 // The half-second value here may be thought of as a conceptual (non-existent) half-second delay *before* the first packet is sent. 693 #define DefaultProbeIntervalForTypeUnique (mDNSPlatformOneSecond/4) 694 #define DefaultAnnounceIntervalForTypeShared (mDNSPlatformOneSecond/2) 695 #define DefaultAnnounceIntervalForTypeUnique (mDNSPlatformOneSecond/2) 696 697 #define DefaultAPIntervalForRecordType(X) ((X) &kDNSRecordTypeActiveSharedMask ? DefaultAnnounceIntervalForTypeShared : \ 698 (X) &kDNSRecordTypeUnique ? DefaultProbeIntervalForTypeUnique : \ 699 (X) &kDNSRecordTypeActiveUniqueMask ? DefaultAnnounceIntervalForTypeUnique : 0) 700 701 #define TimeToAnnounceThisRecord(RR,time) ((RR)->AnnounceCount && (time) - ((RR)->LastAPTime + (RR)->ThisAPInterval) >= 0) 702 #define TimeToSendThisRecord(RR,time) ((TimeToAnnounceThisRecord(RR,time) || (RR)->ImmedAnswer) && ResourceRecordIsValidAnswer(RR)) 703 #define TicksTTL(RR) ((mDNSs32)(RR)->resrec.rroriginalttl * mDNSPlatformOneSecond) 704 #define RRExpireTime(RR) ((RR)->TimeRcvd + TicksTTL(RR)) 705 706 // Adjustment factor to avoid race condition (used for unicast cache entries) : 707 // Suppose real record has TTL of 3600, and our local caching server has held it for 3500 seconds, so it returns an aged TTL of 100. 708 // If we do our normal refresh at 80% of the TTL, our local caching server will return 20 seconds, so we'll do another 709 // 80% refresh after 16 seconds, and then the server will return 4 seconds, and so on, in the fashion of Zeno's paradox. 710 // To avoid this, we extend the record's effective TTL to give it a little extra grace period. 711 // We adjust the 100 second TTL to 127. This means that when we do our 80% query at 102 seconds, 712 // the cached copy at our local caching server will already have expired, so the server will be forced 713 // to fetch a fresh copy from the authoritative server, and then return a fresh record with the full TTL of 3600 seconds. 714 715 #define RRAdjustTTL(ttl) ((ttl) + ((ttl)/4) + 2) 716 #define RRUnadjustedTTL(ttl) ((((ttl) - 2) * 4) / 5) 717 718 #define MaxUnansweredQueries 4 719 720 // SameResourceRecordSignature returns true if two resources records have the same name, type, and class, and may be sent 721 // (or were received) on the same interface (i.e. if *both* records specify an interface, then it has to match). 722 // TTL and rdata may differ. 723 // This is used for cache flush management: 724 // When sending a unique record, all other records matching "SameResourceRecordSignature" must also be sent 725 // When receiving a unique record, all old cache records matching "SameResourceRecordSignature" are flushed 726 727 // SameResourceRecordNameClassInterface is functionally the same as SameResourceRecordSignature, except rrtype does not have to match 728 729 #define SameResourceRecordSignature(A,B) (A)->resrec.rrtype == (B)->resrec.rrtype && SameResourceRecordNameClassInterface((A),(B)) 730 731 mDNSlocal mDNSBool SameResourceRecordNameClassInterface(const AuthRecord *const r1, const AuthRecord *const r2) 732 { 733 if (!r1) { LogMsg("SameResourceRecordSignature ERROR: r1 is NULL"); return(mDNSfalse); } 734 if (!r2) { LogMsg("SameResourceRecordSignature ERROR: r2 is NULL"); return(mDNSfalse); } 735 if (r1->resrec.InterfaceID && 736 r2->resrec.InterfaceID && 737 r1->resrec.InterfaceID != r2->resrec.InterfaceID) return(mDNSfalse); 738 return (mDNSBool)( 739 r1->resrec.rrclass == r2->resrec.rrclass && 740 r1->resrec.namehash == r2->resrec.namehash && 741 SameDomainName(r1->resrec.name, r2->resrec.name)); 742 } 743 744 // PacketRRMatchesSignature behaves as SameResourceRecordSignature, except that types may differ if our 745 // authoratative record is unique (as opposed to shared). For unique records, we are supposed to have 746 // complete ownership of *all* types for this name, so *any* record type with the same name is a conflict. 747 // In addition, when probing we send our questions with the wildcard type kDNSQType_ANY, 748 // so a response of any type should match, even if it is not actually the type the client plans to use. 749 750 // For now, to make it easier to avoid false conflicts, we treat SPS Proxy records like shared records, 751 // and require the rrtypes to match for the rdata to be considered potentially conflicting 752 mDNSlocal mDNSBool PacketRRMatchesSignature(const CacheRecord *const pktrr, const AuthRecord *const authrr) 753 { 754 if (!pktrr) { LogMsg("PacketRRMatchesSignature ERROR: pktrr is NULL"); return(mDNSfalse); } 755 if (!authrr) { LogMsg("PacketRRMatchesSignature ERROR: authrr is NULL"); return(mDNSfalse); } 756 if (pktrr->resrec.InterfaceID && 757 authrr->resrec.InterfaceID && 758 pktrr->resrec.InterfaceID != authrr->resrec.InterfaceID) return(mDNSfalse); 759 if (!(authrr->resrec.RecordType & kDNSRecordTypeUniqueMask) || authrr->WakeUp.HMAC.l[0]) 760 if (pktrr->resrec.rrtype != authrr->resrec.rrtype) return(mDNSfalse); 761 return (mDNSBool)( 762 pktrr->resrec.rrclass == authrr->resrec.rrclass && 763 pktrr->resrec.namehash == authrr->resrec.namehash && 764 SameDomainName(pktrr->resrec.name, authrr->resrec.name)); 765 } 766 767 // CacheRecord *ka is the CacheRecord from the known answer list in the query. 768 // This is the information that the requester believes to be correct. 769 // AuthRecord *rr is the answer we are proposing to give, if not suppressed. 770 // This is the information that we believe to be correct. 771 // We've already determined that we plan to give this answer on this interface 772 // (either the record is non-specific, or it is specific to this interface) 773 // so now we just need to check the name, type, class, rdata and TTL. 774 mDNSlocal mDNSBool ShouldSuppressKnownAnswer(const CacheRecord *const ka, const AuthRecord *const rr) 775 { 776 // If RR signature is different, or data is different, then don't suppress our answer 777 if (!IdenticalResourceRecord(&ka->resrec, &rr->resrec)) return(mDNSfalse); 778 779 // If the requester's indicated TTL is less than half the real TTL, 780 // we need to give our answer before the requester's copy expires. 781 // If the requester's indicated TTL is at least half the real TTL, 782 // then we can suppress our answer this time. 783 // If the requester's indicated TTL is greater than the TTL we believe, 784 // then that's okay, and we don't need to do anything about it. 785 // (If two responders on the network are offering the same information, 786 // that's okay, and if they are offering the information with different TTLs, 787 // the one offering the lower TTL should defer to the one offering the higher TTL.) 788 return (mDNSBool)(ka->resrec.rroriginalttl >= rr->resrec.rroriginalttl / 2); 789 } 790 791 mDNSlocal void SetNextAnnounceProbeTime(mDNS *const m, const AuthRecord *const rr) 792 { 793 if (rr->resrec.RecordType == kDNSRecordTypeUnique) 794 { 795 if ((rr->LastAPTime + rr->ThisAPInterval) - m->timenow > mDNSPlatformOneSecond * 10) 796 { 797 LogMsg("SetNextAnnounceProbeTime: ProbeCount %d Next in %d %s", rr->ProbeCount, (rr->LastAPTime + rr->ThisAPInterval) - m->timenow, ARDisplayString(m, rr)); 798 LogMsg("SetNextAnnounceProbeTime: m->SuppressProbes %d m->timenow %d diff %d", m->SuppressProbes, m->timenow, m->SuppressProbes - m->timenow); 799 } 800 if (m->NextScheduledProbe - (rr->LastAPTime + rr->ThisAPInterval) >= 0) 801 m->NextScheduledProbe = (rr->LastAPTime + rr->ThisAPInterval); 802 // Some defensive code: 803 // If (rr->LastAPTime + rr->ThisAPInterval) happens to be far in the past, we don't want to allow 804 // NextScheduledProbe to be set excessively in the past, because that can cause bad things to happen. 805 // See: <rdar://problem/7795434> mDNS: Sometimes advertising stops working and record interval is set to zero 806 if (m->NextScheduledProbe - m->timenow < 0) 807 m->NextScheduledProbe = m->timenow; 808 } 809 else if (rr->AnnounceCount && (ResourceRecordIsValidAnswer(rr) || rr->resrec.RecordType == kDNSRecordTypeDeregistering)) 810 { 811 if (m->NextScheduledResponse - (rr->LastAPTime + rr->ThisAPInterval) >= 0) 812 m->NextScheduledResponse = (rr->LastAPTime + rr->ThisAPInterval); 813 } 814 } 815 816 mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr) 817 { 818 // For reverse-mapping Sleep Proxy PTR records, probe interval is one second 819 rr->ThisAPInterval = rr->AddressProxy.type ? mDNSPlatformOneSecond : DefaultAPIntervalForRecordType(rr->resrec.RecordType); 820 821 // * If this is a record type that's going to probe, then we use the m->SuppressProbes time. 822 // * Otherwise, if it's not going to probe, but m->SuppressProbes is set because we have other 823 // records that are going to probe, then we delay its first announcement so that it will 824 // go out synchronized with the first announcement for the other records that *are* probing. 825 // This is a minor performance tweak that helps keep groups of related records synchronized together. 826 // The addition of "interval / 2" is to make sure that, in the event that any of the probes are 827 // delayed by a few milliseconds, this announcement does not inadvertently go out *before* the probing is complete. 828 // When the probing is complete and those records begin to announce, these records will also be picked up and accelerated, 829 // because they will meet the criterion of being at least half-way to their scheduled announcement time. 830 // * If it's not going to probe and m->SuppressProbes is not already set then we should announce immediately. 831 832 if (rr->ProbeCount) 833 { 834 // If we have no probe suppression time set, or it is in the past, set it now 835 if (m->SuppressProbes == 0 || m->SuppressProbes - m->timenow < 0) 836 { 837 // To allow us to aggregate probes when a group of services are registered together, 838 // the first probe is delayed 1/4 second. This means the common-case behaviour is: 839 // 1/4 second wait; probe 840 // 1/4 second wait; probe 841 // 1/4 second wait; probe 842 // 1/4 second wait; announce (i.e. service is normally announced exactly one second after being registered) 843 m->SuppressProbes = NonZeroTime(m->timenow + DefaultProbeIntervalForTypeUnique/2 + mDNSRandom(DefaultProbeIntervalForTypeUnique/2)); 844 845 // If we already have a *probe* scheduled to go out sooner, then use that time to get better aggregation 846 if (m->SuppressProbes - m->NextScheduledProbe >= 0) 847 m->SuppressProbes = NonZeroTime(m->NextScheduledProbe); 848 if (m->SuppressProbes - m->timenow < 0) // Make sure we don't set m->SuppressProbes excessively in the past 849 m->SuppressProbes = m->timenow; 850 851 // If we already have a *query* scheduled to go out sooner, then use that time to get better aggregation 852 if (m->SuppressProbes - m->NextScheduledQuery >= 0) 853 m->SuppressProbes = NonZeroTime(m->NextScheduledQuery); 854 if (m->SuppressProbes - m->timenow < 0) // Make sure we don't set m->SuppressProbes excessively in the past 855 m->SuppressProbes = m->timenow; 856 857 // except... don't expect to be able to send before the m->SuppressSending timer fires 858 if (m->SuppressSending && m->SuppressProbes - m->SuppressSending < 0) 859 m->SuppressProbes = NonZeroTime(m->SuppressSending); 860 861 if (m->SuppressProbes - m->timenow > mDNSPlatformOneSecond * 8) 862 { 863 LogMsg("InitializeLastAPTime ERROR m->SuppressProbes %d m->NextScheduledProbe %d m->NextScheduledQuery %d m->SuppressSending %d %d", 864 m->SuppressProbes - m->timenow, 865 m->NextScheduledProbe - m->timenow, 866 m->NextScheduledQuery - m->timenow, 867 m->SuppressSending, 868 m->SuppressSending - m->timenow); 869 m->SuppressProbes = NonZeroTime(m->timenow + DefaultProbeIntervalForTypeUnique/2 + mDNSRandom(DefaultProbeIntervalForTypeUnique/2)); 870 } 871 } 872 rr->LastAPTime = m->SuppressProbes - rr->ThisAPInterval; 873 } 874 else if (m->SuppressProbes && m->SuppressProbes - m->timenow >= 0) 875 rr->LastAPTime = m->SuppressProbes - rr->ThisAPInterval + DefaultProbeIntervalForTypeUnique * DefaultProbeCountForTypeUnique + rr->ThisAPInterval / 2; 876 else 877 rr->LastAPTime = m->timenow - rr->ThisAPInterval; 878 879 // For reverse-mapping Sleep Proxy PTR records we don't want to start probing instantly -- we 880 // wait one second to give the client a chance to go to sleep, and then start our ARP/NDP probing. 881 // After three probes one second apart with no answer, we conclude the client is now sleeping 882 // and we can begin broadcasting our announcements to take over ownership of that IP address. 883 // If we don't wait for the client to go to sleep, then when the client sees our ARP Announcements there's a risk 884 // (depending on the OS and networking stack it's using) that it might interpret it as a conflict and change its IP address. 885 if (rr->AddressProxy.type) 886 rr->LastAPTime = m->timenow; 887 888 // Set LastMCTime to now, to inhibit multicast responses 889 // (no need to send additional multicast responses when we're announcing anyway) 890 rr->LastMCTime = m->timenow; 891 rr->LastMCInterface = mDNSInterfaceMark; 892 893 SetNextAnnounceProbeTime(m, rr); 894 } 895 896 mDNSlocal const domainname *SetUnicastTargetToHostName(mDNS *const m, AuthRecord *rr) 897 { 898 const domainname *target; 899 if (rr->AutoTarget) 900 { 901 // For autotunnel services pointing at our IPv6 ULA we don't need or want a NAT mapping, but for all other 902 // advertised services referencing our uDNS hostname, we want NAT mappings automatically created as appropriate, 903 // with the port number in our advertised SRV record automatically tracking the external mapped port. 904 DomainAuthInfo *AuthInfo = GetAuthInfoForName_internal(m, rr->resrec.name); 905 if (!AuthInfo || !AuthInfo->AutoTunnel) rr->AutoTarget = Target_AutoHostAndNATMAP; 906 } 907 908 target = GetServiceTarget(m, rr); 909 if (!target || target->c[0] == 0) 910 { 911 // defer registration until we've got a target 912 LogInfo("SetUnicastTargetToHostName No target for %s", ARDisplayString(m, rr)); 913 rr->state = regState_NoTarget; 914 return mDNSNULL; 915 } 916 else 917 { 918 LogInfo("SetUnicastTargetToHostName target %##s for resource record %s", target->c, ARDisplayString(m,rr)); 919 return target; 920 } 921 } 922 923 // Right now this only applies to mDNS (.local) services where the target host is always m->MulticastHostname 924 // Eventually we should unify this with GetServiceTarget() in uDNS.c 925 mDNSlocal void SetTargetToHostName(mDNS *const m, AuthRecord *const rr) 926 { 927 domainname *const target = GetRRDomainNameTarget(&rr->resrec); 928 const domainname *newname = &m->MulticastHostname; 929 930 if (!target) LogInfo("SetTargetToHostName: Don't know how to set the target of rrtype %s", DNSTypeName(rr->resrec.rrtype)); 931 932 if (!(rr->ForceMCast || rr->ARType == AuthRecordLocalOnly || rr->ARType == AuthRecordP2P || IsLocalDomain(&rr->namestorage))) 933 { 934 const domainname *const n = SetUnicastTargetToHostName(m, rr); 935 if (n) newname = n; 936 else { target->c[0] = 0; SetNewRData(&rr->resrec, mDNSNULL, 0); return; } 937 } 938 939 if (target && SameDomainName(target, newname)) 940 debugf("SetTargetToHostName: Target of %##s is already %##s", rr->resrec.name->c, target->c); 941 942 if (target && !SameDomainName(target, newname)) 943 { 944 AssignDomainName(target, newname); 945 SetNewRData(&rr->resrec, mDNSNULL, 0); // Update rdlength, rdestimate, rdatahash 946 947 // If we're in the middle of probing this record, we need to start again, 948 // because changing its rdata may change the outcome of the tie-breaker. 949 // (If the record type is kDNSRecordTypeUnique (unconfirmed unique) then DefaultProbeCountForRecordType is non-zero.) 950 rr->ProbeCount = DefaultProbeCountForRecordType(rr->resrec.RecordType); 951 952 // If we've announced this record, we really should send a goodbye packet for the old rdata before 953 // changing to the new rdata. However, in practice, we only do SetTargetToHostName for unique records, 954 // so when we announce them we'll set the kDNSClass_UniqueRRSet and clear any stale data that way. 955 if (rr->RequireGoodbye && rr->resrec.RecordType == kDNSRecordTypeShared) 956 debugf("Have announced shared record %##s (%s) at least once: should have sent a goodbye packet before updating", 957 rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 958 959 rr->AnnounceCount = InitialAnnounceCount; 960 rr->RequireGoodbye = mDNSfalse; 961 rr->ProbeRestartCount = 0; 962 InitializeLastAPTime(m, rr); 963 } 964 } 965 966 mDNSlocal void AcknowledgeRecord(mDNS *const m, AuthRecord *const rr) 967 { 968 if (rr->RecordCallback) 969 { 970 // CAUTION: MUST NOT do anything more with rr after calling rr->Callback(), because the client's callback function 971 // is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc. 972 rr->Acknowledged = mDNStrue; 973 mDNS_DropLockBeforeCallback(); // Allow client to legally make mDNS API calls from the callback 974 rr->RecordCallback(m, rr, mStatus_NoError); 975 mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again 976 } 977 } 978 979 mDNSexport void ActivateUnicastRegistration(mDNS *const m, AuthRecord *const rr) 980 { 981 // Make sure that we don't activate the SRV record and associated service records, if it is in 982 // NoTarget state. First time when a service is being instantiated, SRV record may be in NoTarget state. 983 // We should not activate any of the other reords (PTR, TXT) that are part of the service. When 984 // the target becomes available, the records will be reregistered. 985 if (rr->resrec.rrtype != kDNSType_SRV) 986 { 987 AuthRecord *srvRR = mDNSNULL; 988 if (rr->resrec.rrtype == kDNSType_PTR) 989 srvRR = rr->Additional1; 990 else if (rr->resrec.rrtype == kDNSType_TXT) 991 srvRR = rr->DependentOn; 992 if (srvRR) 993 { 994 if (srvRR->resrec.rrtype != kDNSType_SRV) 995 { 996 LogMsg("ActivateUnicastRegistration: ERROR!! Resource record %s wrong, expecting SRV type", ARDisplayString(m, srvRR)); 997 } 998 else 999 { 1000 LogInfo("ActivateUnicastRegistration: Found Service Record %s in state %d for %##s (%s)", 1001 ARDisplayString(m, srvRR), srvRR->state, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 1002 rr->state = srvRR->state; 1003 } 1004 } 1005 } 1006 1007 if (rr->state == regState_NoTarget) 1008 { 1009 LogInfo("ActivateUnicastRegistration record %s in regState_NoTarget, not activating", ARDisplayString(m, rr)); 1010 return; 1011 } 1012 // When we wake up from sleep, we call ActivateUnicastRegistration. It is possible that just before we went to sleep, 1013 // the service/record was being deregistered. In that case, we should not try to register again. For the cases where 1014 // the records are deregistered due to e.g., no target for the SRV record, we would have returned from above if it 1015 // was already in NoTarget state. If it was in the process of deregistration but did not complete fully before we went 1016 // 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. 1017 if (rr->resrec.RecordType == kDNSRecordTypeDeregistering) 1018 { 1019 LogInfo("ActivateUnicastRegistration: Resource record %s, current state %d, moving to DeregPending", ARDisplayString(m, rr), rr->state); 1020 rr->state = regState_DeregPending; 1021 } 1022 else 1023 { 1024 LogInfo("ActivateUnicastRegistration: Resource record %s, current state %d, moving to Pending", ARDisplayString(m, rr), rr->state); 1025 rr->state = regState_Pending; 1026 } 1027 rr->ProbeCount = 0; 1028 rr->ProbeRestartCount = 0; 1029 rr->AnnounceCount = 0; 1030 rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL; 1031 rr->LastAPTime = m->timenow - rr->ThisAPInterval; 1032 rr->expire = 0; // Forget about all the leases, start fresh 1033 rr->uselease = mDNStrue; 1034 rr->updateid = zeroID; 1035 rr->SRVChanged = mDNSfalse; 1036 rr->updateError = mStatus_NoError; 1037 // RestartRecordGetZoneData calls this function whenever a new interface gets registered with core. 1038 // The records might already be registered with the server and hence could have NAT state. 1039 if (rr->NATinfo.clientContext) 1040 { 1041 mDNS_StopNATOperation_internal(m, &rr->NATinfo); 1042 rr->NATinfo.clientContext = mDNSNULL; 1043 } 1044 if (rr->nta) { CancelGetZoneData(m, rr->nta); rr->nta = mDNSNULL; } 1045 if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; } 1046 if (m->NextuDNSEvent - (rr->LastAPTime + rr->ThisAPInterval) >= 0) 1047 m->NextuDNSEvent = (rr->LastAPTime + rr->ThisAPInterval); 1048 } 1049 1050 // Two records qualify to be local duplicates if: 1051 // (a) the RecordTypes are the same, or 1052 // (b) one is Unique and the other Verified 1053 // (c) either is in the process of deregistering 1054 #define RecordLDT(A,B) ((A)->resrec.RecordType == (B)->resrec.RecordType || \ 1055 ((A)->resrec.RecordType | (B)->resrec.RecordType) == (kDNSRecordTypeUnique | kDNSRecordTypeVerified) || \ 1056 ((A)->resrec.RecordType == kDNSRecordTypeDeregistering || (B)->resrec.RecordType == kDNSRecordTypeDeregistering)) 1057 1058 #define RecordIsLocalDuplicate(A,B) \ 1059 ((A)->resrec.InterfaceID == (B)->resrec.InterfaceID && RecordLDT((A),(B)) && IdenticalResourceRecord(& (A)->resrec, & (B)->resrec)) 1060 1061 mDNSlocal AuthRecord *CheckAuthIdenticalRecord(AuthHash *r, AuthRecord *rr) 1062 { 1063 AuthGroup *a; 1064 AuthGroup **ag = &a; 1065 AuthRecord **rp; 1066 const mDNSu32 slot = AuthHashSlot(rr->resrec.name); 1067 1068 a = AuthGroupForRecord(r, slot, &rr->resrec); 1069 if (!a) return mDNSNULL; 1070 rp = &(*ag)->members; 1071 while (*rp) 1072 { 1073 if (!RecordIsLocalDuplicate(*rp, rr)) 1074 rp=&(*rp)->next; 1075 else 1076 { 1077 if ((*rp)->resrec.RecordType == kDNSRecordTypeDeregistering) 1078 { 1079 (*rp)->AnnounceCount = 0; 1080 rp=&(*rp)->next; 1081 } 1082 else return *rp; 1083 } 1084 } 1085 return (mDNSNULL); 1086 } 1087 1088 mDNSlocal mDNSBool CheckAuthRecordConflict(AuthHash *r, AuthRecord *rr) 1089 { 1090 AuthGroup *a; 1091 AuthGroup **ag = &a; 1092 AuthRecord **rp; 1093 const mDNSu32 slot = AuthHashSlot(rr->resrec.name); 1094 1095 a = AuthGroupForRecord(r, slot, &rr->resrec); 1096 if (!a) return mDNSfalse; 1097 rp = &(*ag)->members; 1098 while (*rp) 1099 { 1100 const AuthRecord *s1 = rr->RRSet ? rr->RRSet : rr; 1101 const AuthRecord *s2 = (*rp)->RRSet ? (*rp)->RRSet : *rp; 1102 if (s1 != s2 && SameResourceRecordSignature((*rp), rr) && !IdenticalSameNameRecord(&(*rp)->resrec, &rr->resrec)) 1103 return mDNStrue; 1104 else 1105 rp=&(*rp)->next; 1106 } 1107 return (mDNSfalse); 1108 } 1109 1110 // checks to see if "rr" is already present 1111 mDNSlocal AuthRecord *CheckAuthSameRecord(AuthHash *r, AuthRecord *rr) 1112 { 1113 AuthGroup *a; 1114 AuthGroup **ag = &a; 1115 AuthRecord **rp; 1116 const mDNSu32 slot = AuthHashSlot(rr->resrec.name); 1117 1118 a = AuthGroupForRecord(r, slot, &rr->resrec); 1119 if (!a) return mDNSNULL; 1120 rp = &(*ag)->members; 1121 while (*rp) 1122 { 1123 if (*rp != rr) 1124 rp=&(*rp)->next; 1125 else 1126 { 1127 return *rp; 1128 } 1129 } 1130 return (mDNSNULL); 1131 } 1132 1133 1134 mDNSlocal void DecrementAutoTargetServices(mDNS *const m, AuthRecord *const rr) 1135 { 1136 if (!AuthRecord_uDNS(rr) && rr->resrec.rrtype == kDNSType_SRV && rr->AutoTarget == Target_AutoHost) 1137 { 1138 m->AutoTargetServices--; 1139 LogInfo("DecrementAutoTargetServices: AutoService Record %s, AutoTargetServices %d", ARDisplayString(m, rr), m->AutoTargetServices); 1140 if (!m->AutoTargetServices) 1141 DeadvertiseAllInterfaceRecords(m); 1142 } 1143 } 1144 1145 mDNSlocal void IncrementAutoTargetServices(mDNS *const m, AuthRecord *const rr) 1146 { 1147 if (!AuthRecord_uDNS(rr) && rr->resrec.rrtype == kDNSType_SRV && rr->AutoTarget == Target_AutoHost) 1148 { 1149 int count = m->AutoTargetServices; 1150 1151 // Bump up before calling AdvertiseAllInterfaceRecords. AdvertiseInterface 1152 // returns without doing anything if the count is zero. 1153 m->AutoTargetServices++; 1154 LogInfo("IncrementAutoTargetServices: AutoService Record %s, AutoTargetServices %d", ARDisplayString(m, rr), m->AutoTargetServices); 1155 if (!count) 1156 AdvertiseAllInterfaceRecords(m); 1157 } 1158 } 1159 1160 mDNSlocal void getKeepaliveRaddr(mDNS *const m, AuthRecord *rr, mDNSAddr *raddr) 1161 { 1162 mDNSAddr laddr; 1163 mDNSEthAddr eth; 1164 mDNSIPPort lport, rport; 1165 mDNSu32 timeout, seq, ack; 1166 mDNSu16 win; 1167 1168 if (mDNS_KeepaliveRecord(&rr->resrec)) 1169 { 1170 mDNS_ExtractKeepaliveInfo(rr, &timeout, &laddr, raddr, ð, &seq, &ack, &lport, &rport, &win); 1171 if (!timeout || mDNSAddressIsZero(&laddr) || mDNSAddressIsZero(raddr) || mDNSIPPortIsZero(lport) || mDNSIPPortIsZero(rport)) 1172 { 1173 LogMsg("getKeepaliveRaddr: not a valid record %s for keepalive %#a:%d %#a:%d", ARDisplayString(m, rr), &laddr, lport.NotAnInteger, raddr, rport.NotAnInteger); 1174 return; 1175 } 1176 } 1177 } 1178 1179 // Exported so uDNS.c can call this 1180 mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr) 1181 { 1182 domainname *target = GetRRDomainNameTarget(&rr->resrec); 1183 AuthRecord *r; 1184 AuthRecord **p = &m->ResourceRecords; 1185 AuthRecord **d = &m->DuplicateRecords; 1186 1187 if ((mDNSs32)rr->resrec.rroriginalttl <= 0) 1188 { LogMsg("mDNS_Register_internal: TTL %X should be 1 - 0x7FFFFFFF %s", rr->resrec.rroriginalttl, ARDisplayString(m, rr)); return(mStatus_BadParamErr); } 1189 1190 if (!rr->resrec.RecordType) 1191 { LogMsg("mDNS_Register_internal: RecordType must be non-zero %s", ARDisplayString(m, rr)); return(mStatus_BadParamErr); } 1192 1193 if (m->ShutdownTime) 1194 { LogMsg("mDNS_Register_internal: Shutting down, can't register %s", ARDisplayString(m, rr)); return(mStatus_ServiceNotRunning); } 1195 1196 if (m->DivertMulticastAdvertisements && !AuthRecord_uDNS(rr)) 1197 { 1198 mDNSInterfaceID previousID = rr->resrec.InterfaceID; 1199 if (rr->resrec.InterfaceID == mDNSInterface_Any || rr->resrec.InterfaceID == mDNSInterface_P2P) 1200 { 1201 rr->resrec.InterfaceID = mDNSInterface_LocalOnly; 1202 rr->ARType = AuthRecordLocalOnly; 1203 } 1204 if (rr->resrec.InterfaceID != mDNSInterface_LocalOnly) 1205 { 1206 NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID); 1207 if (intf && !intf->Advertise) { rr->resrec.InterfaceID = mDNSInterface_LocalOnly; rr->ARType = AuthRecordLocalOnly; } 1208 } 1209 if (rr->resrec.InterfaceID != previousID) 1210 LogInfo("mDNS_Register_internal: Diverting record to local-only %s", ARDisplayString(m, rr)); 1211 } 1212 1213 if (RRLocalOnly(rr)) 1214 { 1215 if (CheckAuthSameRecord(&m->rrauth, rr)) 1216 { 1217 LogMsg("mDNS_Register_internal: ERROR!! Tried to register LocalOnly AuthRecord %p %##s (%s) that's already in the list", 1218 rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 1219 return(mStatus_AlreadyRegistered); 1220 } 1221 } 1222 else 1223 { 1224 while (*p && *p != rr) p=&(*p)->next; 1225 if (*p) 1226 { 1227 LogMsg("mDNS_Register_internal: ERROR!! Tried to register AuthRecord %p %##s (%s) that's already in the list", 1228 rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 1229 return(mStatus_AlreadyRegistered); 1230 } 1231 } 1232 1233 while (*d && *d != rr) d=&(*d)->next; 1234 if (*d) 1235 { 1236 LogMsg("mDNS_Register_internal: ERROR!! Tried to register AuthRecord %p %##s (%s) that's already in the Duplicate list", 1237 rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 1238 return(mStatus_AlreadyRegistered); 1239 } 1240 1241 if (rr->DependentOn) 1242 { 1243 if (rr->resrec.RecordType == kDNSRecordTypeUnique) 1244 rr->resrec.RecordType = kDNSRecordTypeVerified; 1245 else 1246 { 1247 LogMsg("mDNS_Register_internal: ERROR! %##s (%s): rr->DependentOn && RecordType != kDNSRecordTypeUnique", 1248 rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 1249 return(mStatus_Invalid); 1250 } 1251 if (!(rr->DependentOn->resrec.RecordType & (kDNSRecordTypeUnique | kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique))) 1252 { 1253 LogMsg("mDNS_Register_internal: ERROR! %##s (%s): rr->DependentOn->RecordType bad type %X", 1254 rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->DependentOn->resrec.RecordType); 1255 return(mStatus_Invalid); 1256 } 1257 } 1258 1259 rr->next = mDNSNULL; 1260 1261 // Field Group 1: The actual information pertaining to this resource record 1262 // Set up by client prior to call 1263 1264 // Field Group 2: Persistent metadata for Authoritative Records 1265 // rr->Additional1 = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client 1266 // rr->Additional2 = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client 1267 // rr->DependentOn = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client 1268 // rr->RRSet = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client 1269 // rr->Callback = already set in mDNS_SetupResourceRecord 1270 // rr->Context = already set in mDNS_SetupResourceRecord 1271 // rr->RecordType = already set in mDNS_SetupResourceRecord 1272 // rr->HostTarget = set to mDNSfalse in mDNS_SetupResourceRecord; may be overridden by client 1273 // rr->AllowRemoteQuery = set to mDNSfalse in mDNS_SetupResourceRecord; may be overridden by client 1274 // Make sure target is not uninitialized data, or we may crash writing debugging log messages 1275 if (rr->AutoTarget && target) target->c[0] = 0; 1276 1277 // Field Group 3: Transient state for Authoritative Records 1278 rr->Acknowledged = mDNSfalse; 1279 rr->ProbeCount = DefaultProbeCountForRecordType(rr->resrec.RecordType); 1280 rr->ProbeRestartCount = 0; 1281 rr->AnnounceCount = InitialAnnounceCount; 1282 rr->RequireGoodbye = mDNSfalse; 1283 rr->AnsweredLocalQ = mDNSfalse; 1284 rr->IncludeInProbe = mDNSfalse; 1285 rr->ImmedUnicast = mDNSfalse; 1286 rr->SendNSECNow = mDNSNULL; 1287 rr->ImmedAnswer = mDNSNULL; 1288 rr->ImmedAdditional = mDNSNULL; 1289 rr->SendRNow = mDNSNULL; 1290 rr->v4Requester = zerov4Addr; 1291 rr->v6Requester = zerov6Addr; 1292 rr->NextResponse = mDNSNULL; 1293 rr->NR_AnswerTo = mDNSNULL; 1294 rr->NR_AdditionalTo = mDNSNULL; 1295 if (!rr->AutoTarget) InitializeLastAPTime(m, rr); 1296 // rr->LastAPTime = Set for us in InitializeLastAPTime() 1297 // rr->LastMCTime = Set for us in InitializeLastAPTime() 1298 // rr->LastMCInterface = Set for us in InitializeLastAPTime() 1299 rr->NewRData = mDNSNULL; 1300 rr->newrdlength = 0; 1301 rr->UpdateCallback = mDNSNULL; 1302 rr->UpdateCredits = kMaxUpdateCredits; 1303 rr->NextUpdateCredit = 0; 1304 rr->UpdateBlocked = 0; 1305 1306 // For records we're holding as proxy (except reverse-mapping PTR records) two announcements is sufficient 1307 if (rr->WakeUp.HMAC.l[0] && !rr->AddressProxy.type) rr->AnnounceCount = 2; 1308 1309 // Field Group 4: Transient uDNS state for Authoritative Records 1310 rr->state = regState_Zero; 1311 rr->uselease = 0; 1312 rr->expire = 0; 1313 rr->Private = 0; 1314 rr->updateid = zeroID; 1315 rr->updateIntID = zeroOpaque64; 1316 rr->zone = rr->resrec.name; 1317 rr->nta = mDNSNULL; 1318 rr->tcp = mDNSNULL; 1319 rr->OrigRData = 0; 1320 rr->OrigRDLen = 0; 1321 rr->InFlightRData = 0; 1322 rr->InFlightRDLen = 0; 1323 rr->QueuedRData = 0; 1324 rr->QueuedRDLen = 0; 1325 //mDNSPlatformMemZero(&rr->NATinfo, sizeof(rr->NATinfo)); 1326 // We should be recording the actual internal port for this service record here. Once we initiate our NAT mapping 1327 // request we'll subsequently overwrite srv.port with the allocated external NAT port -- potentially multiple 1328 // times with different values if the external NAT port changes during the lifetime of the service registration. 1329 //if (rr->resrec.rrtype == kDNSType_SRV) rr->NATinfo.IntPort = rr->resrec.rdata->u.srv.port; 1330 1331 // rr->resrec.interface = already set in mDNS_SetupResourceRecord 1332 // rr->resrec.name->c = MUST be set by client 1333 // rr->resrec.rrtype = already set in mDNS_SetupResourceRecord 1334 // rr->resrec.rrclass = already set in mDNS_SetupResourceRecord 1335 // rr->resrec.rroriginalttl = already set in mDNS_SetupResourceRecord 1336 // rr->resrec.rdata = MUST be set by client, unless record type is CNAME or PTR and rr->HostTarget is set 1337 1338 // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct, 1339 // since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s". 1340 // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here. 1341 if (rr->resrec.rrtype == kDNSType_TXT && rr->resrec.rdlength == 0) { rr->resrec.rdlength = 1; rr->resrec.rdata->u.txt.c[0] = 0; } 1342 1343 if (rr->AutoTarget) 1344 { 1345 SetTargetToHostName(m, rr); // Also sets rdlength and rdestimate for us, and calls InitializeLastAPTime(); 1346 #ifndef UNICAST_DISABLED 1347 // If we have no target record yet, SetTargetToHostName will set rr->state == regState_NoTarget 1348 // 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. 1349 if (rr->state == regState_NoTarget) 1350 { 1351 // Initialize the target so that we don't crash while logging etc. 1352 domainname *tar = GetRRDomainNameTarget(&rr->resrec); 1353 if (tar) tar->c[0] = 0; 1354 LogInfo("mDNS_Register_internal: record %s in NoTarget state", ARDisplayString(m, rr)); 1355 } 1356 #endif 1357 } 1358 else 1359 { 1360 rr->resrec.rdlength = GetRDLength(&rr->resrec, mDNSfalse); 1361 rr->resrec.rdestimate = GetRDLength(&rr->resrec, mDNStrue); 1362 } 1363 1364 if (!ValidateDomainName(rr->resrec.name)) 1365 { LogMsg("Attempt to register record with invalid name: %s", ARDisplayString(m, rr)); return(mStatus_Invalid); } 1366 1367 // Don't do this until *after* we've set rr->resrec.rdlength 1368 if (!ValidateRData(rr->resrec.rrtype, rr->resrec.rdlength, rr->resrec.rdata)) 1369 { LogMsg("Attempt to register record with invalid rdata: %s", ARDisplayString(m, rr)); return(mStatus_Invalid); } 1370 1371 rr->resrec.namehash = DomainNameHashValue(rr->resrec.name); 1372 rr->resrec.rdatahash = target ? DomainNameHashValue(target) : RDataHashValue(&rr->resrec); 1373 1374 if (RRLocalOnly(rr)) 1375 { 1376 // If this is supposed to be unique, make sure we don't have any name conflicts. 1377 // If we found a conflict, we may still want to insert the record in the list but mark it appropriately 1378 // (kDNSRecordTypeDeregistering) so that we deliver RMV events to the application. But this causes more 1379 // complications and not clear whether there are any benefits. See rdar:9304275 for details. 1380 // Hence, just bail out. 1381 if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask) 1382 { 1383 if (CheckAuthRecordConflict(&m->rrauth, rr)) 1384 { 1385 LogInfo("mDNS_Register_internal: Name conflict %s (%p), InterfaceID %p", ARDisplayString(m, rr), rr, rr->resrec.InterfaceID); 1386 return mStatus_NameConflict; 1387 } 1388 } 1389 } 1390 1391 // For uDNS records, we don't support duplicate checks at this time. 1392 #ifndef UNICAST_DISABLED 1393 if (AuthRecord_uDNS(rr)) 1394 { 1395 if (!m->NewLocalRecords) m->NewLocalRecords = rr; 1396 // When we called SetTargetToHostName, it may have caused mDNS_Register_internal to be re-entered, appending new 1397 // 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. 1398 // Note that for AutoTunnel this should never happen, but this check makes the code future-proof. 1399 while (*p) p=&(*p)->next; 1400 *p = rr; 1401 if (rr->resrec.RecordType == kDNSRecordTypeUnique) rr->resrec.RecordType = kDNSRecordTypeVerified; 1402 rr->ProbeCount = 0; 1403 rr->ProbeRestartCount = 0; 1404 rr->AnnounceCount = 0; 1405 if (rr->state != regState_NoTarget) ActivateUnicastRegistration(m, rr); 1406 return(mStatus_NoError); // <--- Note: For unicast records, code currently bails out at this point 1407 } 1408 #endif 1409 1410 // Now that we've finished building our new record, make sure it's not identical to one we already have 1411 if (RRLocalOnly(rr)) 1412 { 1413 rr->ProbeCount = 0; 1414 rr->ProbeRestartCount = 0; 1415 rr->AnnounceCount = 0; 1416 r = CheckAuthIdenticalRecord(&m->rrauth, rr); 1417 } 1418 else 1419 { 1420 for (r = m->ResourceRecords; r; r=r->next) 1421 if (RecordIsLocalDuplicate(r, rr)) 1422 { 1423 if (r->resrec.RecordType == kDNSRecordTypeDeregistering) r->AnnounceCount = 0; 1424 else break; 1425 } 1426 } 1427 1428 if (r) 1429 { 1430 debugf("mDNS_Register_internal:Adding to duplicate list %s", ARDisplayString(m,rr)); 1431 *d = rr; 1432 // If the previous copy of this record is already verified unique, 1433 // then indicate that we should move this record promptly to kDNSRecordTypeUnique state. 1434 // Setting ProbeCount to zero will cause SendQueries() to advance this record to 1435 // kDNSRecordTypeVerified state and call the client callback at the next appropriate time. 1436 if (rr->resrec.RecordType == kDNSRecordTypeUnique && r->resrec.RecordType == kDNSRecordTypeVerified) 1437 rr->ProbeCount = 0; 1438 } 1439 else 1440 { 1441 debugf("mDNS_Register_internal: Adding to active record list %s", ARDisplayString(m,rr)); 1442 if (RRLocalOnly(rr)) 1443 { 1444 AuthGroup *ag; 1445 ag = InsertAuthRecord(m, &m->rrauth, rr); 1446 if (ag && !ag->NewLocalOnlyRecords) { 1447 m->NewLocalOnlyRecords = mDNStrue; 1448 ag->NewLocalOnlyRecords = rr; 1449 } 1450 // No probing for LocalOnly records, Acknowledge them right away 1451 if (rr->resrec.RecordType == kDNSRecordTypeUnique) rr->resrec.RecordType = kDNSRecordTypeVerified; 1452 AcknowledgeRecord(m, rr); 1453 return(mStatus_NoError); 1454 } 1455 else 1456 { 1457 if (!m->NewLocalRecords) m->NewLocalRecords = rr; 1458 *p = rr; 1459 } 1460 } 1461 1462 // If this is a keepalive record, fetch the MAC address of the remote host. 1463 // This is used by the in-NIC proxy to send the keepalive packets. 1464 if (mDNS_KeepaliveRecord(&rr->resrec)) 1465 { 1466 // Set the record type to known unique to prevent probing keep alive records. 1467 // Also make sure we do not announce the keepalive records. 1468 rr->resrec.RecordType = kDNSRecordTypeKnownUnique; 1469 rr->AnnounceCount = 0; 1470 mDNSAddr raddr; 1471 getKeepaliveRaddr(m, rr, &raddr); 1472 // This is an asynchronous call. Once the remote MAC address is available, helper will schedule an 1473 // asynchronous task to update the resource record 1474 mDNSPlatformGetRemoteMacAddr(m, &raddr); 1475 } 1476 1477 if (!AuthRecord_uDNS(rr)) // This check is superfluous, given that for unicast records we (currently) bail out above 1478 { 1479 // We have inserted the record in the list. See if we have to advertise the A/AAAA,HINFO,PTR records. 1480 IncrementAutoTargetServices(m, rr); 1481 // For records that are not going to probe, acknowledge them right away 1482 if (rr->resrec.RecordType != kDNSRecordTypeUnique && rr->resrec.RecordType != kDNSRecordTypeDeregistering) 1483 AcknowledgeRecord(m, rr); 1484 1485 // Adding a record may affect whether or not we should sleep 1486 mDNS_UpdateAllowSleep(m); 1487 } 1488 1489 return(mStatus_NoError); 1490 } 1491 1492 mDNSlocal void RecordProbeFailure(mDNS *const m, const AuthRecord *const rr) 1493 { 1494 m->ProbeFailTime = m->timenow; 1495 m->NumFailedProbes++; 1496 // If we've had fifteen or more probe failures, rate-limit to one every five seconds. 1497 // If a bunch of hosts have all been configured with the same name, then they'll all 1498 // conflict and run through the same series of names: name-2, name-3, name-4, etc., 1499 // up to name-10. After that they'll start adding random increments in the range 1-100, 1500 // so they're more likely to branch out in the available namespace and settle on a set of 1501 // unique names quickly. If after five more tries the host is still conflicting, then we 1502 // may have a serious problem, so we start rate-limiting so we don't melt down the network. 1503 if (m->NumFailedProbes >= 15) 1504 { 1505 m->SuppressProbes = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 5); 1506 LogMsg("Excessive name conflicts (%lu) for %##s (%s); rate limiting in effect", 1507 m->NumFailedProbes, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 1508 } 1509 } 1510 1511 mDNSlocal void CompleteRDataUpdate(mDNS *const m, AuthRecord *const rr) 1512 { 1513 RData *OldRData = rr->resrec.rdata; 1514 mDNSu16 OldRDLen = rr->resrec.rdlength; 1515 SetNewRData(&rr->resrec, rr->NewRData, rr->newrdlength); // Update our rdata 1516 rr->NewRData = mDNSNULL; // Clear the NewRData pointer ... 1517 if (rr->UpdateCallback) 1518 rr->UpdateCallback(m, rr, OldRData, OldRDLen); // ... and let the client know 1519 } 1520 1521 // Note: mDNS_Deregister_internal can call a user callback, which may change the record list and/or question list. 1522 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this. 1523 // Exported so uDNS.c can call this 1524 mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr, mDNS_Dereg_type drt) 1525 { 1526 AuthRecord *r2; 1527 mDNSu8 RecordType = rr->resrec.RecordType; 1528 AuthRecord **p = &m->ResourceRecords; // Find this record in our list of active records 1529 mDNSBool dupList = mDNSfalse; 1530 1531 if (RRLocalOnly(rr)) 1532 { 1533 AuthGroup *a; 1534 AuthGroup **ag = &a; 1535 AuthRecord **rp; 1536 const mDNSu32 slot = AuthHashSlot(rr->resrec.name); 1537 1538 a = AuthGroupForRecord(&m->rrauth, slot, &rr->resrec); 1539 if (!a) return mDNSfalse; 1540 rp = &(*ag)->members; 1541 while (*rp && *rp != rr) rp=&(*rp)->next; 1542 p = rp; 1543 } 1544 else 1545 { 1546 while (*p && *p != rr) p=&(*p)->next; 1547 } 1548 1549 if (*p) 1550 { 1551 // We found our record on the main list. See if there are any duplicates that need special handling. 1552 if (drt == mDNS_Dereg_conflict) // If this was a conflict, see that all duplicates get the same treatment 1553 { 1554 // Scan for duplicates of rr, and mark them for deregistration at the end of this routine, after we've finished 1555 // deregistering rr. We need to do this scan *before* we give the client the chance to free and reuse the rr memory. 1556 for (r2 = m->DuplicateRecords; r2; r2=r2->next) if (RecordIsLocalDuplicate(r2, rr)) r2->ProbeCount = 0xFF; 1557 } 1558 else 1559 { 1560 // Before we delete the record (and potentially send a goodbye packet) 1561 // first see if we have a record on the duplicate list ready to take over from it. 1562 AuthRecord **d = &m->DuplicateRecords; 1563 while (*d && !RecordIsLocalDuplicate(*d, rr)) d=&(*d)->next; 1564 if (*d) 1565 { 1566 AuthRecord *dup = *d; 1567 debugf("mDNS_Register_internal: Duplicate record %p taking over from %p %##s (%s)", 1568 dup, rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 1569 *d = dup->next; // Cut replacement record from DuplicateRecords list 1570 if (RRLocalOnly(rr)) 1571 { 1572 dup->next = mDNSNULL; 1573 if (!InsertAuthRecord(m, &m->rrauth, dup)) LogMsg("mDNS_Deregister_internal: ERROR!! cannot insert %s", ARDisplayString(m, dup)); 1574 } 1575 else 1576 { 1577 dup->next = rr->next; // And then... 1578 rr->next = dup; // ... splice it in right after the record we're about to delete 1579 } 1580 dup->resrec.RecordType = rr->resrec.RecordType; 1581 dup->ProbeCount = rr->ProbeCount; 1582 dup->ProbeRestartCount = rr->ProbeRestartCount; 1583 dup->AnnounceCount = rr->AnnounceCount; 1584 dup->RequireGoodbye = rr->RequireGoodbye; 1585 dup->AnsweredLocalQ = rr->AnsweredLocalQ; 1586 dup->ImmedAnswer = rr->ImmedAnswer; 1587 dup->ImmedUnicast = rr->ImmedUnicast; 1588 dup->ImmedAdditional = rr->ImmedAdditional; 1589 dup->v4Requester = rr->v4Requester; 1590 dup->v6Requester = rr->v6Requester; 1591 dup->ThisAPInterval = rr->ThisAPInterval; 1592 dup->LastAPTime = rr->LastAPTime; 1593 dup->LastMCTime = rr->LastMCTime; 1594 dup->LastMCInterface = rr->LastMCInterface; 1595 dup->Private = rr->Private; 1596 dup->state = rr->state; 1597 rr->RequireGoodbye = mDNSfalse; 1598 rr->AnsweredLocalQ = mDNSfalse; 1599 } 1600 } 1601 } 1602 else 1603 { 1604 // We didn't find our record on the main list; try the DuplicateRecords list instead. 1605 p = &m->DuplicateRecords; 1606 while (*p && *p != rr) p=&(*p)->next; 1607 // If we found our record on the duplicate list, then make sure we don't send a goodbye for it 1608 if (*p) 1609 { 1610 // Duplicate records are not used for sending wakeups or goodbyes. Hence, deregister them 1611 // immediately. When there is a conflict, we deregister all the conflicting duplicate records 1612 // also that have been marked above in this function. In that case, we come here and if we don't 1613 // deregister (unilink from the DuplicateRecords list), we will be recursing infinitely. Hence, 1614 // clear the HMAC which will cause it to deregister. See <rdar://problem/10380988> for 1615 // details. 1616 rr->WakeUp.HMAC = zeroEthAddr; 1617 rr->RequireGoodbye = mDNSfalse; 1618 rr->resrec.RecordType = kDNSRecordTypeDeregistering; 1619 dupList = mDNStrue; 1620 } 1621 if (*p) debugf("mDNS_Deregister_internal: Deleting DuplicateRecord %p %##s (%s)", 1622 rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 1623 } 1624 1625 if (!*p) 1626 { 1627 // No need to log an error message if we already know this is a potentially repeated deregistration 1628 if (drt != mDNS_Dereg_repeat) 1629 LogMsg("mDNS_Deregister_internal: Record %p not found in list %s", rr, ARDisplayString(m,rr)); 1630 return(mStatus_BadReferenceErr); 1631 } 1632 1633 // If this is a shared record and we've announced it at least once, 1634 // we need to retract that announcement before we delete the record 1635 1636 // If this is a record (including mDNSInterface_LocalOnly records) for which we've given local-only answers then 1637 // it's tempting to just do "AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNSfalse)" here, but that would not not be safe. 1638 // The AnswerAllLocalQuestionsWithLocalAuthRecord routine walks the question list invoking client callbacks, using the "m->CurrentQuestion" 1639 // mechanism to cope with the client callback modifying the question list while that's happening. 1640 // However, mDNS_Deregister could have been called from a client callback (e.g. from the domain enumeration callback FoundDomain) 1641 // which means that the "m->CurrentQuestion" mechanism is already in use to protect that list, so we can't use it twice. 1642 // More generally, if we invoke callbacks from within a client callback, then those callbacks could deregister other 1643 // records, thereby invoking yet more callbacks, without limit. 1644 // The solution is to defer delivering the "Remove" events until mDNS_Execute time, just like we do for sending 1645 // actual goodbye packets. 1646 1647 #ifndef UNICAST_DISABLED 1648 if (AuthRecord_uDNS(rr)) 1649 { 1650 if (rr->RequireGoodbye) 1651 { 1652 if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; } 1653 rr->resrec.RecordType = kDNSRecordTypeDeregistering; 1654 m->LocalRemoveEvents = mDNStrue; 1655 uDNS_DeregisterRecord(m, rr); 1656 // At this point unconditionally we bail out 1657 // Either uDNS_DeregisterRecord will have completed synchronously, and called CompleteDeregistration, 1658 // which calls us back here with RequireGoodbye set to false, or it will have initiated the deregistration 1659 // process and will complete asynchronously. Either way we don't need to do anything more here. 1660 return(mStatus_NoError); 1661 } 1662 // Sometimes the records don't complete proper deregistration i.e., don't wait for a response 1663 // from the server. In that case, if the records have been part of a group update, clear the 1664 // state here. Some recors e.g., AutoTunnel gets reused without ever being completely initialized 1665 rr->updateid = zeroID; 1666 1667 // We defer cleaning up NAT state only after sending goodbyes. This is important because 1668 // RecordRegistrationGotZoneData guards against creating NAT state if clientContext is non-NULL. 1669 // This happens today when we turn on/off interface where we get multiple network transitions 1670 // and RestartRecordGetZoneData triggers re-registration of the resource records even though 1671 // they may be in Registered state which causes NAT information to be setup multiple times. Defering 1672 // the cleanup here keeps clientContext non-NULL and hence prevents that. Note that cleaning up 1673 // NAT state here takes care of the case where we did not send goodbyes at all. 1674 if (rr->NATinfo.clientContext) 1675 { 1676 mDNS_StopNATOperation_internal(m, &rr->NATinfo); 1677 rr->NATinfo.clientContext = mDNSNULL; 1678 } 1679 if (rr->nta) { CancelGetZoneData(m, rr->nta); rr->nta = mDNSNULL; } 1680 if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; } 1681 } 1682 #endif // UNICAST_DISABLED 1683 1684 if (RecordType == kDNSRecordTypeUnregistered) 1685 LogMsg("mDNS_Deregister_internal: %s already marked kDNSRecordTypeUnregistered", ARDisplayString(m, rr)); 1686 else if (RecordType == kDNSRecordTypeDeregistering) 1687 { 1688 LogMsg("mDNS_Deregister_internal: %s already marked kDNSRecordTypeDeregistering", ARDisplayString(m, rr)); 1689 return(mStatus_BadReferenceErr); 1690 } 1691 1692 // <rdar://problem/7457925> Local-only questions don't get remove events for unique records 1693 // We may want to consider changing this code so that we generate local-only question "rmv" 1694 // events (and maybe goodbye packets too) for unique records as well as for shared records 1695 // Note: If we change the logic for this "if" statement, need to ensure that the code in 1696 // CompleteDeregistration() sets the appropriate state variables to gaurantee that "else" 1697 // clause will execute here and the record will be cut from the list. 1698 if (rr->WakeUp.HMAC.l[0] || 1699 (RecordType == kDNSRecordTypeShared && (rr->RequireGoodbye || rr->AnsweredLocalQ))) 1700 { 1701 verbosedebugf("mDNS_Deregister_internal: Starting deregistration for %s", ARDisplayString(m, rr)); 1702 rr->resrec.RecordType = kDNSRecordTypeDeregistering; 1703 rr->resrec.rroriginalttl = 0; 1704 rr->AnnounceCount = rr->WakeUp.HMAC.l[0] ? WakeupCount : (drt == mDNS_Dereg_rapid) ? 1 : GoodbyeCount; 1705 rr->ThisAPInterval = mDNSPlatformOneSecond * 2; 1706 rr->LastAPTime = m->timenow - rr->ThisAPInterval; 1707 m->LocalRemoveEvents = mDNStrue; 1708 if (m->NextScheduledResponse - (m->timenow + mDNSPlatformOneSecond/10) >= 0) 1709 m->NextScheduledResponse = (m->timenow + mDNSPlatformOneSecond/10); 1710 } 1711 else 1712 { 1713 if (!dupList && RRLocalOnly(rr)) 1714 { 1715 AuthGroup *ag = RemoveAuthRecord(m, &m->rrauth, rr); 1716 if (ag->NewLocalOnlyRecords == rr) ag->NewLocalOnlyRecords = rr->next; 1717 } 1718 else 1719 { 1720 *p = rr->next; // Cut this record from the list 1721 if (m->NewLocalRecords == rr) m->NewLocalRecords = rr->next; 1722 DecrementAutoTargetServices(m, rr); 1723 } 1724 // If someone is about to look at this, bump the pointer forward 1725 if (m->CurrentRecord == rr) m->CurrentRecord = rr->next; 1726 rr->next = mDNSNULL; 1727 1728 // Should we generate local remove events here? 1729 // i.e. something like: 1730 // if (rr->AnsweredLocalQ) { AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNSfalse); rr->AnsweredLocalQ = mDNSfalse; } 1731 1732 verbosedebugf("mDNS_Deregister_internal: Deleting record for %s", ARDisplayString(m, rr)); 1733 rr->resrec.RecordType = kDNSRecordTypeUnregistered; 1734 1735 if ((drt == mDNS_Dereg_conflict || drt == mDNS_Dereg_repeat) && RecordType == kDNSRecordTypeShared) 1736 debugf("mDNS_Deregister_internal: Cannot have a conflict on a shared record! %##s (%s)", 1737 rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 1738 1739 // If we have an update queued up which never executed, give the client a chance to free that memory 1740 if (rr->NewRData) CompleteRDataUpdate(m, rr); // Update our rdata, clear the NewRData pointer, and return memory to the client 1741 1742 1743 // CAUTION: MUST NOT do anything more with rr after calling rr->Callback(), because the client's callback function 1744 // is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc. 1745 // In this case the likely client action to the mStatus_MemFree message is to free the memory, 1746 // so any attempt to touch rr after this is likely to lead to a crash. 1747 if (drt != mDNS_Dereg_conflict) 1748 { 1749 mDNS_DropLockBeforeCallback(); // Allow client to legally make mDNS API calls from the callback 1750 LogInfo("mDNS_Deregister_internal: mStatus_MemFree for %s", ARDisplayString(m, rr)); 1751 if (rr->RecordCallback) 1752 rr->RecordCallback(m, rr, mStatus_MemFree); // MUST NOT touch rr after this 1753 mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again 1754 } 1755 else 1756 { 1757 RecordProbeFailure(m, rr); 1758 mDNS_DropLockBeforeCallback(); // Allow client to legally make mDNS API calls from the callback 1759 if (rr->RecordCallback) 1760 rr->RecordCallback(m, rr, mStatus_NameConflict); // MUST NOT touch rr after this 1761 mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again 1762 // Now that we've finished deregistering rr, check our DuplicateRecords list for any that we marked previously. 1763 // Note that with all the client callbacks going on, by the time we get here all the 1764 // records we marked may have been explicitly deregistered by the client anyway. 1765 r2 = m->DuplicateRecords; 1766 while (r2) 1767 { 1768 if (r2->ProbeCount != 0xFF) 1769 { 1770 r2 = r2->next; 1771 } 1772 else 1773 { 1774 mDNS_Deregister_internal(m, r2, mDNS_Dereg_conflict); 1775 // As this is a duplicate record, it will be unlinked from the list 1776 // immediately 1777 r2 = m->DuplicateRecords; 1778 } 1779 } 1780 } 1781 } 1782 mDNS_UpdateAllowSleep(m); 1783 return(mStatus_NoError); 1784 } 1785 1786 // *************************************************************************** 1787 #if COMPILER_LIKES_PRAGMA_MARK 1788 #pragma mark - 1789 #pragma mark - Packet Sending Functions 1790 #endif 1791 1792 mDNSlocal void AddRecordToResponseList(AuthRecord ***nrpp, AuthRecord *rr, AuthRecord *add) 1793 { 1794 if (rr->NextResponse == mDNSNULL && *nrpp != &rr->NextResponse) 1795 { 1796 **nrpp = rr; 1797 // NR_AdditionalTo must point to a record with NR_AnswerTo set (and not NR_AdditionalTo) 1798 // If 'add' does not meet this requirement, then follow its NR_AdditionalTo pointer to a record that does 1799 // The referenced record will definitely be acceptable (by recursive application of this rule) 1800 if (add && add->NR_AdditionalTo) add = add->NR_AdditionalTo; 1801 rr->NR_AdditionalTo = add; 1802 *nrpp = &rr->NextResponse; 1803 } 1804 debugf("AddRecordToResponseList: %##s (%s) already in list", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 1805 } 1806 1807 mDNSlocal void AddAdditionalsToResponseList(mDNS *const m, AuthRecord *ResponseRecords, AuthRecord ***nrpp, const mDNSInterfaceID InterfaceID) 1808 { 1809 AuthRecord *rr, *rr2; 1810 for (rr=ResponseRecords; rr; rr=rr->NextResponse) // For each record we plan to put 1811 { 1812 // (Note: This is an "if", not a "while". If we add a record, we'll find it again 1813 // later in the "for" loop, and we will follow further "additional" links then.) 1814 if (rr->Additional1 && ResourceRecordIsValidInterfaceAnswer(rr->Additional1, InterfaceID)) 1815 AddRecordToResponseList(nrpp, rr->Additional1, rr); 1816 1817 if (rr->Additional2 && ResourceRecordIsValidInterfaceAnswer(rr->Additional2, InterfaceID)) 1818 AddRecordToResponseList(nrpp, rr->Additional2, rr); 1819 1820 // For SRV records, automatically add the Address record(s) for the target host 1821 if (rr->resrec.rrtype == kDNSType_SRV) 1822 { 1823 for (rr2=m->ResourceRecords; rr2; rr2=rr2->next) // Scan list of resource records 1824 if (RRTypeIsAddressType(rr2->resrec.rrtype) && // For all address records (A/AAAA) ... 1825 ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) && // ... which are valid for answer ... 1826 rr->resrec.rdatahash == rr2->resrec.namehash && // ... whose name is the name of the SRV target 1827 SameDomainName(&rr->resrec.rdata->u.srv.target, rr2->resrec.name)) 1828 AddRecordToResponseList(nrpp, rr2, rr); 1829 } 1830 else if (RRTypeIsAddressType(rr->resrec.rrtype)) // For A or AAAA, put counterpart as additional 1831 { 1832 for (rr2=m->ResourceRecords; rr2; rr2=rr2->next) // Scan list of resource records 1833 if (RRTypeIsAddressType(rr2->resrec.rrtype) && // For all address records (A/AAAA) ... 1834 ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) && // ... which are valid for answer ... 1835 rr->resrec.namehash == rr2->resrec.namehash && // ... and have the same name 1836 SameDomainName(rr->resrec.name, rr2->resrec.name)) 1837 AddRecordToResponseList(nrpp, rr2, rr); 1838 } 1839 else if (rr->resrec.rrtype == kDNSType_PTR) // For service PTR, see if we want to add DeviceInfo record 1840 { 1841 if (ResourceRecordIsValidInterfaceAnswer(&m->DeviceInfo, InterfaceID) && 1842 SameDomainLabel(rr->resrec.rdata->u.name.c, m->DeviceInfo.resrec.name->c)) 1843 AddRecordToResponseList(nrpp, &m->DeviceInfo, rr); 1844 } 1845 } 1846 } 1847 1848 mDNSlocal int AnonInfoSpace(AnonymousInfo *info) 1849 { 1850 ResourceRecord *rr = info->nsec3RR; 1851 1852 // 2 bytes for compressed name + type (2) class (2) TTL (4) rdlength (2) rdata (n) 1853 return (2 + 10 + rr->rdlength); 1854 } 1855 1856 mDNSlocal void SendDelayedUnicastResponse(mDNS *const m, const mDNSAddr *const dest, const mDNSInterfaceID InterfaceID) 1857 { 1858 AuthRecord *rr; 1859 AuthRecord *ResponseRecords = mDNSNULL; 1860 AuthRecord **nrp = &ResponseRecords; 1861 NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID); 1862 int AnoninfoSpace = 0; 1863 1864 // Make a list of all our records that need to be unicast to this destination 1865 for (rr = m->ResourceRecords; rr; rr=rr->next) 1866 { 1867 // If we find we can no longer unicast this answer, clear ImmedUnicast 1868 if (rr->ImmedAnswer == mDNSInterfaceMark || 1869 mDNSSameIPv4Address(rr->v4Requester, onesIPv4Addr) || 1870 mDNSSameIPv6Address(rr->v6Requester, onesIPv6Addr) ) 1871 rr->ImmedUnicast = mDNSfalse; 1872 1873 if (rr->ImmedUnicast && rr->ImmedAnswer == InterfaceID) 1874 { 1875 if ((dest->type == mDNSAddrType_IPv4 && mDNSSameIPv4Address(rr->v4Requester, dest->ip.v4)) || 1876 (dest->type == mDNSAddrType_IPv6 && mDNSSameIPv6Address(rr->v6Requester, dest->ip.v6))) 1877 { 1878 rr->ImmedAnswer = mDNSNULL; // Clear the state fields 1879 rr->ImmedUnicast = mDNSfalse; 1880 rr->v4Requester = zerov4Addr; 1881 rr->v6Requester = zerov6Addr; 1882 1883 // Only sent records registered for P2P over P2P interfaces 1884 if (intf && !mDNSPlatformValidRecordForInterface(rr, intf)) 1885 { 1886 LogInfo("SendDelayedUnicastResponse: Not sending %s, on %s", ARDisplayString(m, rr), InterfaceNameForID(m, InterfaceID)); 1887 continue; 1888 } 1889 1890 if (rr->NextResponse == mDNSNULL && nrp != &rr->NextResponse) // rr->NR_AnswerTo 1891 { 1892 rr->NR_AnswerTo = NR_AnswerMulticast; 1893 *nrp = rr; 1894 nrp = &rr->NextResponse; 1895 } 1896 } 1897 } 1898 } 1899 1900 AddAdditionalsToResponseList(m, ResponseRecords, &nrp, InterfaceID); 1901 1902 while (ResponseRecords) 1903 { 1904 mDNSu8 *responseptr = m->omsg.data; 1905 mDNSu8 *newptr; 1906 InitializeDNSMessage(&m->omsg.h, zeroID, ResponseFlags); 1907 1908 // Put answers in the packet 1909 while (ResponseRecords && ResponseRecords->NR_AnswerTo) 1910 { 1911 rr = ResponseRecords; 1912 if (rr->resrec.AnonInfo) 1913 { 1914 AnoninfoSpace += AnonInfoSpace(rr->resrec.AnonInfo); 1915 rr->resrec.AnonInfo->SendNow = mDNSInterfaceMark; 1916 } 1917 if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask) 1918 rr->resrec.rrclass |= kDNSClass_UniqueRRSet; // Temporarily set the cache flush bit so PutResourceRecord will set it 1919 1920 // Retract the limit by AnoninfoSpace which we need to put the AnoInfo option. 1921 newptr = PutResourceRecordTTLWithLimit(&m->omsg, responseptr, &m->omsg.h.numAnswers, &rr->resrec, rr->resrec.rroriginalttl, 1922 m->omsg.data + (AllowedRRSpace(&m->omsg) - AnoninfoSpace)); 1923 1924 rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet; // Make sure to clear cache flush bit back to normal state 1925 if (!newptr && m->omsg.h.numAnswers) 1926 { 1927 break; // If packet full, send it now 1928 } 1929 if (newptr) responseptr = newptr; 1930 ResponseRecords = rr->NextResponse; 1931 rr->NextResponse = mDNSNULL; 1932 rr->NR_AnswerTo = mDNSNULL; 1933 rr->NR_AdditionalTo = mDNSNULL; 1934 rr->RequireGoodbye = mDNStrue; 1935 } 1936 1937 // We have reserved the space for AnonInfo option. PutResourceRecord uses the 1938 // standard limit (AllowedRRSpace) and we should have space now. 1939 for (rr = m->ResourceRecords; rr; rr=rr->next) 1940 { 1941 if (rr->resrec.AnonInfo && rr->resrec.AnonInfo->SendNow == mDNSInterfaceMark) 1942 { 1943 ResourceRecord *nsec3RR = rr->resrec.AnonInfo->nsec3RR; 1944 1945 newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAuthorities, nsec3RR); 1946 if (newptr) 1947 { 1948 responseptr = newptr; 1949 debugf("SendDelayedUnicastResponse: Added NSEC3 Record %s on %p", RRDisplayString(m, nsec3RR), intf->InterfaceID); 1950 } 1951 else 1952 { 1953 // We allocated space and we should not fail. Don't break, we need to clear the SendNow flag. 1954 LogMsg("SendDelayedUnicastResponse: ERROR!! Cannot Add NSEC3 Record %s on %p", RRDisplayString(m, nsec3RR), intf->InterfaceID); 1955 } 1956 rr->resrec.AnonInfo->SendNow = mDNSNULL; 1957 } 1958 } 1959 1960 // Add additionals, if there's space 1961 while (ResponseRecords && !ResponseRecords->NR_AnswerTo) 1962 { 1963 rr = ResponseRecords; 1964 if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask) 1965 rr->resrec.rrclass |= kDNSClass_UniqueRRSet; // Temporarily set the cache flush bit so PutResourceRecord will set it 1966 newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAdditionals, &rr->resrec); 1967 rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet; // Make sure to clear cache flush bit back to normal state 1968 1969 if (newptr) responseptr = newptr; 1970 if (newptr && m->omsg.h.numAnswers) rr->RequireGoodbye = mDNStrue; 1971 else if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask) rr->ImmedAnswer = mDNSInterfaceMark; 1972 ResponseRecords = rr->NextResponse; 1973 rr->NextResponse = mDNSNULL; 1974 rr->NR_AnswerTo = mDNSNULL; 1975 rr->NR_AdditionalTo = mDNSNULL; 1976 } 1977 1978 if (m->omsg.h.numAnswers) 1979 mDNSSendDNSMessage(m, &m->omsg, responseptr, InterfaceID, mDNSNULL, dest, MulticastDNSPort, mDNSNULL, mDNSNULL, mDNSfalse); 1980 } 1981 } 1982 1983 // CompleteDeregistration guarantees that on exit the record will have been cut from the m->ResourceRecords list 1984 // and the client's mStatus_MemFree callback will have been invoked 1985 mDNSexport void CompleteDeregistration(mDNS *const m, AuthRecord *rr) 1986 { 1987 LogInfo("CompleteDeregistration: called for Resource record %s", ARDisplayString(m, rr)); 1988 // Clearing rr->RequireGoodbye signals mDNS_Deregister_internal() that 1989 // it should go ahead and immediately dispose of this registration 1990 rr->resrec.RecordType = kDNSRecordTypeShared; 1991 rr->RequireGoodbye = mDNSfalse; 1992 rr->WakeUp.HMAC = zeroEthAddr; 1993 if (rr->AnsweredLocalQ) { AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, QC_rmv); rr->AnsweredLocalQ = mDNSfalse; } 1994 mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal); // Don't touch rr after this 1995 } 1996 1997 // DiscardDeregistrations is used on shutdown and sleep to discard (forcibly and immediately) 1998 // any deregistering records that remain in the m->ResourceRecords list. 1999 // DiscardDeregistrations calls mDNS_Deregister_internal which can call a user callback, 2000 // which may change the record list and/or question list. 2001 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this. 2002 mDNSlocal void DiscardDeregistrations(mDNS *const m) 2003 { 2004 if (m->CurrentRecord) 2005 LogMsg("DiscardDeregistrations ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord)); 2006 m->CurrentRecord = m->ResourceRecords; 2007 2008 while (m->CurrentRecord) 2009 { 2010 AuthRecord *rr = m->CurrentRecord; 2011 if (!AuthRecord_uDNS(rr) && rr->resrec.RecordType == kDNSRecordTypeDeregistering) 2012 CompleteDeregistration(m, rr); // Don't touch rr after this 2013 else 2014 m->CurrentRecord = rr->next; 2015 } 2016 } 2017 2018 mDNSlocal mStatus GetLabelDecimalValue(const mDNSu8 *const src, mDNSu8 *dst) 2019 { 2020 int i, val = 0; 2021 if (src[0] < 1 || src[0] > 3) return(mStatus_Invalid); 2022 for (i=1; i<=src[0]; i++) 2023 { 2024 if (src[i] < '0' || src[i] > '9') return(mStatus_Invalid); 2025 val = val * 10 + src[i] - '0'; 2026 } 2027 if (val > 255) return(mStatus_Invalid); 2028 *dst = (mDNSu8)val; 2029 return(mStatus_NoError); 2030 } 2031 2032 mDNSlocal mStatus GetIPv4FromName(mDNSAddr *const a, const domainname *const name) 2033 { 2034 int skip = CountLabels(name) - 6; 2035 if (skip < 0) { LogMsg("GetIPFromName: Need six labels in IPv4 reverse mapping name %##s", name); return mStatus_Invalid; } 2036 if (GetLabelDecimalValue(SkipLeadingLabels(name, skip+3)->c, &a->ip.v4.b[0]) || 2037 GetLabelDecimalValue(SkipLeadingLabels(name, skip+2)->c, &a->ip.v4.b[1]) || 2038 GetLabelDecimalValue(SkipLeadingLabels(name, skip+1)->c, &a->ip.v4.b[2]) || 2039 GetLabelDecimalValue(SkipLeadingLabels(name, skip+0)->c, &a->ip.v4.b[3])) return mStatus_Invalid; 2040 a->type = mDNSAddrType_IPv4; 2041 return(mStatus_NoError); 2042 } 2043 2044 #define HexVal(X) ( ((X) >= '0' && (X) <= '9') ? ((X) - '0' ) : \ 2045 ((X) >= 'A' && (X) <= 'F') ? ((X) - 'A' + 10) : \ 2046 ((X) >= 'a' && (X) <= 'f') ? ((X) - 'a' + 10) : -1) 2047 2048 mDNSlocal mStatus GetIPv6FromName(mDNSAddr *const a, const domainname *const name) 2049 { 2050 int i, h, l; 2051 const domainname *n; 2052 2053 int skip = CountLabels(name) - 34; 2054 if (skip < 0) { LogMsg("GetIPFromName: Need 34 labels in IPv6 reverse mapping name %##s", name); return mStatus_Invalid; } 2055 2056 n = SkipLeadingLabels(name, skip); 2057 for (i=0; i<16; i++) 2058 { 2059 if (n->c[0] != 1) return mStatus_Invalid; 2060 l = HexVal(n->c[1]); 2061 n = (const domainname *)(n->c + 2); 2062 2063 if (n->c[0] != 1) return mStatus_Invalid; 2064 h = HexVal(n->c[1]); 2065 n = (const domainname *)(n->c + 2); 2066 2067 if (l<0 || h<0) return mStatus_Invalid; 2068 a->ip.v6.b[15-i] = (mDNSu8)((h << 4) | l); 2069 } 2070 2071 a->type = mDNSAddrType_IPv6; 2072 return(mStatus_NoError); 2073 } 2074 2075 mDNSlocal mDNSs32 ReverseMapDomainType(const domainname *const name) 2076 { 2077 int skip = CountLabels(name) - 2; 2078 if (skip >= 0) 2079 { 2080 const domainname *suffix = SkipLeadingLabels(name, skip); 2081 if (SameDomainName(suffix, (const domainname*)"\x7" "in-addr" "\x4" "arpa")) return mDNSAddrType_IPv4; 2082 if (SameDomainName(suffix, (const domainname*)"\x3" "ip6" "\x4" "arpa")) return mDNSAddrType_IPv6; 2083 } 2084 return(mDNSAddrType_None); 2085 } 2086 2087 mDNSlocal void SendARP(mDNS *const m, const mDNSu8 op, const AuthRecord *const rr, 2088 const mDNSv4Addr *const spa, const mDNSEthAddr *const tha, const mDNSv4Addr *const tpa, const mDNSEthAddr *const dst) 2089 { 2090 int i; 2091 mDNSu8 *ptr = m->omsg.data; 2092 NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID); 2093 if (!intf) { LogMsg("SendARP: No interface with InterfaceID %p found %s", rr->resrec.InterfaceID, ARDisplayString(m,rr)); return; } 2094 2095 // 0x00 Destination address 2096 for (i=0; i<6; i++) *ptr++ = dst->b[i]; 2097 2098 // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option, BPF will fill in the real interface address for us) 2099 for (i=0; i<6; i++) *ptr++ = intf->MAC.b[0]; 2100 2101 // 0x0C ARP Ethertype (0x0806) 2102 *ptr++ = 0x08; *ptr++ = 0x06; 2103 2104 // 0x0E ARP header 2105 *ptr++ = 0x00; *ptr++ = 0x01; // Hardware address space; Ethernet = 1 2106 *ptr++ = 0x08; *ptr++ = 0x00; // Protocol address space; IP = 0x0800 2107 *ptr++ = 6; // Hardware address length 2108 *ptr++ = 4; // Protocol address length 2109 *ptr++ = 0x00; *ptr++ = op; // opcode; Request = 1, Response = 2 2110 2111 // 0x16 Sender hardware address (our MAC address) 2112 for (i=0; i<6; i++) *ptr++ = intf->MAC.b[i]; 2113 2114 // 0x1C Sender protocol address 2115 for (i=0; i<4; i++) *ptr++ = spa->b[i]; 2116 2117 // 0x20 Target hardware address 2118 for (i=0; i<6; i++) *ptr++ = tha->b[i]; 2119 2120 // 0x26 Target protocol address 2121 for (i=0; i<4; i++) *ptr++ = tpa->b[i]; 2122 2123 // 0x2A Total ARP Packet length 42 bytes 2124 mDNSPlatformSendRawPacket(m->omsg.data, ptr, rr->resrec.InterfaceID); 2125 } 2126 2127 mDNSlocal mDNSu16 CheckSum(const void *const data, mDNSs32 length, mDNSu32 sum) 2128 { 2129 const mDNSu16 *ptr = data; 2130 while (length > 0) { length -= 2; sum += *ptr++; } 2131 sum = (sum & 0xFFFF) + (sum >> 16); 2132 sum = (sum & 0xFFFF) + (sum >> 16); 2133 return(sum != 0xFFFF ? sum : 0); 2134 } 2135 2136 mDNSlocal mDNSu16 IPv6CheckSum(const mDNSv6Addr *const src, const mDNSv6Addr *const dst, const mDNSu8 protocol, const void *const data, const mDNSu32 length) 2137 { 2138 IPv6PseudoHeader ph; 2139 ph.src = *src; 2140 ph.dst = *dst; 2141 ph.len.b[0] = length >> 24; 2142 ph.len.b[1] = length >> 16; 2143 ph.len.b[2] = length >> 8; 2144 ph.len.b[3] = length; 2145 ph.pro.b[0] = 0; 2146 ph.pro.b[1] = 0; 2147 ph.pro.b[2] = 0; 2148 ph.pro.b[3] = protocol; 2149 return CheckSum(&ph, sizeof(ph), CheckSum(data, length, 0)); 2150 } 2151 2152 mDNSlocal void SendNDP(mDNS *const m, const mDNSu8 op, const mDNSu8 flags, const AuthRecord *const rr, 2153 const mDNSv6Addr *const spa, const mDNSEthAddr *const tha, const mDNSv6Addr *const tpa, const mDNSEthAddr *const dst) 2154 { 2155 int i; 2156 mDNSOpaque16 checksum; 2157 mDNSu8 *ptr = m->omsg.data; 2158 // Some recipient hosts seem to ignore Neighbor Solicitations if the IPv6-layer destination address is not the 2159 // appropriate IPv6 solicited node multicast address, so we use that IPv6-layer destination address, even though 2160 // at the Ethernet-layer we unicast the packet to the intended target, to avoid wasting network bandwidth. 2161 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] } }; 2162 const mDNSv6Addr *const v6dst = (op == NDP_Sol) ? &mc : tpa; 2163 NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID); 2164 if (!intf) { LogMsg("SendNDP: No interface with InterfaceID %p found %s", rr->resrec.InterfaceID, ARDisplayString(m,rr)); return; } 2165 2166 // 0x00 Destination address 2167 for (i=0; i<6; i++) *ptr++ = dst->b[i]; 2168 // Right now we only send Neighbor Solicitations to verify whether the host we're proxying for has gone to sleep yet. 2169 // Since we know who we're looking for, we send it via Ethernet-layer unicast, rather than bothering every host on the 2170 // link with a pointless link-layer multicast. 2171 // Should we want to send traditional Neighbor Solicitations in the future, where we really don't know in advance what 2172 // Ethernet-layer address we're looking for, we'll need to send to the appropriate Ethernet-layer multicast address: 2173 // *ptr++ = 0x33; 2174 // *ptr++ = 0x33; 2175 // *ptr++ = 0xFF; 2176 // *ptr++ = tpa->b[0xD]; 2177 // *ptr++ = tpa->b[0xE]; 2178 // *ptr++ = tpa->b[0xF]; 2179 2180 // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option, BPF will fill in the real interface address for us) 2181 for (i=0; i<6; i++) 2182 if (tha) 2183 *ptr++ = tha->b[i]; 2184 else 2185 *ptr++ = intf->MAC.b[i]; 2186 2187 // 0x0C IPv6 Ethertype (0x86DD) 2188 *ptr++ = 0x86; *ptr++ = 0xDD; 2189 2190 // 0x0E IPv6 header 2191 *ptr++ = 0x60; *ptr++ = 0x00; *ptr++ = 0x00; *ptr++ = 0x00; // Version, Traffic Class, Flow Label 2192 *ptr++ = 0x00; *ptr++ = 0x20; // Length 2193 *ptr++ = 0x3A; // Protocol == ICMPv6 2194 *ptr++ = 0xFF; // Hop Limit 2195 2196 // 0x16 Sender IPv6 address 2197 for (i=0; i<16; i++) *ptr++ = spa->b[i]; 2198 2199 // 0x26 Destination IPv6 address 2200 for (i=0; i<16; i++) *ptr++ = v6dst->b[i]; 2201 2202 // 0x36 NDP header 2203 *ptr++ = op; // 0x87 == Neighbor Solicitation, 0x88 == Neighbor Advertisement 2204 *ptr++ = 0x00; // Code 2205 *ptr++ = 0x00; *ptr++ = 0x00; // Checksum placeholder (0x38, 0x39) 2206 *ptr++ = flags; 2207 *ptr++ = 0x00; *ptr++ = 0x00; *ptr++ = 0x00; 2208 2209 if (op == NDP_Sol) // Neighbor Solicitation. The NDP "target" is the address we seek. 2210 { 2211 // 0x3E NDP target. 2212 for (i=0; i<16; i++) *ptr++ = tpa->b[i]; 2213 // 0x4E Source Link-layer Address 2214 // <http://www.ietf.org/rfc/rfc2461.txt> 2215 // MUST NOT be included when the source IP address is the unspecified address. 2216 // Otherwise, on link layers that have addresses this option MUST be included 2217 // in multicast solicitations and SHOULD be included in unicast solicitations. 2218 if (!mDNSIPv6AddressIsZero(*spa)) 2219 { 2220 *ptr++ = NDP_SrcLL; // Option Type 1 == Source Link-layer Address 2221 *ptr++ = 0x01; // Option length 1 (in units of 8 octets) 2222 for (i=0; i<6; i++) 2223 if (tha) 2224 *ptr++ = tha->b[i]; 2225 else 2226 *ptr++ = intf->MAC.b[i]; 2227 } 2228 } 2229 else // Neighbor Advertisement. The NDP "target" is the address we're giving information about. 2230 { 2231 // 0x3E NDP target. 2232 for (i=0; i<16; i++) *ptr++ = spa->b[i]; 2233 // 0x4E Target Link-layer Address 2234 *ptr++ = NDP_TgtLL; // Option Type 2 == Target Link-layer Address 2235 *ptr++ = 0x01; // Option length 1 (in units of 8 octets) 2236 for (i=0; i<6; i++) 2237 if (tha) 2238 *ptr++ = tha->b[i]; 2239 else 2240 *ptr++ = intf->MAC.b[i]; 2241 } 2242 2243 // 0x4E or 0x56 Total NDP Packet length 78 or 86 bytes 2244 m->omsg.data[0x13] = ptr - &m->omsg.data[0x36]; // Compute actual length 2245 checksum.NotAnInteger = ~IPv6CheckSum(spa, v6dst, 0x3A, &m->omsg.data[0x36], m->omsg.data[0x13]); 2246 m->omsg.data[0x38] = checksum.b[0]; 2247 m->omsg.data[0x39] = checksum.b[1]; 2248 2249 mDNSPlatformSendRawPacket(m->omsg.data, ptr, rr->resrec.InterfaceID); 2250 } 2251 2252 mDNSlocal void SetupTracerOpt(const mDNS *const m, rdataOPT *const Trace) 2253 { 2254 mDNSu32 DNS_VERS = _DNS_SD_H; 2255 Trace->u.tracer.platf = m->mDNS_plat; 2256 Trace->u.tracer.mDNSv = DNS_VERS; 2257 2258 Trace->opt = kDNSOpt_Trace; 2259 Trace->optlen = DNSOpt_TraceData_Space - 4; 2260 } 2261 2262 mDNSlocal void SetupOwnerOpt(const mDNS *const m, const NetworkInterfaceInfo *const intf, rdataOPT *const owner) 2263 { 2264 owner->u.owner.vers = 0; 2265 owner->u.owner.seq = m->SleepSeqNum; 2266 owner->u.owner.HMAC = m->PrimaryMAC; 2267 owner->u.owner.IMAC = intf->MAC; 2268 owner->u.owner.password = zeroEthAddr; 2269 2270 // Don't try to compute the optlen until *after* we've set up the data fields 2271 // 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 2272 owner->opt = kDNSOpt_Owner; 2273 owner->optlen = DNSOpt_Owner_Space(&m->PrimaryMAC, &intf->MAC) - 4; 2274 } 2275 2276 mDNSlocal void GrantUpdateCredit(AuthRecord *rr) 2277 { 2278 if (++rr->UpdateCredits >= kMaxUpdateCredits) rr->NextUpdateCredit = 0; 2279 else rr->NextUpdateCredit = NonZeroTime(rr->NextUpdateCredit + kUpdateCreditRefreshInterval); 2280 } 2281 2282 mDNSlocal mDNSBool ShouldSendGoodbyesBeforeSleep(mDNS *const m, const NetworkInterfaceInfo *intf, AuthRecord *rr) 2283 { 2284 // If there are no sleep proxies, we set the state to SleepState_Sleeping explicitly 2285 // and hence there is no need to check for Transfering state. But if we have sleep 2286 // proxies and partially sending goodbyes for some records, we will be in Transfering 2287 // state and hence need to make sure that we send goodbyes in that case too. Checking whether 2288 // we are not awake handles both cases. 2289 if ((rr->AuthFlags & AuthFlagsWakeOnly) && (m->SleepState != SleepState_Awake)) 2290 { 2291 debugf("ShouldSendGoodbyesBeforeSleep: marking for goodbye", ARDisplayString(m, rr)); 2292 return mDNStrue; 2293 } 2294 2295 if (m->SleepState != SleepState_Sleeping) 2296 return mDNSfalse; 2297 2298 // If we are going to sleep and in SleepState_Sleeping, SendGoodbyes on the interface tell you 2299 // whether you can send goodbyes or not. 2300 if (!intf->SendGoodbyes) 2301 { 2302 debugf("ShouldSendGoodbyesBeforeSleep: not sending goodbye %s, int %p", ARDisplayString(m, rr), intf->InterfaceID); 2303 return mDNSfalse; 2304 } 2305 else 2306 { 2307 debugf("ShouldSendGoodbyesBeforeSleep: sending goodbye %s, int %p", ARDisplayString(m, rr), intf->InterfaceID); 2308 return mDNStrue; 2309 } 2310 } 2311 2312 // Note about acceleration of announcements to facilitate automatic coalescing of 2313 // multiple independent threads of announcements into a single synchronized thread: 2314 // The announcements in the packet may be at different stages of maturity; 2315 // One-second interval, two-second interval, four-second interval, and so on. 2316 // After we've put in all the announcements that are due, we then consider 2317 // whether there are other nearly-due announcements that are worth accelerating. 2318 // To be eligible for acceleration, a record MUST NOT be older (further along 2319 // its timeline) than the most mature record we've already put in the packet. 2320 // In other words, younger records can have their timelines accelerated to catch up 2321 // with their elder bretheren; this narrows the age gap and helps them eventually get in sync. 2322 // Older records cannot have their timelines accelerated; this would just widen 2323 // the gap between them and their younger bretheren and get them even more out of sync. 2324 2325 // Note: SendResponses calls mDNS_Deregister_internal which can call a user callback, which may change 2326 // the record list and/or question list. 2327 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this. 2328 mDNSlocal void SendResponses(mDNS *const m) 2329 { 2330 int pktcount = 0; 2331 AuthRecord *rr, *r2; 2332 mDNSs32 maxExistingAnnounceInterval = 0; 2333 const NetworkInterfaceInfo *intf = GetFirstActiveInterface(m->HostInterfaces); 2334 2335 m->NextScheduledResponse = m->timenow + 0x78000000; 2336 2337 if (m->SleepState == SleepState_Transferring) RetrySPSRegistrations(m); 2338 2339 for (rr = m->ResourceRecords; rr; rr=rr->next) 2340 if (rr->ImmedUnicast) 2341 { 2342 mDNSAddr v4 = { mDNSAddrType_IPv4, {{{0}}} }; 2343 mDNSAddr v6 = { mDNSAddrType_IPv6, {{{0}}} }; 2344 v4.ip.v4 = rr->v4Requester; 2345 v6.ip.v6 = rr->v6Requester; 2346 if (!mDNSIPv4AddressIsZero(rr->v4Requester)) SendDelayedUnicastResponse(m, &v4, rr->ImmedAnswer); 2347 if (!mDNSIPv6AddressIsZero(rr->v6Requester)) SendDelayedUnicastResponse(m, &v6, rr->ImmedAnswer); 2348 if (rr->ImmedUnicast) 2349 { 2350 LogMsg("SendResponses: ERROR: rr->ImmedUnicast still set: %s", ARDisplayString(m, rr)); 2351 rr->ImmedUnicast = mDNSfalse; 2352 } 2353 } 2354 2355 // *** 2356 // *** 1. Setup: Set the SendRNow and ImmedAnswer fields to indicate which interface(s) the records need to be sent on 2357 // *** 2358 2359 // Run through our list of records, and decide which ones we're going to announce on all interfaces 2360 for (rr = m->ResourceRecords; rr; rr=rr->next) 2361 { 2362 while (rr->NextUpdateCredit && m->timenow - rr->NextUpdateCredit >= 0) GrantUpdateCredit(rr); 2363 if (TimeToAnnounceThisRecord(rr, m->timenow)) 2364 { 2365 if (rr->resrec.RecordType == kDNSRecordTypeDeregistering) 2366 { 2367 if (!rr->WakeUp.HMAC.l[0]) 2368 { 2369 if (rr->AnnounceCount) rr->ImmedAnswer = mDNSInterfaceMark; // Send goodbye packet on all interfaces 2370 } 2371 else 2372 { 2373 LogSPS("SendResponses: Sending wakeup %2d for %.6a %s", rr->AnnounceCount-3, &rr->WakeUp.IMAC, ARDisplayString(m, rr)); 2374 SendWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.IMAC, &rr->WakeUp.password); 2375 for (r2 = rr; r2; r2=r2->next) 2376 if (r2->AnnounceCount && r2->resrec.InterfaceID == rr->resrec.InterfaceID && mDNSSameEthAddress(&r2->WakeUp.IMAC, &rr->WakeUp.IMAC) && 2377 !mDNSSameEthAddress(&zeroEthAddr, &r2->WakeUp.HMAC)) 2378 { 2379 // For now we only want to send a single Unsolicited Neighbor Advertisement restoring the address to the original 2380 // owner, because these packets can cause some IPv6 stacks to falsely conclude that there's an address conflict. 2381 if (r2->AddressProxy.type == mDNSAddrType_IPv6 && r2->AnnounceCount == WakeupCount) 2382 { 2383 LogSPS("NDP Announcement %2d Releasing traffic for H-MAC %.6a I-MAC %.6a %s", 2384 r2->AnnounceCount-3, &r2->WakeUp.HMAC, &r2->WakeUp.IMAC, ARDisplayString(m,r2)); 2385 SendNDP(m, NDP_Adv, NDP_Override, r2, &r2->AddressProxy.ip.v6, &r2->WakeUp.IMAC, &AllHosts_v6, &AllHosts_v6_Eth); 2386 } 2387 r2->LastAPTime = m->timenow; 2388 // After 15 wakeups without success (maybe host has left the network) send three goodbyes instead 2389 if (--r2->AnnounceCount <= GoodbyeCount) r2->WakeUp.HMAC = zeroEthAddr; 2390 } 2391 } 2392 } 2393 else if (ResourceRecordIsValidAnswer(rr)) 2394 { 2395 if (rr->AddressProxy.type) 2396 { 2397 if (!mDNSSameEthAddress(&zeroEthAddr, &rr->WakeUp.HMAC)) 2398 { 2399 rr->AnnounceCount--; 2400 rr->ThisAPInterval *= 2; 2401 rr->LastAPTime = m->timenow; 2402 if (rr->AddressProxy.type == mDNSAddrType_IPv4) 2403 { 2404 LogSPS("ARP Announcement %2d Capturing traffic for H-MAC %.6a I-MAC %.6a %s", 2405 rr->AnnounceCount, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m,rr)); 2406 SendARP(m, 1, rr, &rr->AddressProxy.ip.v4, &zeroEthAddr, &rr->AddressProxy.ip.v4, &onesEthAddr); 2407 } 2408 else if (rr->AddressProxy.type == mDNSAddrType_IPv6) 2409 { 2410 LogSPS("NDP Announcement %2d Capturing traffic for H-MAC %.6a I-MAC %.6a %s", 2411 rr->AnnounceCount, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m,rr)); 2412 SendNDP(m, NDP_Adv, NDP_Override, rr, &rr->AddressProxy.ip.v6, mDNSNULL, &AllHosts_v6, &AllHosts_v6_Eth); 2413 } 2414 } 2415 } 2416 else 2417 { 2418 rr->ImmedAnswer = mDNSInterfaceMark; // Send on all interfaces 2419 if (maxExistingAnnounceInterval < rr->ThisAPInterval) 2420 maxExistingAnnounceInterval = rr->ThisAPInterval; 2421 if (rr->UpdateBlocked) rr->UpdateBlocked = 0; 2422 } 2423 } 2424 } 2425 } 2426 2427 // Any interface-specific records we're going to send are marked as being sent on all appropriate interfaces (which is just one) 2428 // Eligible records that are more than half-way to their announcement time are accelerated 2429 for (rr = m->ResourceRecords; rr; rr=rr->next) 2430 if ((rr->resrec.InterfaceID && rr->ImmedAnswer) || 2431 (rr->ThisAPInterval <= maxExistingAnnounceInterval && 2432 TimeToAnnounceThisRecord(rr, m->timenow + rr->ThisAPInterval/2) && 2433 !rr->AddressProxy.type && // Don't include ARP Annoucements when considering which records to accelerate 2434 ResourceRecordIsValidAnswer(rr))) 2435 rr->ImmedAnswer = mDNSInterfaceMark; // Send on all interfaces 2436 2437 // When sending SRV records (particularly when announcing a new service) automatically add related Address record(s) as additionals 2438 // Note: Currently all address records are interface-specific, so it's safe to set ImmedAdditional to their InterfaceID, 2439 // which will be non-null. If by some chance there is an address record that's not interface-specific (should never happen) 2440 // then all that means is that it won't get sent -- which would not be the end of the world. 2441 for (rr = m->ResourceRecords; rr; rr=rr->next) 2442 { 2443 if (rr->ImmedAnswer && rr->resrec.rrtype == kDNSType_SRV) 2444 for (r2=m->ResourceRecords; r2; r2=r2->next) // Scan list of resource records 2445 if (RRTypeIsAddressType(r2->resrec.rrtype) && // For all address records (A/AAAA) ... 2446 ResourceRecordIsValidAnswer(r2) && // ... which are valid for answer ... 2447 rr->LastMCTime - r2->LastMCTime >= 0 && // ... which we have not sent recently ... 2448 rr->resrec.rdatahash == r2->resrec.namehash && // ... whose name is the name of the SRV target 2449 SameDomainName(&rr->resrec.rdata->u.srv.target, r2->resrec.name) && 2450 (rr->ImmedAnswer == mDNSInterfaceMark || rr->ImmedAnswer == r2->resrec.InterfaceID)) 2451 r2->ImmedAdditional = r2->resrec.InterfaceID; // ... then mark this address record for sending too 2452 // We also make sure we send the DeviceInfo TXT record too, if necessary 2453 // We check for RecordType == kDNSRecordTypeShared because we don't want to tag the 2454 // DeviceInfo TXT record onto a goodbye packet (RecordType == kDNSRecordTypeDeregistering). 2455 if (rr->ImmedAnswer && rr->resrec.RecordType == kDNSRecordTypeShared && rr->resrec.rrtype == kDNSType_PTR) 2456 if (ResourceRecordIsValidAnswer(&m->DeviceInfo) && SameDomainLabel(rr->resrec.rdata->u.name.c, m->DeviceInfo.resrec.name->c)) 2457 { 2458 if (!m->DeviceInfo.ImmedAnswer) m->DeviceInfo.ImmedAnswer = rr->ImmedAnswer; 2459 else m->DeviceInfo.ImmedAnswer = mDNSInterfaceMark; 2460 } 2461 } 2462 2463 // If there's a record which is supposed to be unique that we're going to send, then make sure that we give 2464 // the whole RRSet as an atomic unit. That means that if we have any other records with the same name/type/class 2465 // then we need to mark them for sending too. Otherwise, if we set the kDNSClass_UniqueRRSet bit on a 2466 // record, then other RRSet members that have not been sent recently will get flushed out of client caches. 2467 // -- 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 2468 // -- If any record is marked to be sent on all interfaces, make sure the whole set is marked to be sent on all interfaces 2469 for (rr = m->ResourceRecords; rr; rr=rr->next) 2470 if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask) 2471 { 2472 if (rr->ImmedAnswer) // If we're sending this as answer, see that its whole RRSet is similarly marked 2473 { 2474 for (r2 = m->ResourceRecords; r2; r2=r2->next) 2475 if (ResourceRecordIsValidAnswer(r2)) 2476 if (r2->ImmedAnswer != mDNSInterfaceMark && 2477 r2->ImmedAnswer != rr->ImmedAnswer && SameResourceRecordSignature(r2, rr)) 2478 r2->ImmedAnswer = !r2->ImmedAnswer ? rr->ImmedAnswer : mDNSInterfaceMark; 2479 } 2480 else if (rr->ImmedAdditional) // If we're sending this as additional, see that its whole RRSet is similarly marked 2481 { 2482 for (r2 = m->ResourceRecords; r2; r2=r2->next) 2483 if (ResourceRecordIsValidAnswer(r2)) 2484 if (r2->ImmedAdditional != rr->ImmedAdditional && SameResourceRecordSignature(r2, rr)) 2485 r2->ImmedAdditional = rr->ImmedAdditional; 2486 } 2487 } 2488 2489 // Now set SendRNow state appropriately 2490 for (rr = m->ResourceRecords; rr; rr=rr->next) 2491 { 2492 if (rr->ImmedAnswer == mDNSInterfaceMark) // Sending this record on all appropriate interfaces 2493 { 2494 rr->SendRNow = !intf ? mDNSNULL : (rr->resrec.InterfaceID) ? rr->resrec.InterfaceID : intf->InterfaceID; 2495 rr->ImmedAdditional = mDNSNULL; // No need to send as additional if sending as answer 2496 rr->LastMCTime = m->timenow; 2497 rr->LastMCInterface = rr->ImmedAnswer; 2498 // If we're announcing this record, and it's at least half-way to its ordained time, then consider this announcement done 2499 if (TimeToAnnounceThisRecord(rr, m->timenow + rr->ThisAPInterval/2)) 2500 { 2501 rr->AnnounceCount--; 2502 if (rr->resrec.RecordType != kDNSRecordTypeDeregistering) 2503 rr->ThisAPInterval *= 2; 2504 rr->LastAPTime = m->timenow; 2505 debugf("Announcing %##s (%s) %d", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->AnnounceCount); 2506 } 2507 } 2508 else if (rr->ImmedAnswer) // Else, just respond to a single query on single interface: 2509 { 2510 rr->SendRNow = rr->ImmedAnswer; // Just respond on that interface 2511 rr->ImmedAdditional = mDNSNULL; // No need to send as additional too 2512 rr->LastMCTime = m->timenow; 2513 rr->LastMCInterface = rr->ImmedAnswer; 2514 } 2515 SetNextAnnounceProbeTime(m, rr); 2516 //if (rr->SendRNow) LogMsg("%-15.4a %s", &rr->v4Requester, ARDisplayString(m, rr)); 2517 } 2518 2519 // *** 2520 // *** 2. Loop through interface list, sending records as appropriate 2521 // *** 2522 2523 while (intf) 2524 { 2525 int OwnerRecordSpace = (m->AnnounceOwner && intf->MAC.l[0]) ? DNSOpt_Header_Space + DNSOpt_Owner_Space(&m->PrimaryMAC, &intf->MAC) : 0; 2526 int TraceRecordSpace = (mDNS_McastTracingEnabled && MDNS_TRACER) ? DNSOpt_Header_Space + DNSOpt_TraceData_Space : 0; 2527 int numDereg = 0; 2528 int numAnnounce = 0; 2529 int numAnswer = 0; 2530 int AnoninfoSpace = 0; 2531 mDNSu8 *responseptr = m->omsg.data; 2532 mDNSu8 *newptr; 2533 InitializeDNSMessage(&m->omsg.h, zeroID, ResponseFlags); 2534 2535 // First Pass. Look for: 2536 // 1. Deregistering records that need to send their goodbye packet 2537 // 2. Updated records that need to retract their old data 2538 // 3. Answers and announcements we need to send 2539 for (rr = m->ResourceRecords; rr; rr=rr->next) 2540 { 2541 2542 // Skip this interface if the record InterfaceID is *Any and the record is not 2543 // appropriate for the interface type. 2544 if ((rr->SendRNow == intf->InterfaceID) && 2545 ((rr->resrec.InterfaceID == mDNSInterface_Any) && !mDNSPlatformValidRecordForInterface(rr, intf))) 2546 { 2547 LogInfo("SendResponses: Not sending %s, on %s", ARDisplayString(m, rr), InterfaceNameForID(m, rr->SendRNow)); 2548 rr->SendRNow = GetNextActiveInterfaceID(intf); 2549 } 2550 else if (rr->SendRNow == intf->InterfaceID) 2551 { 2552 RData *OldRData = rr->resrec.rdata; 2553 mDNSu16 oldrdlength = rr->resrec.rdlength; 2554 mDNSu8 active = (mDNSu8) 2555 (rr->resrec.RecordType != kDNSRecordTypeDeregistering && !ShouldSendGoodbyesBeforeSleep(m, intf, rr)); 2556 newptr = mDNSNULL; 2557 if (rr->NewRData && active) 2558 { 2559 // See if we should send a courtesy "goodbye" for the old data before we replace it. 2560 if (ResourceRecordIsValidAnswer(rr) && rr->resrec.RecordType == kDNSRecordTypeShared && rr->RequireGoodbye) 2561 { 2562 newptr = PutRR_OS_TTL(responseptr, &m->omsg.h.numAnswers, &rr->resrec, 0); 2563 if (newptr) { responseptr = newptr; numDereg++; rr->RequireGoodbye = mDNSfalse; } 2564 else continue; // If this packet is already too full to hold the goodbye for this record, skip it for now and we'll retry later 2565 } 2566 SetNewRData(&rr->resrec, rr->NewRData, rr->newrdlength); 2567 } 2568 2569 if (rr->resrec.AnonInfo) 2570 { 2571 int tmp = AnonInfoSpace(rr->resrec.AnonInfo); 2572 2573 AnoninfoSpace += tmp; 2574 // Adjust OwnerRecordSpace/TraceRecordSpace which is used by PutRR_OS_TTL below so that 2575 // we have space to put in the NSEC3 record in the authority section. 2576 OwnerRecordSpace += tmp; 2577 TraceRecordSpace += tmp; 2578 } 2579 2580 if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask) 2581 rr->resrec.rrclass |= kDNSClass_UniqueRRSet; // Temporarily set the cache flush bit so PutResourceRecord will set it 2582 newptr = PutRR_OS_TTL(responseptr, &m->omsg.h.numAnswers, &rr->resrec, active ? rr->resrec.rroriginalttl : 0); 2583 rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet; // Make sure to clear cache flush bit back to normal state 2584 if (newptr) 2585 { 2586 responseptr = newptr; 2587 rr->RequireGoodbye = active; 2588 if (rr->resrec.RecordType == kDNSRecordTypeDeregistering) numDereg++; 2589 else if (rr->LastAPTime == m->timenow) numAnnounce++;else numAnswer++; 2590 } 2591 2592 if (rr->NewRData && active) 2593 SetNewRData(&rr->resrec, OldRData, oldrdlength); 2594 2595 // The first time through (pktcount==0), if this record is verified unique 2596 // (i.e. typically A, AAAA, SRV, TXT and reverse-mapping PTR), set the flag to add an NSEC too. 2597 if (!pktcount && active && (rr->resrec.RecordType & kDNSRecordTypeActiveUniqueMask) && !rr->SendNSECNow) 2598 rr->SendNSECNow = mDNSInterfaceMark; 2599 2600 if (newptr) // If succeeded in sending, advance to next interface 2601 { 2602 if (rr->resrec.AnonInfo) 2603 { 2604 debugf("SendResponses: Marking %s, OwnerRecordSpace %d, TraceRecordSpace %d, limit %p", ARDisplayString(m, rr), OwnerRecordSpace, 2605 TraceRecordSpace, m->omsg.data + AllowedRRSpace(&m->omsg) - OwnerRecordSpace - TraceRecordSpace); 2606 rr->resrec.AnonInfo->SendNow = intf->InterfaceID; 2607 } 2608 2609 // If sending on all interfaces, go to next interface; else we're finished now 2610 if (rr->ImmedAnswer == mDNSInterfaceMark && rr->resrec.InterfaceID == mDNSInterface_Any) 2611 rr->SendRNow = GetNextActiveInterfaceID(intf); 2612 else 2613 rr->SendRNow = mDNSNULL; 2614 } 2615 } 2616 } 2617 2618 // Get the reserved space back 2619 OwnerRecordSpace -= AnoninfoSpace; 2620 TraceRecordSpace -= AnoninfoSpace; 2621 newptr = responseptr; 2622 for (rr = m->ResourceRecords; rr; rr=rr->next) 2623 { 2624 if (rr->resrec.AnonInfo && rr->resrec.AnonInfo->SendNow == intf->InterfaceID) 2625 { 2626 ResourceRecord *nsec3RR = rr->resrec.AnonInfo->nsec3RR; 2627 2628 newptr = PutRR_OS_TTL(newptr, &m->omsg.h.numAuthorities, nsec3RR, nsec3RR->rroriginalttl); 2629 if (newptr) 2630 { 2631 responseptr = newptr; 2632 debugf("SendResponses: Added NSEC3 %s, OwnerRecordSpace %d, TraceRecordSpace %d, limit %p", ARDisplayString(m, rr), OwnerRecordSpace, 2633 TraceRecordSpace, m->omsg.data + AllowedRRSpace(&m->omsg) - OwnerRecordSpace - TraceRecordSpace); 2634 } 2635 else 2636 { 2637 LogMsg("SendResponses: Cannot add NSEC3 %s, OwnerRecordSpace %d, TraceRecordSpace %d, limit %p", ARDisplayString(m, rr), OwnerRecordSpace, 2638 TraceRecordSpace, m->omsg.data + AllowedRRSpace(&m->omsg) - OwnerRecordSpace - TraceRecordSpace); 2639 } 2640 rr->resrec.AnonInfo->SendNow = mDNSNULL; 2641 } 2642 } 2643 // Second Pass. Add additional records, if there's space. 2644 newptr = responseptr; 2645 for (rr = m->ResourceRecords; rr; rr=rr->next) 2646 if (rr->ImmedAdditional == intf->InterfaceID) 2647 if (ResourceRecordIsValidAnswer(rr)) 2648 { 2649 // If we have at least one answer already in the packet, then plan to add additionals too 2650 mDNSBool SendAdditional = (m->omsg.h.numAnswers > 0); 2651 2652 // If we're not planning to send any additionals, but this record is a unique one, then 2653 // make sure we haven't already sent any other members of its RRSet -- if we have, then they 2654 // will have had the cache flush bit set, so now we need to finish the job and send the rest. 2655 if (!SendAdditional && (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)) 2656 { 2657 const AuthRecord *a; 2658 for (a = m->ResourceRecords; a; a=a->next) 2659 if (a->LastMCTime == m->timenow && 2660 a->LastMCInterface == intf->InterfaceID && 2661 SameResourceRecordSignature(a, rr)) { SendAdditional = mDNStrue; break; } 2662 } 2663 if (!SendAdditional) // If we don't want to send this after all, 2664 rr->ImmedAdditional = mDNSNULL; // then cancel its ImmedAdditional field 2665 else if (newptr) // Else, try to add it if we can 2666 { 2667 // The first time through (pktcount==0), if this record is verified unique 2668 // (i.e. typically A, AAAA, SRV, TXT and reverse-mapping PTR), set the flag to add an NSEC too. 2669 if (!pktcount && (rr->resrec.RecordType & kDNSRecordTypeActiveUniqueMask) && !rr->SendNSECNow) 2670 rr->SendNSECNow = mDNSInterfaceMark; 2671 2672 if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask) 2673 rr->resrec.rrclass |= kDNSClass_UniqueRRSet; // Temporarily set the cache flush bit so PutResourceRecord will set it 2674 newptr = PutRR_OS(newptr, &m->omsg.h.numAdditionals, &rr->resrec); 2675 rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet; // Make sure to clear cache flush bit back to normal state 2676 if (newptr) 2677 { 2678 responseptr = newptr; 2679 rr->ImmedAdditional = mDNSNULL; 2680 rr->RequireGoodbye = mDNStrue; 2681 // If we successfully put this additional record in the packet, we record LastMCTime & LastMCInterface. 2682 // This matters particularly in the case where we have more than one IPv6 (or IPv4) address, because otherwise, 2683 // when we see our own multicast with the cache flush bit set, if we haven't set LastMCTime, then we'll get 2684 // all concerned and re-announce our record again to make sure it doesn't get flushed from peer caches. 2685 rr->LastMCTime = m->timenow; 2686 rr->LastMCInterface = intf->InterfaceID; 2687 } 2688 } 2689 } 2690 2691 // Third Pass. Add NSEC records, if there's space. 2692 // When we're generating an NSEC record in response to a specify query for that type 2693 // (recognized by rr->SendNSECNow == intf->InterfaceID) we should really put the NSEC in the Answer Section, 2694 // not Additional Section, but for now it's easier to handle both cases in this Additional Section loop here. 2695 for (rr = m->ResourceRecords; rr; rr=rr->next) 2696 if (rr->SendNSECNow == mDNSInterfaceMark || rr->SendNSECNow == intf->InterfaceID) 2697 { 2698 AuthRecord nsec; 2699 mDNSu8 *ptr; 2700 int len; 2701 mDNS_SetupResourceRecord(&nsec, mDNSNULL, mDNSInterface_Any, kDNSType_NSEC, rr->resrec.rroriginalttl, kDNSRecordTypeUnique, AuthRecordAny, mDNSNULL, mDNSNULL); 2702 nsec.resrec.rrclass |= kDNSClass_UniqueRRSet; 2703 AssignDomainName(&nsec.namestorage, rr->resrec.name); 2704 ptr = nsec.rdatastorage.u.data; 2705 len = DomainNameLength(rr->resrec.name); 2706 // We have a nxt name followed by window number, window length and a window bitmap 2707 nsec.resrec.rdlength = len + 2 + NSEC_MCAST_WINDOW_SIZE; 2708 if (nsec.resrec.rdlength <= StandardAuthRDSize) 2709 { 2710 mDNSPlatformMemZero(ptr, nsec.resrec.rdlength); 2711 AssignDomainName((domainname *)ptr, rr->resrec.name); 2712 ptr += len; 2713 *ptr++ = 0; // window number 2714 *ptr++ = NSEC_MCAST_WINDOW_SIZE; // window length 2715 for (r2 = m->ResourceRecords; r2; r2=r2->next) 2716 if (ResourceRecordIsValidAnswer(r2) && SameResourceRecordNameClassInterface(r2, rr)) 2717 { 2718 if (r2->resrec.rrtype >= kDNSQType_ANY) { LogMsg("SendResponses: Can't create NSEC for record %s", ARDisplayString(m, r2)); break; } 2719 else ptr[r2->resrec.rrtype >> 3] |= 128 >> (r2->resrec.rrtype & 7); 2720 } 2721 newptr = responseptr; 2722 if (!r2) // If we successfully built our NSEC record, add it to the packet now 2723 { 2724 newptr = PutRR_OS(responseptr, &m->omsg.h.numAdditionals, &nsec.resrec); 2725 if (newptr) responseptr = newptr; 2726 } 2727 } 2728 else LogMsg("SendResponses: not enough space (%d) in authrecord for nsec", nsec.resrec.rdlength); 2729 2730 // If we successfully put the NSEC record, clear the SendNSECNow flag 2731 // If we consider this NSEC optional, then we unconditionally clear the SendNSECNow flag, even if we fail to put this additional record 2732 if (newptr || rr->SendNSECNow == mDNSInterfaceMark) 2733 { 2734 rr->SendNSECNow = mDNSNULL; 2735 // Run through remainder of list clearing SendNSECNow flag for all other records which would generate the same NSEC 2736 for (r2 = rr->next; r2; r2=r2->next) 2737 if (SameResourceRecordNameClassInterface(r2, rr)) 2738 if (r2->SendNSECNow == mDNSInterfaceMark || r2->SendNSECNow == intf->InterfaceID) 2739 r2->SendNSECNow = mDNSNULL; 2740 } 2741 } 2742 2743 if (m->omsg.h.numAnswers || m->omsg.h.numAdditionals) 2744 { 2745 // If we have data to send, add OWNER/TRACER/OWNER+TRACER option if necessary, then send packet 2746 if (OwnerRecordSpace || TraceRecordSpace) 2747 { 2748 AuthRecord opt; 2749 mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL); 2750 opt.resrec.rrclass = NormalMaxDNSMessageData; 2751 opt.resrec.rdlength = sizeof(rdataOPT); 2752 opt.resrec.rdestimate = sizeof(rdataOPT); 2753 if (OwnerRecordSpace && TraceRecordSpace) 2754 { 2755 opt.resrec.rdlength += sizeof(rdataOPT); // Two options in this OPT record 2756 opt.resrec.rdestimate += sizeof(rdataOPT); 2757 SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[0]); 2758 SetupTracerOpt(m, &opt.resrec.rdata->u.opt[1]); 2759 } 2760 else if (OwnerRecordSpace) 2761 { 2762 SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[0]); 2763 } 2764 else if (TraceRecordSpace) 2765 { 2766 SetupTracerOpt(m, &opt.resrec.rdata->u.opt[0]); 2767 } 2768 newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAdditionals, &opt.resrec); 2769 if (newptr) 2770 { 2771 responseptr = newptr; 2772 LogInfo("SendResponses put %s %s: %s %s", OwnerRecordSpace ? "OWNER" : "", TraceRecordSpace ? "TRACER" : "", intf->ifname, ARDisplayString(m, &opt)); 2773 } 2774 else if (m->omsg.h.numAnswers + m->omsg.h.numAuthorities + m->omsg.h.numAdditionals == 1) 2775 { 2776 LogInfo("SendResponses: No space in packet for %s %s OPT record (%d/%d/%d/%d) %s", OwnerRecordSpace ? "OWNER" : "", TraceRecordSpace ? "TRACER" : "", 2777 m->omsg.h.numQuestions, m->omsg.h.numAnswers, m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt)); 2778 } 2779 else 2780 { 2781 LogMsg("SendResponses: How did we fail to have space for %s %s OPT record (%d/%d/%d/%d) %s", OwnerRecordSpace ? "OWNER" : "", TraceRecordSpace ? "TRACER" : "", 2782 m->omsg.h.numQuestions, m->omsg.h.numAnswers, m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt)); 2783 } 2784 } 2785 2786 debugf("SendResponses: Sending %d Deregistration%s, %d Announcement%s, %d Answer%s, %d Additional%s on %p", 2787 numDereg, numDereg == 1 ? "" : "s", 2788 numAnnounce, numAnnounce == 1 ? "" : "s", 2789 numAnswer, numAnswer == 1 ? "" : "s", 2790 m->omsg.h.numAdditionals, m->omsg.h.numAdditionals == 1 ? "" : "s", intf->InterfaceID); 2791 2792 if (intf->IPv4Available) mDNSSendDNSMessage(m, &m->omsg, responseptr, intf->InterfaceID, mDNSNULL, &AllDNSLinkGroup_v4, MulticastDNSPort, mDNSNULL, mDNSNULL, mDNSfalse); 2793 if (intf->IPv6Available) mDNSSendDNSMessage(m, &m->omsg, responseptr, intf->InterfaceID, mDNSNULL, &AllDNSLinkGroup_v6, MulticastDNSPort, mDNSNULL, mDNSNULL, mDNSfalse); 2794 if (!m->SuppressSending) m->SuppressSending = NonZeroTime(m->timenow + (mDNSPlatformOneSecond+9)/10); 2795 if (++pktcount >= 1000) { LogMsg("SendResponses exceeded loop limit %d: giving up", pktcount); break; } 2796 // There might be more things to send on this interface, so go around one more time and try again. 2797 } 2798 else // Nothing more to send on this interface; go to next 2799 { 2800 const NetworkInterfaceInfo *next = GetFirstActiveInterface(intf->next); 2801 #if MDNS_DEBUGMSGS && 0 2802 const char *const msg = next ? "SendResponses: Nothing more on %p; moving to %p" : "SendResponses: Nothing more on %p"; 2803 debugf(msg, intf, next); 2804 #endif 2805 intf = next; 2806 pktcount = 0; // When we move to a new interface, reset packet count back to zero -- NSEC generation logic uses it 2807 } 2808 } 2809 2810 // *** 2811 // *** 3. Cleanup: Now that everything is sent, call client callback functions, and reset state variables 2812 // *** 2813 2814 if (m->CurrentRecord) 2815 LogMsg("SendResponses ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord)); 2816 m->CurrentRecord = m->ResourceRecords; 2817 while (m->CurrentRecord) 2818 { 2819 rr = m->CurrentRecord; 2820 m->CurrentRecord = rr->next; 2821 2822 if (rr->SendRNow) 2823 { 2824 if (rr->ARType != AuthRecordLocalOnly && rr->ARType != AuthRecordP2P) 2825 LogInfo("SendResponses: No active interface %d to send: %d %02X %s", 2826 (uint32_t)rr->SendRNow, (uint32_t)rr->resrec.InterfaceID, rr->resrec.RecordType, ARDisplayString(m, rr)); 2827 rr->SendRNow = mDNSNULL; 2828 } 2829 2830 if (rr->ImmedAnswer || rr->resrec.RecordType == kDNSRecordTypeDeregistering) 2831 { 2832 if (rr->NewRData) CompleteRDataUpdate(m, rr); // Update our rdata, clear the NewRData pointer, and return memory to the client 2833 2834 if (rr->resrec.RecordType == kDNSRecordTypeDeregistering && rr->AnnounceCount == 0) 2835 { 2836 // For Unicast, when we get the response from the server, we will call CompleteDeregistration 2837 if (!AuthRecord_uDNS(rr)) CompleteDeregistration(m, rr); // Don't touch rr after this 2838 } 2839 else 2840 { 2841 rr->ImmedAnswer = mDNSNULL; 2842 rr->ImmedUnicast = mDNSfalse; 2843 rr->v4Requester = zerov4Addr; 2844 rr->v6Requester = zerov6Addr; 2845 } 2846 } 2847 } 2848 verbosedebugf("SendResponses: Next in %ld ticks", m->NextScheduledResponse - m->timenow); 2849 } 2850 2851 // Calling CheckCacheExpiration() is an expensive operation because it has to look at the entire cache, 2852 // so we want to be lazy about how frequently we do it. 2853 // 1. If a cache record is currently referenced by *no* active questions, 2854 // then we don't mind expiring it up to a minute late (who will know?) 2855 // 2. Else, if a cache record is due for some of its final expiration queries, 2856 // we'll allow them to be late by up to 2% of the TTL 2857 // 3. Else, if a cache record has completed all its final expiration queries without success, 2858 // and is expiring, and had an original TTL more than ten seconds, we'll allow it to be one second late 2859 // 4. Else, it is expiring and had an original TTL of ten seconds or less (includes explicit goodbye packets), 2860 // so allow at most 1/10 second lateness 2861 // 5. For records with rroriginalttl set to zero, that means we really want to delete them immediately 2862 // (we have a new record with DelayDelivery set, waiting for the old record to go away before we can notify clients). 2863 #define CacheCheckGracePeriod(RR) ( \ 2864 ((RR)->CRActiveQuestion == mDNSNULL ) ? (60 * mDNSPlatformOneSecond) : \ 2865 ((RR)->UnansweredQueries < MaxUnansweredQueries) ? (TicksTTL(rr)/50) : \ 2866 ((RR)->resrec.rroriginalttl > 10 ) ? (mDNSPlatformOneSecond) : \ 2867 ((RR)->resrec.rroriginalttl > 0 ) ? (mDNSPlatformOneSecond/10) : 0) 2868 2869 #define NextCacheCheckEvent(RR) ((RR)->NextRequiredQuery + CacheCheckGracePeriod(RR)) 2870 2871 mDNSexport void ScheduleNextCacheCheckTime(mDNS *const m, const mDNSu32 slot, const mDNSs32 event) 2872 { 2873 if (m->rrcache_nextcheck[slot] - event > 0) 2874 m->rrcache_nextcheck[slot] = event; 2875 if (m->NextCacheCheck - event > 0) 2876 m->NextCacheCheck = event; 2877 } 2878 2879 // Note: MUST call SetNextCacheCheckTimeForRecord any time we change: 2880 // rr->TimeRcvd 2881 // rr->resrec.rroriginalttl 2882 // rr->UnansweredQueries 2883 // rr->CRActiveQuestion 2884 mDNSexport void SetNextCacheCheckTimeForRecord(mDNS *const m, CacheRecord *const rr) 2885 { 2886 rr->NextRequiredQuery = RRExpireTime(rr); 2887 2888 // If we have an active question, then see if we want to schedule a refresher query for this record. 2889 // Usually we expect to do four queries, at 80-82%, 85-87%, 90-92% and then 95-97% of the TTL. 2890 if (rr->CRActiveQuestion && rr->UnansweredQueries < MaxUnansweredQueries) 2891 { 2892 rr->NextRequiredQuery -= TicksTTL(rr)/20 * (MaxUnansweredQueries - rr->UnansweredQueries); 2893 rr->NextRequiredQuery += mDNSRandom((mDNSu32)TicksTTL(rr)/50); 2894 verbosedebugf("SetNextCacheCheckTimeForRecord: NextRequiredQuery in %ld sec CacheCheckGracePeriod %d ticks for %s", 2895 (rr->NextRequiredQuery - m->timenow) / mDNSPlatformOneSecond, CacheCheckGracePeriod(rr), CRDisplayString(m,rr)); 2896 } 2897 ScheduleNextCacheCheckTime(m, HashSlot(rr->resrec.name), NextCacheCheckEvent(rr)); 2898 } 2899 2900 #define kMinimumReconfirmTime ((mDNSu32)mDNSPlatformOneSecond * 5) 2901 #define kDefaultReconfirmTimeForWake ((mDNSu32)mDNSPlatformOneSecond * 5) 2902 #define kDefaultReconfirmTimeForNoAnswer ((mDNSu32)mDNSPlatformOneSecond * 5) 2903 #define kDefaultReconfirmTimeForFlappingInterface ((mDNSu32)mDNSPlatformOneSecond * 5) 2904 2905 mDNSexport mStatus mDNS_Reconfirm_internal(mDNS *const m, CacheRecord *const rr, mDNSu32 interval) 2906 { 2907 if (interval < kMinimumReconfirmTime) 2908 interval = kMinimumReconfirmTime; 2909 if (interval > 0x10000000) // Make sure interval doesn't overflow when we multiply by four below 2910 interval = 0x10000000; 2911 2912 // If the expected expiration time for this record is more than interval+33%, then accelerate its expiration 2913 if (RRExpireTime(rr) - m->timenow > (mDNSs32)((interval * 4) / 3)) 2914 { 2915 // Add a 33% random amount to the interval, to avoid synchronization between multiple hosts 2916 // For all the reconfirmations in a given batch, we want to use the same random value 2917 // so that the reconfirmation questions can be grouped into a single query packet 2918 if (!m->RandomReconfirmDelay) m->RandomReconfirmDelay = 1 + mDNSRandom(0x3FFFFFFF); 2919 interval += m->RandomReconfirmDelay % ((interval/3) + 1); 2920 rr->TimeRcvd = m->timenow - (mDNSs32)interval * 3; 2921 rr->resrec.rroriginalttl = (interval * 4 + mDNSPlatformOneSecond - 1) / mDNSPlatformOneSecond; 2922 SetNextCacheCheckTimeForRecord(m, rr); 2923 } 2924 debugf("mDNS_Reconfirm_internal:%6ld ticks to go for %s %p", 2925 RRExpireTime(rr) - m->timenow, CRDisplayString(m, rr), rr->CRActiveQuestion); 2926 return(mStatus_NoError); 2927 } 2928 2929 // BuildQuestion puts a question into a DNS Query packet and if successful, updates the value of queryptr. 2930 // It also appends to the list of known answer records that need to be included, 2931 // and updates the forcast for the size of the known answer section. 2932 mDNSlocal mDNSBool BuildQuestion(mDNS *const m, DNSMessage *query, mDNSu8 **queryptr, DNSQuestion *q, 2933 CacheRecord ***kalistptrptr, mDNSu32 *answerforecast) 2934 { 2935 mDNSBool ucast = (q->LargeAnswers || q->RequestUnicast) && m->CanReceiveUnicastOn5353; 2936 mDNSu16 ucbit = (mDNSu16)(ucast ? kDNSQClass_UnicastResponse : 0); 2937 const mDNSu8 *const limit = query->data + NormalMaxDNSMessageData; 2938 mDNSu8 anoninfo_space = q->AnonInfo ? AnonInfoSpace(q->AnonInfo) : 0; 2939 mDNSu8 *newptr = putQuestion(query, *queryptr, limit - *answerforecast - anoninfo_space, &q->qname, q->qtype, (mDNSu16)(q->qclass | ucbit)); 2940 if (!newptr) 2941 { 2942 debugf("BuildQuestion: No more space in this packet for question %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 2943 return(mDNSfalse); 2944 } 2945 else 2946 { 2947 mDNSu32 forecast = *answerforecast + anoninfo_space; 2948 const mDNSu32 slot = HashSlot(&q->qname); 2949 const CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); 2950 CacheRecord *rr; 2951 CacheRecord **ka = *kalistptrptr; // Make a working copy of the pointer we're going to update 2952 2953 for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) // If we have a resource record in our cache, 2954 if (rr->resrec.InterfaceID == q->SendQNow && // received on this interface 2955 !(rr->resrec.RecordType & kDNSRecordTypeUniqueMask) && // which is a shared (i.e. not unique) record type 2956 rr->NextInKAList == mDNSNULL && ka != &rr->NextInKAList && // which is not already in the known answer list 2957 rr->resrec.rdlength <= SmallRecordLimit && // which is small enough to sensibly fit in the packet 2958 SameNameRecordAnswersQuestion(&rr->resrec, q) && // which answers our question 2959 rr->TimeRcvd + TicksTTL(rr)/2 - m->timenow > // and its half-way-to-expiry time is at least 1 second away 2960 mDNSPlatformOneSecond) // (also ensures we never include goodbye records with TTL=1) 2961 { 2962 // We don't want to include unique records in the Known Answer section. The Known Answer section 2963 // is intended to suppress floods of shared-record replies from many other devices on the network. 2964 // That concept really does not apply to unique records, and indeed if we do send a query for 2965 // which we have a unique record already in our cache, then including that unique record as a 2966 // Known Answer, so as to suppress the only answer we were expecting to get, makes little sense. 2967 2968 *ka = rr; // Link this record into our known answer chain 2969 ka = &rr->NextInKAList; 2970 // We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n) 2971 forecast += 12 + rr->resrec.rdestimate; 2972 // If we're trying to put more than one question in this packet, and it doesn't fit 2973 // then undo that last question and try again next time 2974 if (query->h.numQuestions > 1 && newptr + forecast >= limit) 2975 { 2976 query->h.numQuestions--; 2977 debugf("BuildQuestion: Retracting question %##s (%s) new forecast total %d, total questions %d", 2978 q->qname.c, DNSTypeName(q->qtype), newptr + forecast - query->data, query->h.numQuestions); 2979 ka = *kalistptrptr; // Go back to where we started and retract these answer records 2980 while (*ka) { CacheRecord *c = *ka; *ka = mDNSNULL; ka = &c->NextInKAList; } 2981 return(mDNSfalse); // Return false, so we'll try again in the next packet 2982 } 2983 } 2984 2985 // Success! Update our state pointers, increment UnansweredQueries as appropriate, and return 2986 *queryptr = newptr; // Update the packet pointer 2987 *answerforecast = forecast; // Update the forecast 2988 *kalistptrptr = ka; // Update the known answer list pointer 2989 if (ucast) q->ExpectUnicastResp = NonZeroTime(m->timenow); 2990 2991 for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) // For every resource record in our cache, 2992 if (rr->resrec.InterfaceID == q->SendQNow && // received on this interface 2993 rr->NextInKAList == mDNSNULL && ka != &rr->NextInKAList && // which is not in the known answer list 2994 SameNameRecordAnswersQuestion(&rr->resrec, q)) // which answers our question 2995 { 2996 rr->UnansweredQueries++; // indicate that we're expecting a response 2997 rr->LastUnansweredTime = m->timenow; 2998 SetNextCacheCheckTimeForRecord(m, rr); 2999 } 3000 3001 return(mDNStrue); 3002 } 3003 } 3004 3005 // When we have a query looking for a specified name, but there appear to be no answers with 3006 // that name, ReconfirmAntecedents() is called with depth=0 to start the reconfirmation process 3007 // for any records in our cache that reference the given name (e.g. PTR and SRV records). 3008 // For any such cache record we find, we also recursively call ReconfirmAntecedents() for *its* name. 3009 // We increment depth each time we recurse, to guard against possible infinite loops, with a limit of 5. 3010 // A typical reconfirmation scenario might go like this: 3011 // Depth 0: Name "myhost.local" has no address records 3012 // Depth 1: SRV "My Service._example._tcp.local." refers to "myhost.local"; may be stale 3013 // Depth 2: PTR "_example._tcp.local." refers to "My Service"; may be stale 3014 // Depth 3: PTR "_services._dns-sd._udp.local." refers to "_example._tcp.local."; may be stale 3015 // Currently depths 4 and 5 are not expected to occur; if we did get to depth 5 we'd reconfim any records we 3016 // found referring to the given name, but not recursively descend any further reconfirm *their* antecedents. 3017 mDNSlocal void ReconfirmAntecedents(mDNS *const m, const domainname *const name, const mDNSu32 namehash, const int depth) 3018 { 3019 mDNSu32 slot; 3020 CacheGroup *cg; 3021 CacheRecord *cr; 3022 debugf("ReconfirmAntecedents (depth=%d) for %##s", depth, name->c); 3023 FORALL_CACHERECORDS(slot, cg, cr) 3024 { 3025 domainname *crtarget = GetRRDomainNameTarget(&cr->resrec); 3026 if (crtarget && cr->resrec.rdatahash == namehash && SameDomainName(crtarget, name)) 3027 { 3028 LogInfo("ReconfirmAntecedents: Reconfirming (depth=%d) %s", depth, CRDisplayString(m, cr)); 3029 mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer); 3030 if (depth < 5) 3031 ReconfirmAntecedents(m, cr->resrec.name, cr->resrec.namehash, depth+1); 3032 } 3033 } 3034 } 3035 3036 // If we get no answer for a AAAA query, then before doing an automatic implicit ReconfirmAntecedents 3037 // we check if we have an address record for the same name. If we do have an IPv4 address for a given 3038 // name but not an IPv6 address, that's okay (it just means the device doesn't do IPv6) so the failure 3039 // to get a AAAA response is not grounds to doubt the PTR/SRV chain that lead us to that name. 3040 mDNSlocal const CacheRecord *CacheHasAddressTypeForName(mDNS *const m, const domainname *const name, const mDNSu32 namehash) 3041 { 3042 CacheGroup *const cg = CacheGroupForName(m, HashSlot(name), namehash, name); 3043 const CacheRecord *cr = cg ? cg->members : mDNSNULL; 3044 while (cr && !RRTypeIsAddressType(cr->resrec.rrtype)) cr=cr->next; 3045 return(cr); 3046 } 3047 3048 3049 mDNSlocal const CacheRecord *FindSPSInCache1(mDNS *const m, const DNSQuestion *const q, const CacheRecord *const c0, const CacheRecord *const c1) 3050 { 3051 #ifndef SPC_DISABLED 3052 CacheGroup *const cg = CacheGroupForName(m, HashSlot(&q->qname), q->qnamehash, &q->qname); 3053 const CacheRecord *cr, *bestcr = mDNSNULL; 3054 mDNSu32 bestmetric = 1000000; 3055 for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next) 3056 if (cr->resrec.rrtype == kDNSType_PTR && cr->resrec.rdlength >= 6) // If record is PTR type, with long enough name, 3057 if (cr != c0 && cr != c1) // that's not one we've seen before, 3058 if (SameNameRecordAnswersQuestion(&cr->resrec, q)) // and answers our browse query, 3059 if (!IdenticalSameNameRecord(&cr->resrec, &m->SPSRecords.RR_PTR.resrec)) // and is not our own advertised service... 3060 { 3061 mDNSu32 metric = SPSMetric(cr->resrec.rdata->u.name.c); 3062 if (bestmetric > metric) { bestmetric = metric; bestcr = cr; } 3063 } 3064 return(bestcr); 3065 #else // SPC_DISABLED 3066 (void) m; 3067 (void) q; 3068 (void) c0; 3069 (void) c1; 3070 (void) c1; 3071 return mDNSNULL; 3072 #endif // SPC_DISABLED 3073 } 3074 3075 mDNSlocal void CheckAndSwapSPS(const CacheRecord *sps1, const CacheRecord *sps2) 3076 { 3077 const CacheRecord *swap_sps; 3078 mDNSu32 metric1, metric2; 3079 3080 if (!sps1 || !sps2) return; 3081 metric1 = SPSMetric(sps1->resrec.rdata->u.name.c); 3082 metric2 = SPSMetric(sps2->resrec.rdata->u.name.c); 3083 if (!SPSFeatures(sps1->resrec.rdata->u.name.c) && SPSFeatures(sps2->resrec.rdata->u.name.c) && (metric2 >= metric1)) 3084 { 3085 swap_sps = sps1; 3086 sps1 = sps2; 3087 sps2 = swap_sps; 3088 } 3089 } 3090 3091 mDNSlocal void ReorderSPSByFeature(const CacheRecord *sps[3]) 3092 { 3093 CheckAndSwapSPS(sps[0], sps[1]); 3094 CheckAndSwapSPS(sps[0], sps[2]); 3095 CheckAndSwapSPS(sps[1], sps[2]); 3096 } 3097 3098 3099 // Finds the three best Sleep Proxies we currently have in our cache 3100 mDNSexport void FindSPSInCache(mDNS *const m, const DNSQuestion *const q, const CacheRecord *sps[3]) 3101 { 3102 sps[0] = FindSPSInCache1(m, q, mDNSNULL, mDNSNULL); 3103 sps[1] = !sps[0] ? mDNSNULL : FindSPSInCache1(m, q, sps[0], mDNSNULL); 3104 sps[2] = !sps[1] ? mDNSNULL : FindSPSInCache1(m, q, sps[0], sps[1]); 3105 3106 // SPS is already sorted by metric. We want to move the entries to the beginning of the array 3107 // only if they have equally good metric and support features. 3108 ReorderSPSByFeature(sps); 3109 } 3110 3111 // Only DupSuppressInfos newer than the specified 'time' are allowed to remain active 3112 mDNSlocal void ExpireDupSuppressInfo(DupSuppressInfo ds[DupSuppressInfoSize], mDNSs32 time) 3113 { 3114 int i; 3115 for (i=0; i<DupSuppressInfoSize; i++) if (ds[i].Time - time < 0) ds[i].InterfaceID = mDNSNULL; 3116 } 3117 3118 mDNSlocal void ExpireDupSuppressInfoOnInterface(DupSuppressInfo ds[DupSuppressInfoSize], mDNSs32 time, mDNSInterfaceID InterfaceID) 3119 { 3120 int i; 3121 for (i=0; i<DupSuppressInfoSize; i++) if (ds[i].InterfaceID == InterfaceID && ds[i].Time - time < 0) ds[i].InterfaceID = mDNSNULL; 3122 } 3123 3124 mDNSlocal mDNSBool SuppressOnThisInterface(const DupSuppressInfo ds[DupSuppressInfoSize], const NetworkInterfaceInfo * const intf) 3125 { 3126 int i; 3127 mDNSBool v4 = !intf->IPv4Available; // If this interface doesn't do v4, we don't need to find a v4 duplicate of this query 3128 mDNSBool v6 = !intf->IPv6Available; // If this interface doesn't do v6, we don't need to find a v6 duplicate of this query 3129 for (i=0; i<DupSuppressInfoSize; i++) 3130 if (ds[i].InterfaceID == intf->InterfaceID) 3131 { 3132 if (ds[i].Type == mDNSAddrType_IPv4) v4 = mDNStrue; 3133 else if (ds[i].Type == mDNSAddrType_IPv6) v6 = mDNStrue; 3134 if (v4 && v6) return(mDNStrue); 3135 } 3136 return(mDNSfalse); 3137 } 3138 3139 mDNSlocal int RecordDupSuppressInfo(DupSuppressInfo ds[DupSuppressInfoSize], mDNSs32 Time, mDNSInterfaceID InterfaceID, mDNSs32 Type) 3140 { 3141 int i, j; 3142 3143 // See if we have this one in our list somewhere already 3144 for (i=0; i<DupSuppressInfoSize; i++) if (ds[i].InterfaceID == InterfaceID && ds[i].Type == Type) break; 3145 3146 // If not, find a slot we can re-use 3147 if (i >= DupSuppressInfoSize) 3148 { 3149 i = 0; 3150 for (j=1; j<DupSuppressInfoSize && ds[i].InterfaceID; j++) 3151 if (!ds[j].InterfaceID || ds[j].Time - ds[i].Time < 0) 3152 i = j; 3153 } 3154 3155 // Record the info about this query we saw 3156 ds[i].Time = Time; 3157 ds[i].InterfaceID = InterfaceID; 3158 ds[i].Type = Type; 3159 3160 return(i); 3161 } 3162 3163 mDNSlocal void mDNSSendWakeOnResolve(mDNS *const m, DNSQuestion *q) 3164 { 3165 int len, i, cnt; 3166 mDNSInterfaceID InterfaceID = q->InterfaceID; 3167 domainname *d = &q->qname; 3168 3169 // We can't send magic packets without knowing which interface to send it on. 3170 if (InterfaceID == mDNSInterface_Any || InterfaceID == mDNSInterface_LocalOnly || InterfaceID == mDNSInterface_P2P) 3171 { 3172 LogMsg("mDNSSendWakeOnResolve: ERROR!! Invalid InterfaceID %p for question %##s", InterfaceID, q->qname.c); 3173 return; 3174 } 3175 3176 // Split MAC@IPAddress and pass them separately 3177 len = d->c[0]; 3178 i = 1; 3179 cnt = 0; 3180 for (i = 1; i < len; i++) 3181 { 3182 if (d->c[i] == '@') 3183 { 3184 char EthAddr[18]; // ethernet adddress : 12 bytes + 5 ":" + 1 NULL byte 3185 char IPAddr[47]; // Max IP address len: 46 bytes (IPv6) + 1 NULL byte 3186 if (cnt != 5) 3187 { 3188 LogMsg("mDNSSendWakeOnResolve: ERROR!! Malformed Ethernet address %##s, cnt %d", q->qname.c, cnt); 3189 return; 3190 } 3191 if ((i - 1) > (int) (sizeof(EthAddr) - 1)) 3192 { 3193 LogMsg("mDNSSendWakeOnResolve: ERROR!! Malformed Ethernet address %##s, length %d", q->qname.c, i - 1); 3194 return; 3195 } 3196 if ((len - i) > (int)(sizeof(IPAddr) - 1)) 3197 { 3198 LogMsg("mDNSSendWakeOnResolve: ERROR!! Malformed IP address %##s, length %d", q->qname.c, len - i); 3199 return; 3200 } 3201 mDNSPlatformMemCopy(EthAddr, &d->c[1], i - 1); 3202 EthAddr[i - 1] = 0; 3203 mDNSPlatformMemCopy(IPAddr, &d->c[i + 1], len - i); 3204 IPAddr[len - i] = 0; 3205 m->mDNSStats.WakeOnResolves++; 3206 mDNSPlatformSendWakeupPacket(m, InterfaceID, EthAddr, IPAddr, InitialWakeOnResolveCount - q->WakeOnResolveCount); 3207 return; 3208 } 3209 else if (d->c[i] == ':') 3210 cnt++; 3211 } 3212 LogMsg("mDNSSendWakeOnResolve: ERROR!! Malformed WakeOnResolve name %##s", q->qname.c); 3213 } 3214 3215 3216 mDNSlocal mDNSBool AccelerateThisQuery(mDNS *const m, DNSQuestion *q) 3217 { 3218 // If more than 90% of the way to the query time, we should unconditionally accelerate it 3219 if (TimeToSendThisQuestion(q, m->timenow + q->ThisQInterval/10)) 3220 return(mDNStrue); 3221 3222 // If half-way to next scheduled query time, only accelerate if it will add less than 512 bytes to the packet 3223 if (TimeToSendThisQuestion(q, m->timenow + q->ThisQInterval/2)) 3224 { 3225 // We forecast: qname (n) type (2) class (2) 3226 mDNSu32 forecast = (mDNSu32)DomainNameLength(&q->qname) + 4; 3227 const mDNSu32 slot = HashSlot(&q->qname); 3228 const CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); 3229 const CacheRecord *rr; 3230 for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) // If we have a resource record in our cache, 3231 if (rr->resrec.rdlength <= SmallRecordLimit && // which is small enough to sensibly fit in the packet 3232 SameNameRecordAnswersQuestion(&rr->resrec, q) && // which answers our question 3233 rr->TimeRcvd + TicksTTL(rr)/2 - m->timenow >= 0 && // and it is less than half-way to expiry 3234 rr->NextRequiredQuery - (m->timenow + q->ThisQInterval) > 0) // and we'll ask at least once again before NextRequiredQuery 3235 { 3236 // We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n) 3237 forecast += 12 + rr->resrec.rdestimate; 3238 if (forecast >= 512) return(mDNSfalse); // If this would add 512 bytes or more to the packet, don't accelerate 3239 } 3240 return(mDNStrue); 3241 } 3242 3243 return(mDNSfalse); 3244 } 3245 3246 // How Standard Queries are generated: 3247 // 1. The Question Section contains the question 3248 // 2. The Additional Section contains answers we already know, to suppress duplicate responses 3249 3250 // How Probe Queries are generated: 3251 // 1. The Question Section contains queries for the name we intend to use, with QType=ANY because 3252 // if some other host is already using *any* records with this name, we want to know about it. 3253 // 2. The Authority Section contains the proposed values we intend to use for one or more 3254 // of our records with that name (analogous to the Update section of DNS Update packets) 3255 // because if some other host is probing at the same time, we each want to know what the other is 3256 // planning, in order to apply the tie-breaking rule to see who gets to use the name and who doesn't. 3257 3258 mDNSlocal void SendQueries(mDNS *const m) 3259 { 3260 mDNSu32 slot; 3261 CacheGroup *cg; 3262 CacheRecord *cr; 3263 AuthRecord *ar; 3264 int pktcount = 0; 3265 DNSQuestion *q; 3266 // For explanation of maxExistingQuestionInterval logic, see comments for maxExistingAnnounceInterval 3267 mDNSs32 maxExistingQuestionInterval = 0; 3268 const NetworkInterfaceInfo *intf = GetFirstActiveInterface(m->HostInterfaces); 3269 CacheRecord *KnownAnswerList = mDNSNULL; 3270 3271 // 1. If time for a query, work out what we need to do 3272 3273 // We're expecting to send a query anyway, so see if any expiring cache records are close enough 3274 // to their NextRequiredQuery to be worth batching them together with this one 3275 FORALL_CACHERECORDS(slot, cg, cr) 3276 { 3277 if (cr->CRActiveQuestion && cr->UnansweredQueries < MaxUnansweredQueries) 3278 { 3279 if (m->timenow + TicksTTL(cr)/50 - cr->NextRequiredQuery >= 0) 3280 { 3281 debugf("Sending %d%% cache expiration query for %s", 80 + 5 * cr->UnansweredQueries, CRDisplayString(m, cr)); 3282 q = cr->CRActiveQuestion; 3283 ExpireDupSuppressInfoOnInterface(q->DupSuppress, m->timenow - TicksTTL(cr)/20, cr->resrec.InterfaceID); 3284 // For uDNS queries (TargetQID non-zero) we adjust LastQTime, 3285 // and bump UnansweredQueries so that we don't spin trying to send the same cache expiration query repeatedly 3286 if (q->Target.type) 3287 { 3288 q->SendQNow = mDNSInterfaceMark; // If targeted query, mark it 3289 } 3290 else if (!mDNSOpaque16IsZero(q->TargetQID)) 3291 { 3292 q->LastQTime = m->timenow - q->ThisQInterval; 3293 cr->UnansweredQueries++; 3294 m->mDNSStats.CacheRefreshQueries++; 3295 } 3296 else if (q->SendQNow == mDNSNULL) 3297 { 3298 q->SendQNow = cr->resrec.InterfaceID; 3299 } 3300 else if (q->SendQNow != cr->resrec.InterfaceID) 3301 { 3302 q->SendQNow = mDNSInterfaceMark; 3303 } 3304 3305 // Indicate that this question was marked for sending 3306 // to update an existing cached answer record. 3307 // The browse throttling logic below uses this to determine 3308 // if the query should be sent. 3309 if (mDNSOpaque16IsZero(q->TargetQID)) 3310 q->CachedAnswerNeedsUpdate = mDNStrue; 3311 } 3312 } 3313 } 3314 3315 // Scan our list of questions to see which: 3316 // *WideArea* queries need to be sent 3317 // *unicast* queries need to be sent 3318 // *multicast* queries we're definitely going to send 3319 if (m->CurrentQuestion) 3320 LogMsg("SendQueries ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype)); 3321 m->CurrentQuestion = m->Questions; 3322 while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions) 3323 { 3324 q = m->CurrentQuestion; 3325 if (q->Target.type && (q->SendQNow || TimeToSendThisQuestion(q, m->timenow))) 3326 { 3327 mDNSu8 *qptr = m->omsg.data; 3328 const mDNSu8 *const limit = m->omsg.data + sizeof(m->omsg.data); 3329 3330 // If we fail to get a new on-demand socket (should only happen cases of the most extreme resource exhaustion), we'll try again next time 3331 if (!q->LocalSocket) q->LocalSocket = mDNSPlatformUDPSocket(m, zeroIPPort); 3332 if (q->LocalSocket) 3333 { 3334 InitializeDNSMessage(&m->omsg.h, q->TargetQID, QueryFlags); 3335 qptr = putQuestion(&m->omsg, qptr, limit, &q->qname, q->qtype, q->qclass); 3336 mDNSSendDNSMessage(m, &m->omsg, qptr, mDNSInterface_Any, q->LocalSocket, &q->Target, q->TargetPort, mDNSNULL, mDNSNULL, q->UseBackgroundTrafficClass); 3337 q->ThisQInterval *= QuestionIntervalStep; 3338 } 3339 if (q->ThisQInterval > MaxQuestionInterval) 3340 q->ThisQInterval = MaxQuestionInterval; 3341 q->LastQTime = m->timenow; 3342 q->LastQTxTime = m->timenow; 3343 q->RecentAnswerPkts = 0; 3344 q->SendQNow = mDNSNULL; 3345 q->ExpectUnicastResp = NonZeroTime(m->timenow); 3346 } 3347 else if (mDNSOpaque16IsZero(q->TargetQID) && !q->Target.type && TimeToSendThisQuestion(q, m->timenow)) 3348 { 3349 //LogInfo("Time to send %##s (%s) %d", q->qname.c, DNSTypeName(q->qtype), m->timenow - NextQSendTime(q)); 3350 q->SendQNow = mDNSInterfaceMark; // Mark this question for sending on all interfaces 3351 if (maxExistingQuestionInterval < q->ThisQInterval) 3352 maxExistingQuestionInterval = q->ThisQInterval; 3353 } 3354 // If m->CurrentQuestion wasn't modified out from under us, advance it now 3355 // We can't do this at the start of the loop because uDNS_CheckCurrentQuestion() depends on having 3356 // m->CurrentQuestion point to the right question 3357 if (q == m->CurrentQuestion) m->CurrentQuestion = m->CurrentQuestion->next; 3358 } 3359 while (m->CurrentQuestion) 3360 { 3361 LogInfo("SendQueries question loop 1: Skipping NewQuestion %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype)); 3362 m->CurrentQuestion = m->CurrentQuestion->next; 3363 } 3364 m->CurrentQuestion = mDNSNULL; 3365 3366 // Scan our list of questions 3367 // (a) to see if there are any more that are worth accelerating, and 3368 // (b) to update the state variables for *all* the questions we're going to send 3369 // Note: Don't set NextScheduledQuery until here, because uDNS_CheckCurrentQuestion in the loop above can add new questions to the list, 3370 // which causes NextScheduledQuery to get (incorrectly) set to m->timenow. Setting it here is the right place, because the very 3371 // next thing we do is scan the list and call SetNextQueryTime() for every question we find, so we know we end up with the right value. 3372 m->NextScheduledQuery = m->timenow + 0x78000000; 3373 for (q = m->Questions; q && q != m->NewQuestions; q=q->next) 3374 { 3375 if (mDNSOpaque16IsZero(q->TargetQID) 3376 && (q->SendQNow || (!q->Target.type && ActiveQuestion(q) && q->ThisQInterval <= maxExistingQuestionInterval && AccelerateThisQuery(m,q)))) 3377 { 3378 // If at least halfway to next query time, advance to next interval 3379 // If less than halfway to next query time, then 3380 // treat this as logically a repeat of the last transmission, without advancing the interval 3381 if (m->timenow - (q->LastQTime + (q->ThisQInterval/2)) >= 0) 3382 { 3383 // If we have reached the answer threshold for this question, 3384 // don't send it again until MaxQuestionInterval unless: 3385 // one of its cached answers needs to be refreshed, 3386 // or it's the initial query for a kDNSServiceFlagsThresholdFinder mode browse. 3387 if (q->BrowseThreshold 3388 && (q->CurrentAnswers >= q->BrowseThreshold) 3389 && (q->CachedAnswerNeedsUpdate == mDNSfalse) 3390 && !((q->flags & kDNSServiceFlagsThresholdFinder) && (q->ThisQInterval == InitialQuestionInterval))) 3391 { 3392 q->SendQNow = mDNSNULL; 3393 q->ThisQInterval = MaxQuestionInterval; 3394 q->LastQTime = m->timenow; 3395 q->RequestUnicast = 0; 3396 LogInfo("SendQueries: (%s) %##s reached threshold of %d answers", 3397 DNSTypeName(q->qtype), q->qname.c, q->BrowseThreshold); 3398 } 3399 else 3400 { 3401 // Mark this question for sending on all interfaces 3402 q->SendQNow = mDNSInterfaceMark; 3403 q->ThisQInterval *= QuestionIntervalStep; 3404 } 3405 3406 debugf("SendQueries: %##s (%s) next interval %d seconds RequestUnicast = %d", 3407 q->qname.c, DNSTypeName(q->qtype), q->ThisQInterval / InitialQuestionInterval, q->RequestUnicast); 3408 3409 if (q->ThisQInterval >= QuestionIntervalThreshold) 3410 { 3411 q->ThisQInterval = MaxQuestionInterval; 3412 } 3413 else if (q->CurrentAnswers == 0 && q->ThisQInterval == InitialQuestionInterval * QuestionIntervalStep3 && !q->RequestUnicast && 3414 !(RRTypeIsAddressType(q->qtype) && CacheHasAddressTypeForName(m, &q->qname, q->qnamehash))) 3415 { 3416 // Generally don't need to log this. 3417 // It's not especially noteworthy if a query finds no results -- this usually happens for domain 3418 // enumeration queries in the LL subdomain (e.g. "db._dns-sd._udp.0.0.254.169.in-addr.arpa") 3419 // and when there simply happen to be no instances of the service the client is looking 3420 // for (e.g. iTunes is set to look for RAOP devices, and the current network has none). 3421 debugf("SendQueries: Zero current answers for %##s (%s); will reconfirm antecedents", 3422 q->qname.c, DNSTypeName(q->qtype)); 3423 // Sending third query, and no answers yet; time to begin doubting the source 3424 ReconfirmAntecedents(m, &q->qname, q->qnamehash, 0); 3425 } 3426 } 3427 3428 // Mark for sending. (If no active interfaces, then don't even try.) 3429 q->SendOnAll = (q->SendQNow == mDNSInterfaceMark); 3430 if (q->SendOnAll) 3431 { 3432 q->SendQNow = !intf ? mDNSNULL : (q->InterfaceID) ? q->InterfaceID : intf->InterfaceID; 3433 q->LastQTime = m->timenow; 3434 } 3435 3436 // If we recorded a duplicate suppression for this question less than half an interval ago, 3437 // then we consider it recent enough that we don't need to do an identical query ourselves. 3438 ExpireDupSuppressInfo(q->DupSuppress, m->timenow - q->ThisQInterval/2); 3439 3440 q->LastQTxTime = m->timenow; 3441 q->RecentAnswerPkts = 0; 3442 if (q->RequestUnicast) q->RequestUnicast--; 3443 } 3444 // For all questions (not just the ones we're sending) check what the next scheduled event will be 3445 // We don't need to consider NewQuestions here because for those we'll set m->NextScheduledQuery in AnswerNewQuestion 3446 SetNextQueryTime(m,q); 3447 } 3448 3449 // 2. Scan our authoritative RR list to see what probes we might need to send 3450 3451 m->NextScheduledProbe = m->timenow + 0x78000000; 3452 3453 if (m->CurrentRecord) 3454 LogMsg("SendQueries ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord)); 3455 m->CurrentRecord = m->ResourceRecords; 3456 while (m->CurrentRecord) 3457 { 3458 ar = m->CurrentRecord; 3459 m->CurrentRecord = ar->next; 3460 if (!AuthRecord_uDNS(ar) && ar->resrec.RecordType == kDNSRecordTypeUnique) // For all records that are still probing... 3461 { 3462 // 1. If it's not reached its probe time, just make sure we update m->NextScheduledProbe correctly 3463 if (m->timenow - (ar->LastAPTime + ar->ThisAPInterval) < 0) 3464 { 3465 SetNextAnnounceProbeTime(m, ar); 3466 } 3467 // 2. else, if it has reached its probe time, mark it for sending and then update m->NextScheduledProbe correctly 3468 else if (ar->ProbeCount) 3469 { 3470 if (ar->AddressProxy.type == mDNSAddrType_IPv4) 3471 { 3472 // There's a problem here. If a host is waking up, and we probe to see if it responds, then 3473 // it will see those ARP probes as signalling intent to use the address, so it picks a different one. 3474 // A more benign way to find out if a host is responding to ARPs might be send a standard ARP *request* 3475 // (using our sender IP address) instead of an ARP *probe* (using all-zero sender IP address). 3476 // A similar concern may apply to the NDP Probe too. -- SC 3477 LogSPS("SendQueries ARP Probe %d %s %s", ar->ProbeCount, InterfaceNameForID(m, ar->resrec.InterfaceID), ARDisplayString(m,ar)); 3478 SendARP(m, 1, ar, &zerov4Addr, &zeroEthAddr, &ar->AddressProxy.ip.v4, &ar->WakeUp.IMAC); 3479 } 3480 else if (ar->AddressProxy.type == mDNSAddrType_IPv6) 3481 { 3482 LogSPS("SendQueries NDP Probe %d %s %s", ar->ProbeCount, InterfaceNameForID(m, ar->resrec.InterfaceID), ARDisplayString(m,ar)); 3483 // IPv6 source = zero 3484 // No target hardware address 3485 // IPv6 target address is address we're probing 3486 // Ethernet destination address is Ethernet interface address of the Sleep Proxy client we're probing 3487 SendNDP(m, NDP_Sol, 0, ar, &zerov6Addr, mDNSNULL, &ar->AddressProxy.ip.v6, &ar->WakeUp.IMAC); 3488 } 3489 // Mark for sending. (If no active interfaces, then don't even try.) 3490 ar->SendRNow = (!intf || ar->WakeUp.HMAC.l[0]) ? mDNSNULL : ar->resrec.InterfaceID ? ar->resrec.InterfaceID : intf->InterfaceID; 3491 ar->LastAPTime = m->timenow; 3492 // When we have a late conflict that resets a record to probing state we use a special marker value greater 3493 // than DefaultProbeCountForTypeUnique. Here we detect that state and reset ar->ProbeCount back to the right value. 3494 if (ar->ProbeCount > DefaultProbeCountForTypeUnique) 3495 ar->ProbeCount = DefaultProbeCountForTypeUnique; 3496 ar->ProbeCount--; 3497 SetNextAnnounceProbeTime(m, ar); 3498 if (ar->ProbeCount == 0) 3499 { 3500 // If this is the last probe for this record, then see if we have any matching records 3501 // on our duplicate list which should similarly have their ProbeCount cleared to zero... 3502 AuthRecord *r2; 3503 for (r2 = m->DuplicateRecords; r2; r2=r2->next) 3504 if (r2->resrec.RecordType == kDNSRecordTypeUnique && RecordIsLocalDuplicate(r2, ar)) 3505 r2->ProbeCount = 0; 3506 // ... then acknowledge this record to the client. 3507 // We do this optimistically, just as we're about to send the third probe. 3508 // This helps clients that both advertise and browse, and want to filter themselves 3509 // from the browse results list, because it helps ensure that the registration 3510 // confirmation will be delivered 1/4 second *before* the browse "add" event. 3511 // A potential downside is that we could deliver a registration confirmation and then find out 3512 // moments later that there's a name conflict, but applications have to be prepared to handle 3513 // late conflicts anyway (e.g. on connection of network cable, etc.), so this is nothing new. 3514 if (!ar->Acknowledged) AcknowledgeRecord(m, ar); 3515 } 3516 } 3517 // else, if it has now finished probing, move it to state Verified, 3518 // and update m->NextScheduledResponse so it will be announced 3519 else 3520 { 3521 if (!ar->Acknowledged) AcknowledgeRecord(m, ar); // Defensive, just in case it got missed somehow 3522 ar->resrec.RecordType = kDNSRecordTypeVerified; 3523 ar->ThisAPInterval = DefaultAnnounceIntervalForTypeUnique; 3524 ar->LastAPTime = m->timenow - DefaultAnnounceIntervalForTypeUnique; 3525 SetNextAnnounceProbeTime(m, ar); 3526 } 3527 } 3528 } 3529 m->CurrentRecord = m->DuplicateRecords; 3530 while (m->CurrentRecord) 3531 { 3532 ar = m->CurrentRecord; 3533 m->CurrentRecord = ar->next; 3534 if (ar->resrec.RecordType == kDNSRecordTypeUnique && ar->ProbeCount == 0 && !ar->Acknowledged) 3535 AcknowledgeRecord(m, ar); 3536 } 3537 3538 // 3. Now we know which queries and probes we're sending, 3539 // go through our interface list sending the appropriate queries on each interface 3540 while (intf) 3541 { 3542 int OwnerRecordSpace = (m->AnnounceOwner && intf->MAC.l[0]) ? DNSOpt_Header_Space + DNSOpt_Owner_Space(&m->PrimaryMAC, &intf->MAC) : 0; 3543 int TraceRecordSpace = (mDNS_McastTracingEnabled && MDNS_TRACER) ? DNSOpt_Header_Space + DNSOpt_TraceData_Space : 0; 3544 mDNSu8 *queryptr = m->omsg.data; 3545 mDNSBool useBackgroundTrafficClass = mDNSfalse; // set if we should use background traffic class 3546 3547 InitializeDNSMessage(&m->omsg.h, zeroID, QueryFlags); 3548 if (KnownAnswerList) verbosedebugf("SendQueries: KnownAnswerList set... Will continue from previous packet"); 3549 if (!KnownAnswerList) 3550 { 3551 // Start a new known-answer list 3552 CacheRecord **kalistptr = &KnownAnswerList; 3553 mDNSu32 answerforecast = OwnerRecordSpace + TraceRecordSpace; // Start by assuming we'll need at least enough space to put the Owner+Tracer Option 3554 3555 // Put query questions in this packet 3556 for (q = m->Questions; q && q != m->NewQuestions; q=q->next) 3557 { 3558 if (mDNSOpaque16IsZero(q->TargetQID) && (q->SendQNow == intf->InterfaceID)) 3559 { 3560 mDNSBool Suppress = mDNSfalse; 3561 debugf("SendQueries: %s question for %##s (%s) at %d forecast total %d", 3562 SuppressOnThisInterface(q->DupSuppress, intf) ? "Suppressing" : "Putting ", 3563 q->qname.c, DNSTypeName(q->qtype), queryptr - m->omsg.data, queryptr + answerforecast - m->omsg.data); 3564 3565 // If interface is P2P type, verify that query should be sent over it. 3566 if (!mDNSPlatformValidQuestionForInterface(q, intf)) 3567 { 3568 LogInfo("SendQueries: Not sending (%s) %##s on %s", DNSTypeName(q->qtype), q->qname.c, InterfaceNameForID(m, intf->InterfaceID)); 3569 q->SendQNow = (q->InterfaceID || !q->SendOnAll) ? mDNSNULL : GetNextActiveInterfaceID(intf); 3570 } 3571 // If we're suppressing this question, or we successfully put it, update its SendQNow state 3572 else if ((Suppress = SuppressOnThisInterface(q->DupSuppress, intf)) || 3573 BuildQuestion(m, &m->omsg, &queryptr, q, &kalistptr, &answerforecast)) 3574 { 3575 // We successfully added the question to the packet. Make sure that 3576 // we also send the NSEC3 record if required. BuildQuestion accounted for 3577 // the space. 3578 // 3579 // Note: We don't suppress anonymous questions and hence Suppress should always 3580 // be zero. 3581 3582 if (Suppress) 3583 m->mDNSStats.DupQuerySuppressions++; 3584 3585 if (!Suppress && q->AnonInfo) 3586 { 3587 debugf("SendQueries: marking for question %##s, Suppress %d", q->qname.c, Suppress); 3588 q->AnonInfo->SendNow = intf->InterfaceID; 3589 } 3590 q->SendQNow = (q->InterfaceID || !q->SendOnAll) ? mDNSNULL : GetNextActiveInterfaceID(intf); 3591 if (q->WakeOnResolveCount) 3592 { 3593 mDNSSendWakeOnResolve(m, q); 3594 q->WakeOnResolveCount--; 3595 } 3596 3597 // use brackground traffic class if any included question requires it 3598 if (q->UseBackgroundTrafficClass) 3599 { 3600 useBackgroundTrafficClass = mDNStrue; 3601 } 3602 } 3603 } 3604 } 3605 3606 // Put probe questions in this packet 3607 for (ar = m->ResourceRecords; ar; ar=ar->next) 3608 if (ar->SendRNow == intf->InterfaceID) 3609 { 3610 mDNSBool ucast = (ar->ProbeCount >= DefaultProbeCountForTypeUnique-1) && m->CanReceiveUnicastOn5353; 3611 mDNSu16 ucbit = (mDNSu16)(ucast ? kDNSQClass_UnicastResponse : 0); 3612 const mDNSu8 *const limit = m->omsg.data + (m->omsg.h.numQuestions ? NormalMaxDNSMessageData : AbsoluteMaxDNSMessageData); 3613 // We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n) 3614 mDNSu32 forecast = answerforecast + 12 + ar->resrec.rdestimate; 3615 mDNSu8 *newptr = putQuestion(&m->omsg, queryptr, limit - forecast, ar->resrec.name, kDNSQType_ANY, (mDNSu16)(ar->resrec.rrclass | ucbit)); 3616 if (newptr) 3617 { 3618 queryptr = newptr; 3619 answerforecast = forecast; 3620 ar->SendRNow = (ar->resrec.InterfaceID) ? mDNSNULL : GetNextActiveInterfaceID(intf); 3621 ar->IncludeInProbe = mDNStrue; 3622 verbosedebugf("SendQueries: Put Question %##s (%s) probecount %d", 3623 ar->resrec.name->c, DNSTypeName(ar->resrec.rrtype), ar->ProbeCount); 3624 } 3625 } 3626 } 3627 3628 // Put our known answer list (either new one from this question or questions, or remainder of old one from last time) 3629 while (KnownAnswerList) 3630 { 3631 CacheRecord *ka = KnownAnswerList; 3632 mDNSu32 SecsSinceRcvd = ((mDNSu32)(m->timenow - ka->TimeRcvd)) / mDNSPlatformOneSecond; 3633 mDNSu8 *newptr = PutResourceRecordTTLWithLimit(&m->omsg, queryptr, &m->omsg.h.numAnswers, &ka->resrec, ka->resrec.rroriginalttl - SecsSinceRcvd, 3634 m->omsg.data + NormalMaxDNSMessageData - OwnerRecordSpace - TraceRecordSpace); 3635 if (newptr) 3636 { 3637 verbosedebugf("SendQueries: Put %##s (%s) at %d - %d", 3638 ka->resrec.name->c, DNSTypeName(ka->resrec.rrtype), queryptr - m->omsg.data, newptr - m->omsg.data); 3639 queryptr = newptr; 3640 KnownAnswerList = ka->NextInKAList; 3641 ka->NextInKAList = mDNSNULL; 3642 } 3643 else 3644 { 3645 // If we ran out of space and we have more than one question in the packet, that's an error -- 3646 // we shouldn't have put more than one question if there was a risk of us running out of space. 3647 if (m->omsg.h.numQuestions > 1) 3648 LogMsg("SendQueries: Put %d answers; No more space for known answers", m->omsg.h.numAnswers); 3649 m->omsg.h.flags.b[0] |= kDNSFlag0_TC; 3650 break; 3651 } 3652 } 3653 3654 for (ar = m->ResourceRecords; ar; ar=ar->next) 3655 { 3656 if (ar->IncludeInProbe) 3657 { 3658 mDNSu8 *newptr = PutResourceRecord(&m->omsg, queryptr, &m->omsg.h.numAuthorities, &ar->resrec); 3659 ar->IncludeInProbe = mDNSfalse; 3660 if (newptr) queryptr = newptr; 3661 else LogMsg("SendQueries: How did we fail to have space for the Update record %s", ARDisplayString(m,ar)); 3662 } 3663 } 3664 3665 for (q = m->Questions; q; q = q->next) 3666 { 3667 if (q->AnonInfo && q->AnonInfo->SendNow == intf->InterfaceID) 3668 { 3669 mDNSu8 *newptr = PutResourceRecord(&m->omsg, queryptr, &m->omsg.h.numAuthorities, q->AnonInfo->nsec3RR); 3670 if (newptr) 3671 { 3672 debugf("SendQueries: Added NSEC3 record %s on InterfaceID %p", RRDisplayString(m, q->AnonInfo->nsec3RR), intf->InterfaceID); 3673 queryptr = newptr; 3674 } 3675 else 3676 { 3677 LogMsg("SendQueries: ERROR!! Cannot add NSEC3 record %s on InterfaceID %p", RRDisplayString(m, q->AnonInfo->nsec3RR), intf->InterfaceID); 3678 } 3679 q->AnonInfo->SendNow = mDNSNULL; 3680 } 3681 } 3682 3683 if (queryptr > m->omsg.data) 3684 { 3685 // If we have data to send, add OWNER/TRACER/OWNER+TRACER option if necessary, then send packet 3686 if (OwnerRecordSpace || TraceRecordSpace) 3687 { 3688 AuthRecord opt; 3689 mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL); 3690 opt.resrec.rrclass = NormalMaxDNSMessageData; 3691 opt.resrec.rdlength = sizeof(rdataOPT); 3692 opt.resrec.rdestimate = sizeof(rdataOPT); 3693 if (OwnerRecordSpace && TraceRecordSpace) 3694 { 3695 opt.resrec.rdlength += sizeof(rdataOPT); // Two options in this OPT record 3696 opt.resrec.rdestimate += sizeof(rdataOPT); 3697 SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[0]); 3698 SetupTracerOpt(m, &opt.resrec.rdata->u.opt[1]); 3699 } 3700 else if (OwnerRecordSpace) 3701 { 3702 SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[0]); 3703 } 3704 else if (TraceRecordSpace) 3705 { 3706 SetupTracerOpt(m, &opt.resrec.rdata->u.opt[0]); 3707 } 3708 LogInfo("SendQueries putting %s %s: %s %s", OwnerRecordSpace ? "OWNER" : "", TraceRecordSpace ? "TRACER" : "", intf->ifname, ARDisplayString(m, &opt)); 3709 queryptr = PutResourceRecordTTLWithLimit(&m->omsg, queryptr, &m->omsg.h.numAdditionals, 3710 &opt.resrec, opt.resrec.rroriginalttl, m->omsg.data + AbsoluteMaxDNSMessageData); 3711 if (!queryptr) 3712 { 3713 LogMsg("SendQueries: How did we fail to have space for %s %s OPT record (%d/%d/%d/%d) %s", OwnerRecordSpace ? "OWNER" : "", TraceRecordSpace ? "TRACER" : "", 3714 m->omsg.h.numQuestions, m->omsg.h.numAnswers, m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt)); 3715 } 3716 if (queryptr > m->omsg.data + NormalMaxDNSMessageData) 3717 { 3718 if (m->omsg.h.numQuestions != 1 || m->omsg.h.numAnswers != 0 || m->omsg.h.numAuthorities != 1 || m->omsg.h.numAdditionals != 1) 3719 LogMsg("SendQueries: Why did we generate oversized packet with %s %s OPT record %p %p %p (%d/%d/%d/%d) %s", OwnerRecordSpace ? "OWNER" : "", 3720 TraceRecordSpace ? "TRACER" : "", m->omsg.data, m->omsg.data + NormalMaxDNSMessageData, queryptr, m->omsg.h.numQuestions, m->omsg.h.numAnswers, 3721 m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt)); 3722 } 3723 } 3724 3725 if ((m->omsg.h.flags.b[0] & kDNSFlag0_TC) && m->omsg.h.numQuestions > 1) 3726 LogMsg("SendQueries: Should not have more than one question (%d) in a truncated packet", m->omsg.h.numQuestions); 3727 debugf("SendQueries: Sending %d Question%s %d Answer%s %d Update%s on %p", 3728 m->omsg.h.numQuestions, m->omsg.h.numQuestions == 1 ? "" : "s", 3729 m->omsg.h.numAnswers, m->omsg.h.numAnswers == 1 ? "" : "s", 3730 m->omsg.h.numAuthorities, m->omsg.h.numAuthorities == 1 ? "" : "s", intf->InterfaceID); 3731 if (intf->IPv4Available) mDNSSendDNSMessage(m, &m->omsg, queryptr, intf->InterfaceID, mDNSNULL, &AllDNSLinkGroup_v4, MulticastDNSPort, mDNSNULL, mDNSNULL, useBackgroundTrafficClass); 3732 if (intf->IPv6Available) mDNSSendDNSMessage(m, &m->omsg, queryptr, intf->InterfaceID, mDNSNULL, &AllDNSLinkGroup_v6, MulticastDNSPort, mDNSNULL, mDNSNULL, useBackgroundTrafficClass); 3733 if (!m->SuppressSending) m->SuppressSending = NonZeroTime(m->timenow + (mDNSPlatformOneSecond+9)/10); 3734 if (++pktcount >= 1000) 3735 { LogMsg("SendQueries exceeded loop limit %d: giving up", pktcount); break; } 3736 // There might be more records left in the known answer list, or more questions to send 3737 // on this interface, so go around one more time and try again. 3738 } 3739 else // Nothing more to send on this interface; go to next 3740 { 3741 const NetworkInterfaceInfo *next = GetFirstActiveInterface(intf->next); 3742 #if MDNS_DEBUGMSGS && 0 3743 const char *const msg = next ? "SendQueries: Nothing more on %p; moving to %p" : "SendQueries: Nothing more on %p"; 3744 debugf(msg, intf, next); 3745 #endif 3746 intf = next; 3747 } 3748 } 3749 3750 // 4. Final housekeeping 3751 3752 // 4a. Debugging check: Make sure we announced all our records 3753 for (ar = m->ResourceRecords; ar; ar=ar->next) 3754 if (ar->SendRNow) 3755 { 3756 if (ar->ARType != AuthRecordLocalOnly && ar->ARType != AuthRecordP2P) 3757 LogInfo("SendQueries: No active interface %d to send probe: %d %s", 3758 (uint32_t)ar->SendRNow, (uint32_t)ar->resrec.InterfaceID, ARDisplayString(m, ar)); 3759 ar->SendRNow = mDNSNULL; 3760 } 3761 3762 // 4b. When we have lingering cache records that we're keeping around for a few seconds in the hope 3763 // that their interface which went away might come back again, the logic will want to send queries 3764 // for those records, but we can't because their interface isn't here any more, so to keep the 3765 // state machine ticking over we just pretend we did so. 3766 // If the interface does not come back in time, the cache record will expire naturally 3767 FORALL_CACHERECORDS(slot, cg, cr) 3768 { 3769 if (cr->CRActiveQuestion && cr->UnansweredQueries < MaxUnansweredQueries) 3770 { 3771 if (m->timenow + TicksTTL(cr)/50 - cr->NextRequiredQuery >= 0) 3772 { 3773 cr->UnansweredQueries++; 3774 cr->CRActiveQuestion->SendQNow = mDNSNULL; 3775 SetNextCacheCheckTimeForRecord(m, cr); 3776 } 3777 } 3778 } 3779 3780 // 4c. Debugging check: Make sure we sent all our planned questions 3781 // Do this AFTER the lingering cache records check above, because that will prevent spurious warnings for questions 3782 // we legitimately couldn't send because the interface is no longer available 3783 for (q = m->Questions; q; q=q->next) 3784 { 3785 if (q->SendQNow) 3786 { 3787 DNSQuestion *x; 3788 for (x = m->NewQuestions; x; x=x->next) if (x == q) break; // Check if this question is a NewQuestion 3789 LogInfo("SendQueries: No active interface %d to send %s question: %d %##s (%s)", 3790 (uint32_t)q->SendQNow, x ? "new" : "old", (uint32_t)q->InterfaceID, q->qname.c, DNSTypeName(q->qtype)); 3791 q->SendQNow = mDNSNULL; 3792 } 3793 q->CachedAnswerNeedsUpdate = mDNSfalse; 3794 } 3795 } 3796 3797 mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password) 3798 { 3799 int i, j; 3800 mDNSu8 *ptr = m->omsg.data; 3801 NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID); 3802 if (!intf) { LogMsg("SendARP: No interface with InterfaceID %p found", InterfaceID); return; } 3803 3804 // 0x00 Destination address 3805 for (i=0; i<6; i++) *ptr++ = EthAddr->b[i]; 3806 3807 // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option, BPF will fill in the real interface address for us) 3808 for (i=0; i<6; i++) *ptr++ = intf->MAC.b[0]; 3809 3810 // 0x0C Ethertype (0x0842) 3811 *ptr++ = 0x08; 3812 *ptr++ = 0x42; 3813 3814 // 0x0E Wakeup sync sequence 3815 for (i=0; i<6; i++) *ptr++ = 0xFF; 3816 3817 // 0x14 Wakeup data 3818 for (j=0; j<16; j++) for (i=0; i<6; i++) *ptr++ = EthAddr->b[i]; 3819 3820 // 0x74 Password 3821 for (i=0; i<6; i++) *ptr++ = password->b[i]; 3822 3823 mDNSPlatformSendRawPacket(m->omsg.data, ptr, InterfaceID); 3824 3825 // For Ethernet switches that don't flood-foward packets with unknown unicast destination MAC addresses, 3826 // broadcast is the only reliable way to get a wakeup packet to the intended target machine. 3827 // For 802.11 WPA networks, where a sleeping target machine may have missed a broadcast/multicast 3828 // key rotation, unicast is the only way to get a wakeup packet to the intended target machine. 3829 // So, we send one of each, unicast first, then broadcast second. 3830 for (i=0; i<6; i++) m->omsg.data[i] = 0xFF; 3831 mDNSPlatformSendRawPacket(m->omsg.data, ptr, InterfaceID); 3832 } 3833 3834 // *************************************************************************** 3835 #if COMPILER_LIKES_PRAGMA_MARK 3836 #pragma mark - 3837 #pragma mark - RR List Management & Task Management 3838 #endif 3839 3840 // Whenever a question is answered, reset its state so that we don't query 3841 // the network repeatedly. This happens first time when we answer the question and 3842 // and later when we refresh the cache. 3843 mDNSlocal void ResetQuestionState(mDNS *const m, DNSQuestion *q) 3844 { 3845 q->LastQTime = m->timenow; 3846 q->LastQTxTime = m->timenow; 3847 q->RecentAnswerPkts = 0; 3848 q->ThisQInterval = MaxQuestionInterval; 3849 q->RequestUnicast = 0; 3850 // Reset unansweredQueries so that we don't penalize this server later when we 3851 // start sending queries when the cache expires. 3852 q->unansweredQueries = 0; 3853 debugf("ResetQuestionState: Set MaxQuestionInterval for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 3854 } 3855 3856 // Note: AnswerCurrentQuestionWithResourceRecord can call a user callback, which may change the record list and/or question list. 3857 // Any code walking either list must use the m->CurrentQuestion (and possibly m->CurrentRecord) mechanism to protect against this. 3858 // In fact, to enforce this, the routine will *only* answer the question currently pointed to by m->CurrentQuestion, 3859 // which will be auto-advanced (possibly to NULL) if the client callback cancels the question. 3860 mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheRecord *const rr, const QC_result AddRecord) 3861 { 3862 DNSQuestion *const q = m->CurrentQuestion; 3863 mDNSBool followcname = FollowCNAME(q, &rr->resrec, AddRecord); 3864 3865 verbosedebugf("AnswerCurrentQuestionWithResourceRecord:%4lu %s TTL %d %s", 3866 q->CurrentAnswers, AddRecord ? "Add" : "Rmv", rr->resrec.rroriginalttl, CRDisplayString(m, rr)); 3867 3868 // When the response for the question was validated, the entire rrset was validated. If we deliver 3869 // a RMV for a single record in the rrset, we invalidate the response. If we deliver another add 3870 // in the future, we will do the revalidation again. 3871 // 3872 // Also, if we deliver an ADD for a negative cache record and it has no NSEC/NSEC3, the ValidationStatus needs 3873 // to be reset. This happens normally when we deliver a "secure" negative response followed by an insecure 3874 // negative response which can happen e.g., when disconnecting from network that leads to a negative response 3875 // due to no DNS servers. As we don't deliver RMVs for negative responses that were delivered before, we need 3876 // to do it on the next ADD of a negative cache record. This ADD could be the result of a timeout, no DNS servers 3877 // etc. in which case we need to reset the state to make sure we don't deliver them as secure. If this is 3878 // a real negative response, we would reset the state here and validate the results at the end of this function. 3879 // or the real response again if we purge the cache. 3880 if (q->ValidationRequired && ((AddRecord == QC_rmv) || 3881 (rr->resrec.RecordType == kDNSRecordTypePacketNegative && (AddRecord == QC_add)))) 3882 { 3883 q->ValidationStatus = 0; 3884 q->ValidationState = DNSSECValRequired; 3885 } 3886 3887 // Normally we don't send out the unicast query if we have answered using our local only auth records e.g., /etc/hosts. 3888 // But if the query for "A" record has a local answer but query for "AAAA" record has no local answer, we might 3889 // send the AAAA query out which will come back with CNAME and will also answer the "A" query. To prevent that, 3890 // we check to see if that query already has a unique local answer. 3891 if (q->LOAddressAnswers) 3892 { 3893 LogInfo("AnswerCurrentQuestionWithResourceRecord: Question %p %##s (%s) not answering with record %s due to " 3894 "LOAddressAnswers %d", q, q->qname.c, DNSTypeName(q->qtype), ARDisplayString(m, rr), 3895 q->LOAddressAnswers); 3896 return; 3897 } 3898 3899 if (QuerySuppressed(q)) 3900 { 3901 // If the query is suppressed, then we don't want to answer from the cache. But if this query is 3902 // supposed to time out, we still want to callback the clients. We do this only for TimeoutQuestions 3903 // that are timing out, which we know are answered with negative cache record when timing out. 3904 if (!q->TimeoutQuestion || rr->resrec.RecordType != kDNSRecordTypePacketNegative || (m->timenow - q->StopTime < 0)) 3905 return; 3906 } 3907 3908 // Note: Use caution here. In the case of records with rr->DelayDelivery set, AnswerCurrentQuestionWithResourceRecord(... mDNStrue) 3909 // may be called twice, once when the record is received, and again when it's time to notify local clients. 3910 // If any counters or similar are added here, care must be taken to ensure that they are not double-incremented by this. 3911 3912 rr->LastUsed = m->timenow; 3913 if (AddRecord == QC_add && !q->DuplicateOf && rr->CRActiveQuestion != q) 3914 { 3915 if (!rr->CRActiveQuestion) m->rrcache_active++; // If not previously active, increment rrcache_active count 3916 debugf("AnswerCurrentQuestionWithResourceRecord: Updating CRActiveQuestion from %p to %p for cache record %s, CurrentAnswer %d", 3917 rr->CRActiveQuestion, q, CRDisplayString(m,rr), q->CurrentAnswers); 3918 rr->CRActiveQuestion = q; // We know q is non-null 3919 SetNextCacheCheckTimeForRecord(m, rr); 3920 } 3921 3922 // If this is: 3923 // (a) a no-cache add, where we've already done at least one 'QM' query, or 3924 // (b) a normal add, where we have at least one unique-type answer, 3925 // then there's no need to keep polling the network. 3926 // (If we have an answer in the cache, then we'll automatically ask again in time to stop it expiring.) 3927 // We do this for mDNS questions and uDNS one-shot questions, but not for 3928 // uDNS LongLived questions, because that would mess up our LLQ lease renewal timing. 3929 if ((AddRecord == QC_addnocache && !q->RequestUnicast) || 3930 (AddRecord == QC_add && (q->ExpectUnique || (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask)))) 3931 if (ActiveQuestion(q) && (mDNSOpaque16IsZero(q->TargetQID) || !q->LongLived)) 3932 { 3933 ResetQuestionState(m, q); 3934 } 3935 3936 if (rr->DelayDelivery) return; // We'll come back later when CacheRecordDeferredAdd() calls us 3937 3938 // Only deliver negative answers if client has explicitly requested them except when we are forcing a negative response 3939 // for the purpose of retrying search domains/timeout OR the question is suppressed 3940 if (rr->resrec.RecordType == kDNSRecordTypePacketNegative || (q->qtype != kDNSType_NSEC && RRAssertsNonexistence(&rr->resrec, q->qtype))) 3941 if (!AddRecord || (AddRecord != QC_suppressed && AddRecord != QC_forceresponse && !q->ReturnIntermed)) return; 3942 3943 // For CNAME results to non-CNAME questions, only inform the client if they explicitly requested that 3944 if (q->QuestionCallback && !q->NoAnswer && (!followcname || q->ReturnIntermed)) 3945 { 3946 mDNS_DropLockBeforeCallback(); // Allow client (and us) to legally make mDNS API calls 3947 if (q->qtype != kDNSType_NSEC && RRAssertsNonexistence(&rr->resrec, q->qtype)) 3948 { 3949 CacheRecord neg; 3950 MakeNegativeCacheRecord(m, &neg, &q->qname, q->qnamehash, q->qtype, q->qclass, 1, rr->resrec.InterfaceID, q->qDNSServer); 3951 q->QuestionCallback(m, q, &neg.resrec, AddRecord); 3952 } 3953 else 3954 q->QuestionCallback(m, q, &rr->resrec, AddRecord); 3955 mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again 3956 } 3957 // If this is an "Add" operation and this question needs validation, validate the response. 3958 // In the case of negative responses, extra care should be taken. Negative cache records are 3959 // used for many purposes. For example, 3960 // 3961 // 1) Suppressing questions (SuppressUnusable) 3962 // 2) Timeout questions 3963 // 3) The name does not exist 3964 // 4) No DNS servers are available and we need a quick response for the application 3965 // 3966 // (1) and (2) are handled by "QC_add" check as AddRecord would be "QC_forceresponse" or "QC_suppressed" 3967 // in that case. For (3), it is possible that we don't get nsecs back but we still need to call 3968 // VerifySignature so that we can deliver the appropriate DNSSEC result. There is no point in verifying 3969 // signature for (4) and hence the explicit check for q->qDNSServer. 3970 // 3971 if (m->CurrentQuestion == q && (AddRecord == QC_add) && !q->ValidatingResponse && q->ValidationRequired && 3972 q->ValidationState == DNSSECValRequired && q->qDNSServer) 3973 { 3974 q->ValidationState = DNSSECValInProgress; 3975 // Treat it as callback call as that's what dnssec code expects 3976 mDNS_DropLockBeforeCallback(); // Allow client (and us) to legally make mDNS API calls 3977 VerifySignature(m, mDNSNULL, q); 3978 mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again 3979 return; 3980 } 3981 3982 // Note: Proceed with caution here because client callback function is allowed to do anything, 3983 // including starting/stopping queries, registering/deregistering records, etc. 3984 // 3985 // If we get a CNAME back while we are validating the response (i.e., CNAME for DS, DNSKEY, RRSIG), 3986 // don't follow them. If it is a ValidationRequired question, wait for the CNAME to be validated 3987 // first before following it 3988 if (!ValidatingQuestion(q) && followcname && m->CurrentQuestion == q) 3989 AnswerQuestionByFollowingCNAME(m, q, &rr->resrec); 3990 } 3991 3992 mDNSlocal void CacheRecordDeferredAdd(mDNS *const m, CacheRecord *rr) 3993 { 3994 rr->DelayDelivery = 0; 3995 if (m->CurrentQuestion) 3996 LogMsg("CacheRecordDeferredAdd ERROR m->CurrentQuestion already set: %##s (%s)", 3997 m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype)); 3998 m->CurrentQuestion = m->Questions; 3999 while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions) 4000 { 4001 DNSQuestion *q = m->CurrentQuestion; 4002 if (ResourceRecordAnswersQuestion(&rr->resrec, q)) 4003 AnswerCurrentQuestionWithResourceRecord(m, rr, QC_add); 4004 if (m->CurrentQuestion == q) // If m->CurrentQuestion was not auto-advanced, do it ourselves now 4005 m->CurrentQuestion = q->next; 4006 } 4007 m->CurrentQuestion = mDNSNULL; 4008 } 4009 4010 mDNSlocal mDNSs32 CheckForSoonToExpireRecords(mDNS *const m, const domainname *const name, const mDNSu32 namehash, const mDNSu32 slot, mDNSBool *purge) 4011 { 4012 const mDNSs32 threshhold = m->timenow + mDNSPlatformOneSecond; // See if there are any records expiring within one second 4013 const mDNSs32 start = m->timenow - 0x10000000; 4014 mDNSs32 delay = start; 4015 CacheGroup *cg = CacheGroupForName(m, slot, namehash, name); 4016 const CacheRecord *rr; 4017 4018 if (purge) 4019 *purge = mDNSfalse; 4020 for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) 4021 { 4022 // If there are records that will expire soon, there are cases that need delayed 4023 // delivery of events: 4024 // 4025 // 1) A new cache entry is about to be added as a replacement. The caller needs to 4026 // deliver a RMV (for the current old entry) followed by ADD (for the new entry). 4027 // It needs to schedule the timer for the next cache expiry (ScheduleNextCacheCheckTime), 4028 // so that the cache entry can be purged (purging causes the RMV followed by ADD) 4029 // 4030 // 2) A new question is about to be answered and the caller needs to know whether it's 4031 // scheduling should be delayed so that the question is not answered with this record. 4032 // Instead of delivering an ADD (old entry) followed by RMV (old entry) and another ADD 4033 // (new entry), a single ADD can be delivered by delaying the scheduling of the question 4034 // immediately. 4035 // 4036 // When the unicast cache record is created, it's TTL has been extended beyond its value 4037 // given in the resource record (See RRAdjustTTL). If it is in the "extended" time, the 4038 // cache is already expired and we set "purge" to indicate that. When "purge" is set, the 4039 // return value of the function should be ignored by the callers. 4040 // 4041 // Note: For case (1), "purge" argument is NULL and hence the following checks are skipped. 4042 // It is okay to skip in that case because the cache records have been set to expire almost 4043 // immediately and the extended time does not apply. 4044 // 4045 // Also, if there is already an active question we don't try to optimize as purging the cache 4046 // would end up delivering RMV for the active question and hence we avoid that. 4047 4048 if (purge && !rr->resrec.InterfaceID && !rr->CRActiveQuestion && rr->resrec.rroriginalttl) 4049 { 4050 mDNSu32 uTTL = RRUnadjustedTTL(rr->resrec.rroriginalttl); 4051 if (m->timenow - (rr->TimeRcvd + ((mDNSs32)uTTL * mDNSPlatformOneSecond)) >= 0) 4052 { 4053 LogInfo("CheckForSoonToExpireRecords: %s: rroriginalttl %u, unadjustedTTL %u, currentTTL %u", 4054 CRDisplayString(m, rr), rr->resrec.rroriginalttl, uTTL, (m->timenow - rr->TimeRcvd)/mDNSPlatformOneSecond); 4055 *purge = mDNStrue; 4056 continue; 4057 } 4058 } 4059 if (threshhold - RRExpireTime(rr) >= 0) // If we have records about to expire within a second 4060 { 4061 if (delay - RRExpireTime(rr) < 0) // then delay until after they've been deleted 4062 delay = RRExpireTime(rr); 4063 } 4064 } 4065 if (delay - start > 0) 4066 return(NonZeroTime(delay)); 4067 else 4068 return(0); 4069 } 4070 4071 // CacheRecordAdd is only called from CreateNewCacheEntry, *never* directly as a result of a client API call. 4072 // If new questions are created as a result of invoking client callbacks, they will be added to 4073 // the end of the question list, and m->NewQuestions will be set to indicate the first new question. 4074 // rr is a new CacheRecord just received into our cache 4075 // (kDNSRecordTypePacketAns/PacketAnsUnique/PacketAdd/PacketAddUnique). 4076 // Note: CacheRecordAdd calls AnswerCurrentQuestionWithResourceRecord which can call a user callback, 4077 // which may change the record list and/or question list. 4078 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this. 4079 mDNSlocal void CacheRecordAdd(mDNS *const m, CacheRecord *rr) 4080 { 4081 DNSQuestion *q; 4082 4083 // We stop when we get to NewQuestions -- if we increment their CurrentAnswers/LargeAnswers/UniqueAnswers 4084 // counters here we'll end up double-incrementing them when we do it again in AnswerNewQuestion(). 4085 for (q = m->Questions; q && q != m->NewQuestions; q=q->next) 4086 { 4087 if (ResourceRecordAnswersQuestion(&rr->resrec, q)) 4088 { 4089 // If this question is one that's actively sending queries, and it's received ten answers within one 4090 // second of sending the last query packet, then that indicates some radical network topology change, 4091 // so reset its exponential backoff back to the start. We must be at least at the eight-second interval 4092 // to do this. If we're at the four-second interval, or less, there's not much benefit accelerating 4093 // because we will anyway send another query within a few seconds. The first reset query is sent out 4094 // randomized over the next four seconds to reduce possible synchronization between machines. 4095 if (q->LastAnswerPktNum != m->PktNum) 4096 { 4097 q->LastAnswerPktNum = m->PktNum; 4098 if (mDNSOpaque16IsZero(q->TargetQID) && ActiveQuestion(q) && ++q->RecentAnswerPkts >= 10 && 4099 q->ThisQInterval > InitialQuestionInterval * QuestionIntervalStep3 && m->timenow - q->LastQTxTime < mDNSPlatformOneSecond) 4100 { 4101 LogMsg("CacheRecordAdd: %##s (%s) got immediate answer burst (%d); restarting exponential backoff sequence (%d)", 4102 q->qname.c, DNSTypeName(q->qtype), q->RecentAnswerPkts, q->ThisQInterval); 4103 q->LastQTime = m->timenow - InitialQuestionInterval + (mDNSs32)mDNSRandom((mDNSu32)mDNSPlatformOneSecond*4); 4104 q->ThisQInterval = InitialQuestionInterval; 4105 SetNextQueryTime(m,q); 4106 } 4107 } 4108 verbosedebugf("CacheRecordAdd %p %##s (%s) %lu %#a:%d question %p", rr, rr->resrec.name->c, 4109 DNSTypeName(rr->resrec.rrtype), rr->resrec.rroriginalttl, rr->resrec.rDNSServer ? 4110 &rr->resrec.rDNSServer->addr : mDNSNULL, mDNSVal16(rr->resrec.rDNSServer ? 4111 rr->resrec.rDNSServer->port : zeroIPPort), q); 4112 q->CurrentAnswers++; 4113 4114 q->unansweredQueries = 0; 4115 if (rr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers++; 4116 if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers++; 4117 if (q->CurrentAnswers > 4000) 4118 { 4119 static int msgcount = 0; 4120 if (msgcount++ < 10) 4121 LogMsg("CacheRecordAdd: %##s (%s) has %d answers; shedding records to resist DOS attack", 4122 q->qname.c, DNSTypeName(q->qtype), q->CurrentAnswers); 4123 rr->resrec.rroriginalttl = 0; 4124 rr->UnansweredQueries = MaxUnansweredQueries; 4125 } 4126 } 4127 } 4128 4129 if (!rr->DelayDelivery) 4130 { 4131 if (m->CurrentQuestion) 4132 LogMsg("CacheRecordAdd ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype)); 4133 m->CurrentQuestion = m->Questions; 4134 while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions) 4135 { 4136 q = m->CurrentQuestion; 4137 if (ResourceRecordAnswersQuestion(&rr->resrec, q)) 4138 AnswerCurrentQuestionWithResourceRecord(m, rr, QC_add); 4139 if (m->CurrentQuestion == q) // If m->CurrentQuestion was not auto-advanced, do it ourselves now 4140 m->CurrentQuestion = q->next; 4141 } 4142 m->CurrentQuestion = mDNSNULL; 4143 } 4144 4145 SetNextCacheCheckTimeForRecord(m, rr); 4146 } 4147 4148 // NoCacheAnswer is only called from mDNSCoreReceiveResponse, *never* directly as a result of a client API call. 4149 // If new questions are created as a result of invoking client callbacks, they will be added to 4150 // the end of the question list, and m->NewQuestions will be set to indicate the first new question. 4151 // rr is a new CacheRecord just received from the wire (kDNSRecordTypePacketAns/AnsUnique/Add/AddUnique) 4152 // but we don't have any place to cache it. We'll deliver question 'add' events now, but we won't have any 4153 // way to deliver 'remove' events in future, nor will we be able to include this in known-answer lists, 4154 // so we immediately bump ThisQInterval up to MaxQuestionInterval to avoid pounding the network. 4155 // Note: NoCacheAnswer calls AnswerCurrentQuestionWithResourceRecord which can call a user callback, 4156 // which may change the record list and/or question list. 4157 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this. 4158 mDNSlocal void NoCacheAnswer(mDNS *const m, CacheRecord *rr) 4159 { 4160 LogMsg("No cache space: Delivering non-cached result for %##s", m->rec.r.resrec.name->c); 4161 if (m->CurrentQuestion) 4162 LogMsg("NoCacheAnswer ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype)); 4163 m->CurrentQuestion = m->Questions; 4164 // We do this for *all* questions, not stopping when we get to m->NewQuestions, 4165 // since we're not caching the record and we'll get no opportunity to do this later 4166 while (m->CurrentQuestion) 4167 { 4168 DNSQuestion *q = m->CurrentQuestion; 4169 if (ResourceRecordAnswersQuestion(&rr->resrec, q)) 4170 AnswerCurrentQuestionWithResourceRecord(m, rr, QC_addnocache); // QC_addnocache means "don't expect remove events for this" 4171 if (m->CurrentQuestion == q) // If m->CurrentQuestion was not auto-advanced, do it ourselves now 4172 m->CurrentQuestion = q->next; 4173 } 4174 m->CurrentQuestion = mDNSNULL; 4175 } 4176 4177 // CacheRecordRmv is only called from CheckCacheExpiration, which is called from mDNS_Execute. 4178 // Note that CacheRecordRmv is *only* called for records that are referenced by at least one active question. 4179 // If new questions are created as a result of invoking client callbacks, they will be added to 4180 // the end of the question list, and m->NewQuestions will be set to indicate the first new question. 4181 // rr is an existing cache CacheRecord that just expired and is being deleted 4182 // (kDNSRecordTypePacketAns/PacketAnsUnique/PacketAdd/PacketAddUnique). 4183 // Note: CacheRecordRmv calls AnswerCurrentQuestionWithResourceRecord which can call a user callback, 4184 // which may change the record list and/or question list. 4185 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this. 4186 mDNSlocal void CacheRecordRmv(mDNS *const m, CacheRecord *rr) 4187 { 4188 if (m->CurrentQuestion) 4189 LogMsg("CacheRecordRmv ERROR m->CurrentQuestion already set: %##s (%s)", 4190 m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype)); 4191 m->CurrentQuestion = m->Questions; 4192 4193 // We stop when we get to NewQuestions -- for new questions their CurrentAnswers/LargeAnswers/UniqueAnswers counters 4194 // will all still be zero because we haven't yet gone through the cache counting how many answers we have for them. 4195 while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions) 4196 { 4197 DNSQuestion *q = m->CurrentQuestion; 4198 // When a question enters suppressed state, we generate RMV events and generate a negative 4199 // response. A cache may be present that answers this question e.g., cache entry generated 4200 // before the question became suppressed. We need to skip the suppressed questions here as 4201 // the RMV event has already been generated. 4202 if (!QuerySuppressed(q) && ResourceRecordAnswersQuestion(&rr->resrec, q)) 4203 { 4204 verbosedebugf("CacheRecordRmv %p %s", rr, CRDisplayString(m, rr)); 4205 q->FlappingInterface1 = mDNSNULL; 4206 q->FlappingInterface2 = mDNSNULL; 4207 4208 if (q->CurrentAnswers == 0) { 4209 mDNSIPPort zp = zeroIPPort; 4210 LogMsg("CacheRecordRmv ERROR!!: How can CurrentAnswers already be zero for %p %##s (%s) DNSServer %#a:%d", 4211 q, q->qname.c, DNSTypeName(q->qtype), q->qDNSServer ? &q->qDNSServer->addr : mDNSNULL, 4212 mDNSVal16(q->qDNSServer ? q->qDNSServer->port : zp)); 4213 } 4214 else 4215 { 4216 q->CurrentAnswers--; 4217 if (rr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers--; 4218 if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers--; 4219 } 4220 4221 // If we have dropped below the answer threshold for this mDNS question, 4222 // restart the queries at InitialQuestionInterval. 4223 if (mDNSOpaque16IsZero(q->TargetQID) && (q->BrowseThreshold > 0) && (q->CurrentAnswers < q->BrowseThreshold)) 4224 { 4225 q->ThisQInterval = InitialQuestionInterval; 4226 q->LastQTime = m->timenow - q->ThisQInterval; 4227 SetNextQueryTime(m,q); 4228 LogInfo("CacheRecordRmv: (%s) %##s dropped below threshold of %d answers", 4229 DNSTypeName(q->qtype), q->qname.c, q->BrowseThreshold); 4230 } 4231 if (rr->resrec.rdata->MaxRDLength) // Never generate "remove" events for negative results 4232 { 4233 if (q->CurrentAnswers == 0) 4234 { 4235 LogInfo("CacheRecordRmv: Last answer for %##s (%s) expired from cache; will reconfirm antecedents", 4236 q->qname.c, DNSTypeName(q->qtype)); 4237 ReconfirmAntecedents(m, &q->qname, q->qnamehash, 0); 4238 } 4239 AnswerCurrentQuestionWithResourceRecord(m, rr, QC_rmv); 4240 } 4241 } 4242 if (m->CurrentQuestion == q) // If m->CurrentQuestion was not auto-advanced, do it ourselves now 4243 m->CurrentQuestion = q->next; 4244 } 4245 m->CurrentQuestion = mDNSNULL; 4246 } 4247 4248 mDNSlocal void ReleaseCacheEntity(mDNS *const m, CacheEntity *e) 4249 { 4250 #if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING >= 1 4251 unsigned int i; 4252 for (i=0; i<sizeof(*e); i++) ((char*)e)[i] = 0xFF; 4253 #endif 4254 e->next = m->rrcache_free; 4255 m->rrcache_free = e; 4256 m->rrcache_totalused--; 4257 } 4258 4259 mDNSlocal void ReleaseCacheGroup(mDNS *const m, CacheGroup **cp) 4260 { 4261 CacheEntity *e = (CacheEntity *)(*cp); 4262 //LogMsg("ReleaseCacheGroup: Releasing CacheGroup for %p, %##s", (*cp)->name->c, (*cp)->name->c); 4263 if ((*cp)->rrcache_tail != &(*cp)->members) 4264 LogMsg("ERROR: (*cp)->members == mDNSNULL but (*cp)->rrcache_tail != &(*cp)->members)"); 4265 //if ((*cp)->name != (domainname*)((*cp)->namestorage)) 4266 // LogMsg("ReleaseCacheGroup: %##s, %p %p", (*cp)->name->c, (*cp)->name, (domainname*)((*cp)->namestorage)); 4267 if ((*cp)->name != (domainname*)((*cp)->namestorage)) mDNSPlatformMemFree((*cp)->name); 4268 (*cp)->name = mDNSNULL; 4269 *cp = (*cp)->next; // Cut record from list 4270 ReleaseCacheEntity(m, e); 4271 } 4272 4273 mDNSlocal void ReleaseAdditionalCacheRecords(mDNS *const m, CacheRecord **rp) 4274 { 4275 while (*rp) 4276 { 4277 CacheRecord *rr = *rp; 4278 *rp = (*rp)->next; // Cut record from list 4279 if (rr->resrec.rdata && rr->resrec.rdata != (RData*)&rr->smallrdatastorage) 4280 { 4281 mDNSPlatformMemFree(rr->resrec.rdata); 4282 rr->resrec.rdata = mDNSNULL; 4283 } 4284 // NSEC or SOA records that are not added to the CacheGroup do not share the name 4285 // of the CacheGroup. 4286 if (rr->resrec.name) 4287 { 4288 debugf("ReleaseAdditionalCacheRecords: freeing cached record %##s (%s)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype)); 4289 mDNSPlatformMemFree((void *)rr->resrec.name); 4290 rr->resrec.name = mDNSNULL; 4291 } 4292 // Don't count the NSEC3 records used by anonymous browse/reg 4293 if (!rr->resrec.InterfaceID) 4294 { 4295 m->rrcache_totalused_unicast -= rr->resrec.rdlength; 4296 if (DNSSECRecordType(rr->resrec.rrtype)) 4297 BumpDNSSECStats(m, kStatsActionDecrement, kStatsTypeMemoryUsage, rr->resrec.rdlength); 4298 } 4299 ReleaseCacheEntity(m, (CacheEntity *)rr); 4300 } 4301 } 4302 4303 mDNSexport void ReleaseCacheRecord(mDNS *const m, CacheRecord *r) 4304 { 4305 CacheGroup *cg; 4306 const mDNSu32 slot = HashSlot(r->resrec.name); 4307 4308 //LogMsg("ReleaseCacheRecord: Releasing %s", CRDisplayString(m, r)); 4309 if (r->resrec.rdata && r->resrec.rdata != (RData*)&r->smallrdatastorage) mDNSPlatformMemFree(r->resrec.rdata); 4310 r->resrec.rdata = mDNSNULL; 4311 4312 cg = CacheGroupForRecord(m, slot, &r->resrec); 4313 4314 if (!cg) 4315 { 4316 // It is okay to have this printed for NSEC/NSEC3s 4317 LogInfo("ReleaseCacheRecord: ERROR!! cg NULL for %##s (%s)", r->resrec.name->c, DNSTypeName(r->resrec.rrtype)); 4318 } 4319 // When NSEC records are not added to the cache, it is usually cached at the "nsec" list 4320 // of the CacheRecord. But sometimes they may be freed without adding to the "nsec" list 4321 // (which is handled below) and in that case it should be freed here. 4322 if (r->resrec.name && cg && r->resrec.name != cg->name) 4323 { 4324 debugf("ReleaseCacheRecord: freeing %##s (%s)", r->resrec.name->c, DNSTypeName(r->resrec.rrtype)); 4325 mDNSPlatformMemFree((void *)r->resrec.name); 4326 } 4327 r->resrec.name = mDNSNULL; 4328 4329 if (r->resrec.AnonInfo) 4330 { 4331 debugf("ReleaseCacheRecord: freeing AnonInfo for %##s (%s)", r->resrec.name->c, DNSTypeName(r->resrec.rrtype)); 4332 FreeAnonInfo((void *)r->resrec.AnonInfo); 4333 } 4334 r->resrec.AnonInfo = mDNSNULL; 4335 4336 if (!r->resrec.InterfaceID) 4337 { 4338 m->rrcache_totalused_unicast -= r->resrec.rdlength; 4339 if (DNSSECRecordType(r->resrec.rrtype)) 4340 BumpDNSSECStats(m, kStatsActionDecrement, kStatsTypeMemoryUsage, r->resrec.rdlength); 4341 } 4342 4343 ReleaseAdditionalCacheRecords(m, &r->nsec); 4344 ReleaseAdditionalCacheRecords(m, &r->soa); 4345 4346 ReleaseCacheEntity(m, (CacheEntity *)r); 4347 } 4348 4349 // Note: We want to be careful that we deliver all the CacheRecordRmv calls before delivering 4350 // CacheRecordDeferredAdd calls. The in-order nature of the cache lists ensures that all 4351 // callbacks for old records are delivered before callbacks for newer records. 4352 mDNSlocal void CheckCacheExpiration(mDNS *const m, const mDNSu32 slot, CacheGroup *const cg) 4353 { 4354 CacheRecord **rp = &cg->members; 4355 4356 if (m->lock_rrcache) { LogMsg("CheckCacheExpiration ERROR! Cache already locked!"); return; } 4357 m->lock_rrcache = 1; 4358 4359 while (*rp) 4360 { 4361 CacheRecord *const rr = *rp; 4362 mDNSs32 event = RRExpireTime(rr); 4363 if (m->timenow - event >= 0) // If expired, delete it 4364 { 4365 *rp = rr->next; // Cut it from the list 4366 4367 verbosedebugf("CheckCacheExpiration: Deleting%7d %7d %p %s", 4368 m->timenow - rr->TimeRcvd, rr->resrec.rroriginalttl, rr->CRActiveQuestion, CRDisplayString(m, rr)); 4369 if (rr->CRActiveQuestion) // If this record has one or more active questions, tell them it's going away 4370 { 4371 DNSQuestion *q = rr->CRActiveQuestion; 4372 // When a cache record is about to expire, we expect to do four queries at 80-82%, 85-87%, 90-92% and 4373 // then 95-97% of the TTL. If the DNS server does not respond, then we will remove the cache entry 4374 // before we pick a new DNS server. As the question interval is set to MaxQuestionInterval, we may 4375 // not send out a query anytime soon. Hence, we need to reset the question interval. If this is 4376 // a normal deferred ADD case, then AnswerCurrentQuestionWithResourceRecord will reset it to 4377 // MaxQuestionInterval. If we have inactive questions referring to negative cache entries, 4378 // don't ressurect them as they will deliver duplicate "No such Record" ADD events 4379 if (!mDNSOpaque16IsZero(q->TargetQID) && !q->LongLived && ActiveQuestion(q)) 4380 { 4381 q->ThisQInterval = InitialQuestionInterval; 4382 q->LastQTime = m->timenow - q->ThisQInterval; 4383 SetNextQueryTime(m, q); 4384 } 4385 CacheRecordRmv(m, rr); 4386 m->rrcache_active--; 4387 } 4388 ReleaseCacheRecord(m, rr); 4389 } 4390 else // else, not expired; see if we need to query 4391 { 4392 // If waiting to delay delivery, do nothing until then 4393 if (rr->DelayDelivery && rr->DelayDelivery - m->timenow > 0) 4394 event = rr->DelayDelivery; 4395 else 4396 { 4397 if (rr->DelayDelivery) CacheRecordDeferredAdd(m, rr); 4398 if (rr->CRActiveQuestion && rr->UnansweredQueries < MaxUnansweredQueries) 4399 { 4400 if (m->timenow - rr->NextRequiredQuery < 0) // If not yet time for next query 4401 event = NextCacheCheckEvent(rr); // then just record when we want the next query 4402 else // else trigger our question to go out now 4403 { 4404 // Set NextScheduledQuery to timenow so that SendQueries() will run. 4405 // SendQueries() will see that we have records close to expiration, and send FEQs for them. 4406 m->NextScheduledQuery = m->timenow; 4407 // After sending the query we'll increment UnansweredQueries and call SetNextCacheCheckTimeForRecord(), 4408 // which will correctly update m->NextCacheCheck for us. 4409 event = m->timenow + 0x3FFFFFFF; 4410 } 4411 } 4412 } 4413 verbosedebugf("CheckCacheExpiration:%6d %5d %s", 4414 (event - m->timenow) / mDNSPlatformOneSecond, CacheCheckGracePeriod(rr), CRDisplayString(m, rr)); 4415 if (m->rrcache_nextcheck[slot] - event > 0) 4416 m->rrcache_nextcheck[slot] = event; 4417 rp = &rr->next; 4418 } 4419 } 4420 if (cg->rrcache_tail != rp) verbosedebugf("CheckCacheExpiration: Updating CacheGroup tail from %p to %p", cg->rrcache_tail, rp); 4421 cg->rrcache_tail = rp; 4422 m->lock_rrcache = 0; 4423 } 4424 4425 // "LORecord" includes both LocalOnly and P2P record. This function assumes m->CurrentQuestion is pointing to "q". 4426 // 4427 // If "CheckOnly" is set to "true", the question won't be answered but just check to see if there is an answer and 4428 // returns true if there is an answer. 4429 // 4430 // If "CheckOnly" is set to "false", the question will be answered if there is a LocalOnly/P2P record and 4431 // returns true to indicate the same. 4432 mDNSlocal mDNSBool AnswerQuestionWithLORecord(mDNS *const m, DNSQuestion *q, mDNSBool checkOnly) 4433 { 4434 mDNSu32 slot; 4435 AuthRecord *lr; 4436 AuthGroup *ag; 4437 4438 if (m->CurrentRecord) 4439 LogMsg("AnswerQuestionWithLORecord ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord)); 4440 4441 slot = AuthHashSlot(&q->qname); 4442 ag = AuthGroupForName(&m->rrauth, slot, q->qnamehash, &q->qname); 4443 if (ag) 4444 { 4445 m->CurrentRecord = ag->members; 4446 while (m->CurrentRecord && m->CurrentRecord != ag->NewLocalOnlyRecords) 4447 { 4448 AuthRecord *rr = m->CurrentRecord; 4449 m->CurrentRecord = rr->next; 4450 // 4451 // If the question is mDNSInterface_LocalOnly, all records local to the machine should be used 4452 // to answer the query. This is handled in AnswerNewLocalOnlyQuestion. 4453 // 4454 // We handle mDNSInterface_Any and scoped questions here. See LocalOnlyRecordAnswersQuestion for more 4455 // details on how we handle this case. For P2P we just handle "Interface_Any" questions. For LocalOnly 4456 // we handle both mDNSInterface_Any and scoped questions. 4457 4458 if (rr->ARType == AuthRecordLocalOnly || (rr->ARType == AuthRecordP2P && q->InterfaceID == mDNSInterface_Any)) 4459 if (LocalOnlyRecordAnswersQuestion(rr, q)) 4460 { 4461 if (checkOnly) 4462 { 4463 LogInfo("AnswerQuestionWithLORecord: question %##s (%s) answered by %s", q->qname.c, DNSTypeName(q->qtype), 4464 ARDisplayString(m, rr)); 4465 m->CurrentRecord = mDNSNULL; 4466 return mDNStrue; 4467 } 4468 AnswerLocalQuestionWithLocalAuthRecord(m, rr, QC_add); 4469 if (m->CurrentQuestion != q) 4470 break; // If callback deleted q, then we're finished here 4471 } 4472 } 4473 } 4474 m->CurrentRecord = mDNSNULL; 4475 4476 if (m->CurrentQuestion != q) 4477 { 4478 LogInfo("AnswerQuestionWithLORecord: Question deleted while while answering LocalOnly record answers"); 4479 return mDNStrue; 4480 } 4481 4482 if (q->LOAddressAnswers) 4483 { 4484 LogInfo("AnswerQuestionWithLORecord: Question %p %##s (%s) answered using local auth records LOAddressAnswers %d", 4485 q, q->qname.c, DNSTypeName(q->qtype), q->LOAddressAnswers); 4486 return mDNStrue; 4487 } 4488 4489 // Before we go check the cache and ship this query on the wire, we have to be sure that there are 4490 // no local records that could possibly answer this question. As we did not check the NewLocalRecords, we 4491 // need to just peek at them to see whether it will answer this question. If it would answer, pretend 4492 // that we answered. AnswerAllLocalQuestionsWithLocalAuthRecord will answer shortly. This happens normally 4493 // when we add new /etc/hosts entries and restart the question. It is a new question and also a new record. 4494 if (ag) 4495 { 4496 lr = ag->NewLocalOnlyRecords; 4497 while (lr) 4498 { 4499 if (UniqueLocalOnlyRecord(lr) && LocalOnlyRecordAnswersQuestion(lr, q)) 4500 { 4501 LogInfo("AnswerQuestionWithLORecord: Question %p %##s (%s) will be answered using new local auth records " 4502 " LOAddressAnswers %d", q, q->qname.c, DNSTypeName(q->qtype), q->LOAddressAnswers); 4503 return mDNStrue; 4504 } 4505 lr = lr->next; 4506 } 4507 } 4508 return mDNSfalse; 4509 } 4510 4511 // Today, we suppress questions (not send them on the wire) for several reasons e.g., 4512 // AAAA query is suppressed because no IPv6 capability or PID is not allowed to make 4513 // DNS requests. We need to temporarily suspend the suppress status so that we can 4514 // deliver a negative response (AnswerCurrentQuestionWithResourceRecord does not answer 4515 // suppressed questions) and reset it back. In the future, if there are other 4516 // reasons for suppressing the query, this function should be updated. 4517 mDNSlocal void AnswerSuppressedQuestion(mDNS *const m, DNSQuestion *q) 4518 { 4519 mDNSBool SuppressQuery = q->SuppressQuery; 4520 mDNSBool DisallowPID = q->DisallowPID; 4521 4522 // make sure that QuerySuppressed() returns false 4523 q->SuppressQuery = mDNSfalse; 4524 q->DisallowPID = mDNSfalse; 4525 4526 GenerateNegativeResponse(m, QC_suppressed); 4527 4528 q->SuppressQuery = SuppressQuery; 4529 q->DisallowPID = DisallowPID; 4530 } 4531 4532 mDNSlocal void AnswerNewQuestion(mDNS *const m) 4533 { 4534 mDNSBool ShouldQueryImmediately = mDNStrue; 4535 DNSQuestion *const q = m->NewQuestions; // Grab the question we're going to answer 4536 mDNSu32 slot = HashSlot(&q->qname); 4537 CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); 4538 mDNSBool AnsweredFromCache = mDNSfalse; 4539 4540 verbosedebugf("AnswerNewQuestion: Answering %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 4541 4542 if (cg) CheckCacheExpiration(m, slot, cg); 4543 if (m->NewQuestions != q) { LogInfo("AnswerNewQuestion: Question deleted while doing CheckCacheExpiration"); goto exit; } 4544 m->NewQuestions = q->next; 4545 // Advance NewQuestions to the next *after* calling CheckCacheExpiration, because if we advance it first 4546 // then CheckCacheExpiration may give this question add/remove callbacks, and it's not yet ready for that. 4547 // 4548 // Also, CheckCacheExpiration() calls CacheRecordDeferredAdd() and CacheRecordRmv(), which invoke 4549 // client callbacks, which may delete their own or any other question. Our mechanism for detecting 4550 // whether our current m->NewQuestions question got deleted by one of these callbacks is to store the 4551 // value of m->NewQuestions in 'q' before calling CheckCacheExpiration(), and then verify afterwards 4552 // that they're still the same. If m->NewQuestions has changed (because mDNS_StopQuery_internal 4553 // advanced it), that means the question was deleted, so we no longer need to worry about answering 4554 // it (and indeed 'q' is now a dangling pointer, so dereferencing it at all would be bad, and the 4555 // values we computed for slot and cg are now stale and relate to a question that no longer exists). 4556 // 4557 // We can't use the usual m->CurrentQuestion mechanism for this because CacheRecordDeferredAdd() and 4558 // CacheRecordRmv() both use that themselves when walking the list of (non-new) questions generating callbacks. 4559 // Fortunately mDNS_StopQuery_internal auto-advances both m->CurrentQuestion *AND* m->NewQuestions when 4560 // deleting a question, so luckily we have an easy alternative way of detecting if our question got deleted. 4561 4562 if (m->lock_rrcache) LogMsg("AnswerNewQuestion ERROR! Cache already locked!"); 4563 // This should be safe, because calling the client's question callback may cause the 4564 // question list to be modified, but should not ever cause the rrcache list to be modified. 4565 // If the client's question callback deletes the question, then m->CurrentQuestion will 4566 // be advanced, and we'll exit out of the loop 4567 m->lock_rrcache = 1; 4568 if (m->CurrentQuestion) 4569 LogMsg("AnswerNewQuestion ERROR m->CurrentQuestion already set: %##s (%s)", 4570 m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype)); 4571 m->CurrentQuestion = q; // Indicate which question we're answering, so we'll know if it gets deleted 4572 4573 if (q->NoAnswer == NoAnswer_Fail) 4574 { 4575 LogMsg("AnswerNewQuestion: NoAnswer_Fail %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 4576 MakeNegativeCacheRecord(m, &m->rec.r, &q->qname, q->qnamehash, q->qtype, q->qclass, 60, mDNSInterface_Any, q->qDNSServer); 4577 q->NoAnswer = NoAnswer_Normal; // Temporarily turn off answer suppression 4578 AnswerCurrentQuestionWithResourceRecord(m, &m->rec.r, QC_addnocache); 4579 // Don't touch the question if it has been stopped already 4580 if (m->CurrentQuestion == q) q->NoAnswer = NoAnswer_Fail; // Restore NoAnswer state 4581 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 4582 } 4583 4584 if (m->CurrentQuestion != q) 4585 { 4586 LogInfo("AnswerNewQuestion: Question deleted while generating NoAnswer_Fail response"); 4587 goto exit; 4588 } 4589 4590 // See if we want to tell it about LocalOnly/P2P records. If we answered them using LocalOnly 4591 // or P2P record, then we are done. 4592 if (AnswerQuestionWithLORecord(m, q, mDNSfalse)) 4593 goto exit; 4594 4595 // If we are not supposed to answer this question, generate a negative response. 4596 // Temporarily suspend the SuppressQuery so that AnswerCurrentQuestionWithResourceRecord can answer the question 4597 // 4598 // If it is a question trying to validate some response, it already checked the cache for a response. If it still 4599 // reissues a question it means it could not find the RRSIGs. So, we need to bypass the cache check and send 4600 // the question out. 4601 if (QuerySuppressed(q)) 4602 { 4603 AnswerSuppressedQuestion(m, q); 4604 } 4605 else if (!q->ValidatingResponse) 4606 { 4607 CacheRecord *rr; 4608 for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) 4609 if (SameNameRecordAnswersQuestion(&rr->resrec, q)) 4610 { 4611 // SecsSinceRcvd is whole number of elapsed seconds, rounded down 4612 mDNSu32 SecsSinceRcvd = ((mDNSu32)(m->timenow - rr->TimeRcvd)) / mDNSPlatformOneSecond; 4613 if (rr->resrec.rroriginalttl <= SecsSinceRcvd) 4614 { 4615 LogMsg("AnswerNewQuestion: How is rr->resrec.rroriginalttl %lu <= SecsSinceRcvd %lu for %s %d %d", 4616 rr->resrec.rroriginalttl, SecsSinceRcvd, CRDisplayString(m, rr), m->timenow, rr->TimeRcvd); 4617 continue; // Go to next one in loop 4618 } 4619 4620 // If this record set is marked unique, then that means we can reasonably assume we have the whole set 4621 // -- we don't need to rush out on the network and query immediately to see if there are more answers out there 4622 if ((rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) || (q->ExpectUnique)) 4623 ShouldQueryImmediately = mDNSfalse; 4624 q->CurrentAnswers++; 4625 if (rr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers++; 4626 if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers++; 4627 AnsweredFromCache = mDNStrue; 4628 AnswerCurrentQuestionWithResourceRecord(m, rr, QC_add); 4629 if (m->CurrentQuestion != q) break; // If callback deleted q, then we're finished here 4630 } 4631 else if (RRTypeIsAddressType(rr->resrec.rrtype) && RRTypeIsAddressType(q->qtype)) 4632 ShouldQueryImmediately = mDNSfalse; 4633 } 4634 // We don't use LogInfo for this "Question deleted" message because it happens so routinely that 4635 // it's not remotely remarkable, and therefore unlikely to be of much help tracking down bugs. 4636 if (m->CurrentQuestion != q) { debugf("AnswerNewQuestion: Question deleted while giving cache answers"); goto exit; } 4637 4638 // Neither a local record nor a cache entry could answer this question. If this question need to be retried 4639 // with search domains, generate a negative response which will now retry after appending search domains. 4640 // If the query was suppressed above, we already generated a negative response. When it gets unsuppressed, 4641 // we will retry with search domains. 4642 if (!QuerySuppressed(q) && !AnsweredFromCache && q->RetryWithSearchDomains) 4643 { 4644 LogInfo("AnswerNewQuestion: Generating response for retrying with search domains %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 4645 GenerateNegativeResponse(m, QC_forceresponse); 4646 } 4647 4648 if (m->CurrentQuestion != q) { debugf("AnswerNewQuestion: Question deleted while giving negative answer"); goto exit; } 4649 4650 // Note: When a query gets suppressed or retried with search domains, we de-activate the question. 4651 // Hence we don't execute the following block of code for those cases. 4652 if (ShouldQueryImmediately && ActiveQuestion(q)) 4653 { 4654 debugf("AnswerNewQuestion: ShouldQueryImmediately %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 4655 q->ThisQInterval = InitialQuestionInterval; 4656 q->LastQTime = m->timenow - q->ThisQInterval; 4657 if (mDNSOpaque16IsZero(q->TargetQID)) // For mDNS, spread packets to avoid a burst of simultaneous queries 4658 { 4659 // Compute random delay in the range 1-6 seconds, then divide by 50 to get 20-120ms 4660 if (!m->RandomQueryDelay) 4661 m->RandomQueryDelay = (mDNSPlatformOneSecond + mDNSRandom(mDNSPlatformOneSecond*5) - 1) / 50 + 1; 4662 q->LastQTime += m->RandomQueryDelay; 4663 } 4664 } 4665 4666 // IN ALL CASES make sure that m->NextScheduledQuery is set appropriately. 4667 // In cases where m->NewQuestions->DelayAnswering is set, we may have delayed generating our 4668 // answers for this question until *after* its scheduled transmission time, in which case 4669 // m->NextScheduledQuery may now be set to 'never', and in that case -- even though we're *not* doing 4670 // ShouldQueryImmediately -- we still need to make sure we set m->NextScheduledQuery correctly. 4671 SetNextQueryTime(m,q); 4672 4673 exit: 4674 m->CurrentQuestion = mDNSNULL; 4675 m->lock_rrcache = 0; 4676 } 4677 4678 // When a NewLocalOnlyQuestion is created, AnswerNewLocalOnlyQuestion runs though our ResourceRecords delivering any 4679 // appropriate answers, stopping if it reaches a NewLocalOnlyRecord -- these will be handled by AnswerAllLocalQuestionsWithLocalAuthRecord 4680 mDNSlocal void AnswerNewLocalOnlyQuestion(mDNS *const m) 4681 { 4682 mDNSu32 slot; 4683 AuthGroup *ag; 4684 DNSQuestion *q = m->NewLocalOnlyQuestions; // Grab the question we're going to answer 4685 m->NewLocalOnlyQuestions = q->next; // Advance NewLocalOnlyQuestions to the next (if any) 4686 4687 debugf("AnswerNewLocalOnlyQuestion: Answering %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 4688 4689 if (m->CurrentQuestion) 4690 LogMsg("AnswerNewLocalOnlyQuestion ERROR m->CurrentQuestion already set: %##s (%s)", 4691 m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype)); 4692 m->CurrentQuestion = q; // Indicate which question we're answering, so we'll know if it gets deleted 4693 4694 if (m->CurrentRecord) 4695 LogMsg("AnswerNewLocalOnlyQuestion ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord)); 4696 4697 // 1. First walk the LocalOnly records answering the LocalOnly question 4698 // 2. As LocalOnly questions should also be answered by any other Auth records local to the machine, 4699 // walk the ResourceRecords list delivering the answers 4700 slot = AuthHashSlot(&q->qname); 4701 ag = AuthGroupForName(&m->rrauth, slot, q->qnamehash, &q->qname); 4702 if (ag) 4703 { 4704 m->CurrentRecord = ag->members; 4705 while (m->CurrentRecord && m->CurrentRecord != ag->NewLocalOnlyRecords) 4706 { 4707 AuthRecord *rr = m->CurrentRecord; 4708 m->CurrentRecord = rr->next; 4709 if (LocalOnlyRecordAnswersQuestion(rr, q)) 4710 { 4711 AnswerLocalQuestionWithLocalAuthRecord(m, rr, QC_add); 4712 if (m->CurrentQuestion != q) break; // If callback deleted q, then we're finished here 4713 } 4714 } 4715 } 4716 4717 if (m->CurrentQuestion == q) 4718 { 4719 m->CurrentRecord = m->ResourceRecords; 4720 4721 while (m->CurrentRecord && m->CurrentRecord != m->NewLocalRecords) 4722 { 4723 AuthRecord *rr = m->CurrentRecord; 4724 m->CurrentRecord = rr->next; 4725 if (ResourceRecordAnswersQuestion(&rr->resrec, q)) 4726 { 4727 AnswerLocalQuestionWithLocalAuthRecord(m, rr, QC_add); 4728 if (m->CurrentQuestion != q) break; // If callback deleted q, then we're finished here 4729 } 4730 } 4731 } 4732 4733 m->CurrentQuestion = mDNSNULL; 4734 m->CurrentRecord = mDNSNULL; 4735 } 4736 4737 mDNSlocal CacheEntity *GetCacheEntity(mDNS *const m, const CacheGroup *const PreserveCG) 4738 { 4739 CacheEntity *e = mDNSNULL; 4740 4741 if (m->lock_rrcache) { LogMsg("GetFreeCacheRR ERROR! Cache already locked!"); return(mDNSNULL); } 4742 m->lock_rrcache = 1; 4743 4744 // If we have no free records, ask the client layer to give us some more memory 4745 if (!m->rrcache_free && m->MainCallback) 4746 { 4747 if (m->rrcache_totalused != m->rrcache_size) 4748 LogMsg("GetFreeCacheRR: count mismatch: m->rrcache_totalused %lu != m->rrcache_size %lu", 4749 m->rrcache_totalused, m->rrcache_size); 4750 4751 // We don't want to be vulnerable to a malicious attacker flooding us with an infinite 4752 // number of bogus records so that we keep growing our cache until the machine runs out of memory. 4753 // To guard against this, if our cache grows above 512kB (approx 3168 records at 164 bytes each), 4754 // and we're actively using less than 1/32 of that cache, then we purge all the unused records 4755 // and recycle them, instead of allocating more memory. 4756 if (m->rrcache_size > 5000 && m->rrcache_size / 32 > m->rrcache_active) 4757 LogInfo("Possible denial-of-service attack in progress: m->rrcache_size %lu; m->rrcache_active %lu", 4758 m->rrcache_size, m->rrcache_active); 4759 else 4760 { 4761 mDNS_DropLockBeforeCallback(); // Allow client to legally make mDNS API calls from the callback 4762 m->MainCallback(m, mStatus_GrowCache); 4763 mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again 4764 } 4765 } 4766 4767 // If we still have no free records, recycle all the records we can. 4768 // Enumerating the entire cache is moderately expensive, so when we do it, we reclaim all the records we can in one pass. 4769 if (!m->rrcache_free) 4770 { 4771 mDNSu32 oldtotalused = m->rrcache_totalused; 4772 mDNSu32 slot; 4773 for (slot = 0; slot < CACHE_HASH_SLOTS; slot++) 4774 { 4775 CacheGroup **cp = &m->rrcache_hash[slot]; 4776 while (*cp) 4777 { 4778 CacheRecord **rp = &(*cp)->members; 4779 while (*rp) 4780 { 4781 // Records that answer still-active questions are not candidates for recycling 4782 // Records that are currently linked into the CacheFlushRecords list may not be recycled, or we'll crash 4783 if ((*rp)->CRActiveQuestion || (*rp)->NextInCFList) 4784 rp=&(*rp)->next; 4785 else 4786 { 4787 CacheRecord *rr = *rp; 4788 *rp = (*rp)->next; // Cut record from list 4789 ReleaseCacheRecord(m, rr); 4790 } 4791 } 4792 if ((*cp)->rrcache_tail != rp) 4793 verbosedebugf("GetFreeCacheRR: Updating rrcache_tail[%lu] from %p to %p", slot, (*cp)->rrcache_tail, rp); 4794 (*cp)->rrcache_tail = rp; 4795 if ((*cp)->members || (*cp)==PreserveCG) cp=&(*cp)->next; 4796 else ReleaseCacheGroup(m, cp); 4797 } 4798 } 4799 LogInfo("GetCacheEntity recycled %d records to reduce cache from %d to %d", 4800 oldtotalused - m->rrcache_totalused, oldtotalused, m->rrcache_totalused); 4801 } 4802 4803 if (m->rrcache_free) // If there are records in the free list, take one 4804 { 4805 e = m->rrcache_free; 4806 m->rrcache_free = e->next; 4807 if (++m->rrcache_totalused >= m->rrcache_report) 4808 { 4809 LogInfo("RR Cache now using %ld objects", m->rrcache_totalused); 4810 if (m->rrcache_report < 100) m->rrcache_report += 10; 4811 else if (m->rrcache_report < 1000) m->rrcache_report += 100; 4812 else m->rrcache_report += 1000; 4813 } 4814 mDNSPlatformMemZero(e, sizeof(*e)); 4815 } 4816 4817 m->lock_rrcache = 0; 4818 4819 return(e); 4820 } 4821 4822 mDNSlocal CacheRecord *GetCacheRecord(mDNS *const m, CacheGroup *cg, mDNSu16 RDLength) 4823 { 4824 CacheRecord *r = (CacheRecord *)GetCacheEntity(m, cg); 4825 if (r) 4826 { 4827 r->resrec.rdata = (RData*)&r->smallrdatastorage; // By default, assume we're usually going to be using local storage 4828 if (RDLength > InlineCacheRDSize) // If RDLength is too big, allocate extra storage 4829 { 4830 r->resrec.rdata = (RData*)mDNSPlatformMemAllocate(sizeofRDataHeader + RDLength); 4831 if (r->resrec.rdata) r->resrec.rdata->MaxRDLength = r->resrec.rdlength = RDLength; 4832 else { ReleaseCacheEntity(m, (CacheEntity*)r); r = mDNSNULL; } 4833 } 4834 } 4835 return(r); 4836 } 4837 4838 mDNSlocal CacheGroup *GetCacheGroup(mDNS *const m, const mDNSu32 slot, const ResourceRecord *const rr) 4839 { 4840 mDNSu16 namelen = DomainNameLength(rr->name); 4841 CacheGroup *cg = (CacheGroup*)GetCacheEntity(m, mDNSNULL); 4842 if (!cg) { LogMsg("GetCacheGroup: Failed to allocate memory for %##s", rr->name->c); return(mDNSNULL); } 4843 cg->next = m->rrcache_hash[slot]; 4844 cg->namehash = rr->namehash; 4845 cg->members = mDNSNULL; 4846 cg->rrcache_tail = &cg->members; 4847 if (namelen > sizeof(cg->namestorage)) 4848 cg->name = mDNSPlatformMemAllocate(namelen); 4849 else 4850 cg->name = (domainname*)cg->namestorage; 4851 if (!cg->name) 4852 { 4853 LogMsg("GetCacheGroup: Failed to allocate name storage for %##s", rr->name->c); 4854 ReleaseCacheEntity(m, (CacheEntity*)cg); 4855 return(mDNSNULL); 4856 } 4857 AssignDomainName(cg->name, rr->name); 4858 4859 if (CacheGroupForRecord(m, slot, rr)) LogMsg("GetCacheGroup: Already have CacheGroup for %##s", rr->name->c); 4860 m->rrcache_hash[slot] = cg; 4861 if (CacheGroupForRecord(m, slot, rr) != cg) LogMsg("GetCacheGroup: Not finding CacheGroup for %##s", rr->name->c); 4862 4863 return(cg); 4864 } 4865 4866 mDNSexport void mDNS_PurgeCacheResourceRecord(mDNS *const m, CacheRecord *rr) 4867 { 4868 mDNS_CheckLock(m); 4869 4870 // Make sure we mark this record as thoroughly expired -- we don't ever want to give 4871 // a positive answer using an expired record (e.g. from an interface that has gone away). 4872 // We don't want to clear CRActiveQuestion here, because that would leave the record subject to 4873 // summary deletion without giving the proper callback to any questions that are monitoring it. 4874 // By setting UnansweredQueries to MaxUnansweredQueries we ensure it won't trigger any further expiration queries. 4875 rr->TimeRcvd = m->timenow - mDNSPlatformOneSecond * 60; 4876 rr->UnansweredQueries = MaxUnansweredQueries; 4877 rr->resrec.rroriginalttl = 0; 4878 SetNextCacheCheckTimeForRecord(m, rr); 4879 } 4880 4881 mDNSexport mDNSs32 mDNS_TimeNow(const mDNS *const m) 4882 { 4883 mDNSs32 time; 4884 mDNSPlatformLock(m); 4885 if (m->mDNS_busy) 4886 { 4887 LogMsg("mDNS_TimeNow called while holding mDNS lock. This is incorrect. Code protected by lock should just use m->timenow."); 4888 if (!m->timenow) LogMsg("mDNS_TimeNow: m->mDNS_busy is %ld but m->timenow not set", m->mDNS_busy); 4889 } 4890 4891 if (m->timenow) time = m->timenow; 4892 else time = mDNS_TimeNow_NoLock(m); 4893 mDNSPlatformUnlock(m); 4894 return(time); 4895 } 4896 4897 // To avoid pointless CPU thrash, we use SetSPSProxyListChanged(X) to record the last interface that 4898 // had its Sleep Proxy client list change, and defer to actual BPF reconfiguration to mDNS_Execute(). 4899 // (GetNextScheduledEvent() returns "now" when m->SPSProxyListChanged is set) 4900 #define SetSPSProxyListChanged(X) do { \ 4901 if (m->SPSProxyListChanged && m->SPSProxyListChanged != (X)) mDNSPlatformUpdateProxyList(m, m->SPSProxyListChanged); \ 4902 m->SPSProxyListChanged = (X); } while(0) 4903 4904 // Called from mDNS_Execute() to expire stale proxy records 4905 mDNSlocal void CheckProxyRecords(mDNS *const m, AuthRecord *list) 4906 { 4907 m->CurrentRecord = list; 4908 while (m->CurrentRecord) 4909 { 4910 AuthRecord *rr = m->CurrentRecord; 4911 if (rr->resrec.RecordType != kDNSRecordTypeDeregistering && rr->WakeUp.HMAC.l[0]) 4912 { 4913 // If m->SPSSocket is NULL that means we're not acting as a sleep proxy any more, 4914 // so we need to cease proxying for *all* records we may have, expired or not. 4915 if (m->SPSSocket && m->timenow - rr->TimeExpire < 0) // If proxy record not expired yet, update m->NextScheduledSPS 4916 { 4917 if (m->NextScheduledSPS - rr->TimeExpire > 0) 4918 m->NextScheduledSPS = rr->TimeExpire; 4919 } 4920 else // else proxy record expired, so remove it 4921 { 4922 LogSPS("CheckProxyRecords: Removing %d H-MAC %.6a I-MAC %.6a %d %s", 4923 m->ProxyRecords, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, rr->WakeUp.seq, ARDisplayString(m, rr)); 4924 SetSPSProxyListChanged(rr->resrec.InterfaceID); 4925 mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal); 4926 // Don't touch rr after this -- memory may have been free'd 4927 } 4928 } 4929 // Mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal, because 4930 // new records could have been added to the end of the list as a result of that call. 4931 if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now 4932 m->CurrentRecord = rr->next; 4933 } 4934 } 4935 4936 mDNSlocal void CheckRmvEventsForLocalRecords(mDNS *const m) 4937 { 4938 while (m->CurrentRecord) 4939 { 4940 AuthRecord *rr = m->CurrentRecord; 4941 if (rr->AnsweredLocalQ && rr->resrec.RecordType == kDNSRecordTypeDeregistering) 4942 { 4943 debugf("CheckRmvEventsForLocalRecords: Generating local RMV events for %s", ARDisplayString(m, rr)); 4944 rr->resrec.RecordType = kDNSRecordTypeShared; 4945 AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, QC_rmv); 4946 if (m->CurrentRecord == rr) // If rr still exists in list, restore its state now 4947 { 4948 rr->resrec.RecordType = kDNSRecordTypeDeregistering; 4949 rr->AnsweredLocalQ = mDNSfalse; 4950 // SendResponses normally calls CompleteDeregistration after sending goodbyes. 4951 // For LocalOnly records, we don't do that and hence we need to do that here. 4952 if (RRLocalOnly(rr)) CompleteDeregistration(m, rr); 4953 } 4954 } 4955 if (m->CurrentRecord == rr) // If m->CurrentRecord was not auto-advanced, do it ourselves now 4956 m->CurrentRecord = rr->next; 4957 } 4958 } 4959 4960 mDNSlocal void TimeoutQuestions(mDNS *const m) 4961 { 4962 m->NextScheduledStopTime = m->timenow + 0x3FFFFFFF; 4963 if (m->CurrentQuestion) 4964 LogMsg("TimeoutQuestions ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, 4965 DNSTypeName(m->CurrentQuestion->qtype)); 4966 m->CurrentQuestion = m->Questions; 4967 while (m->CurrentQuestion) 4968 { 4969 DNSQuestion *const q = m->CurrentQuestion; 4970 if (q->StopTime) 4971 { 4972 if (!q->TimeoutQuestion) 4973 LogMsg("TimeoutQuestions: ERROR!! TimeoutQuestion not set, but StopTime set for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 4974 4975 if (m->timenow - q->StopTime >= 0) 4976 { 4977 LogInfo("TimeoutQuestions: question %p %##s timed out, time %d", q, q->qname.c, m->timenow - q->StopTime); 4978 GenerateNegativeResponse(m, QC_forceresponse); 4979 if (m->CurrentQuestion == q) q->StopTime = 0; 4980 } 4981 else 4982 { 4983 if (m->NextScheduledStopTime - q->StopTime > 0) 4984 m->NextScheduledStopTime = q->StopTime; 4985 } 4986 } 4987 // If m->CurrentQuestion wasn't modified out from under us, advance it now 4988 // We can't do this at the start of the loop because GenerateNegativeResponse 4989 // depends on having m->CurrentQuestion point to the right question 4990 if (m->CurrentQuestion == q) 4991 m->CurrentQuestion = q->next; 4992 } 4993 m->CurrentQuestion = mDNSNULL; 4994 } 4995 4996 mDNSlocal void mDNSCoreFreeProxyRR(mDNS *const m) 4997 { 4998 AuthRecord *rrPtr = m->SPSRRSet, *rrNext = mDNSNULL; 4999 LogSPS("%s : Freeing stored sleep proxy A/AAAA records", __func__); 5000 while (rrPtr) 5001 { 5002 rrNext = rrPtr->next; 5003 mDNSPlatformMemFree(rrPtr); 5004 rrPtr = rrNext; 5005 } 5006 m->SPSRRSet = mDNSNULL; 5007 } 5008 5009 mDNSexport mDNSs32 mDNS_Execute(mDNS *const m) 5010 { 5011 mDNS_Lock(m); // Must grab lock before trying to read m->timenow 5012 5013 #if APPLE_OSX_mDNSResponder 5014 mDNSLogStatistics(m); 5015 #endif // APPLE_OSX_mDNSResponder 5016 5017 if (m->timenow - m->NextScheduledEvent >= 0) 5018 { 5019 int i; 5020 AuthRecord *head, *tail; 5021 mDNSu32 slot; 5022 AuthGroup *ag; 5023 5024 verbosedebugf("mDNS_Execute"); 5025 5026 if (m->CurrentQuestion) 5027 LogMsg("mDNS_Execute: ERROR m->CurrentQuestion already set: %##s (%s)", 5028 m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype)); 5029 5030 if (m->CurrentRecord) 5031 LogMsg("mDNS_Execute: ERROR m->CurrentRecord already set: %s", ARDisplayString(m, m->CurrentRecord)); 5032 5033 // 1. If we're past the probe suppression time, we can clear it 5034 if (m->SuppressProbes && m->timenow - m->SuppressProbes >= 0) m->SuppressProbes = 0; 5035 5036 // 2. If it's been more than ten seconds since the last probe failure, we can clear the counter 5037 if (m->NumFailedProbes && m->timenow - m->ProbeFailTime >= mDNSPlatformOneSecond * 10) m->NumFailedProbes = 0; 5038 5039 // 3. Purge our cache of stale old records 5040 if (m->rrcache_size && m->timenow - m->NextCacheCheck >= 0) 5041 { 5042 mDNSu32 numchecked = 0; 5043 m->NextCacheCheck = m->timenow + 0x3FFFFFFF; 5044 for (slot = 0; slot < CACHE_HASH_SLOTS; slot++) 5045 { 5046 if (m->timenow - m->rrcache_nextcheck[slot] >= 0) 5047 { 5048 CacheGroup **cp = &m->rrcache_hash[slot]; 5049 m->rrcache_nextcheck[slot] = m->timenow + 0x3FFFFFFF; 5050 while (*cp) 5051 { 5052 debugf("m->NextCacheCheck %4d Slot %3d %##s", numchecked, slot, *cp ? (*cp)->name : (domainname*)"\x04NULL"); 5053 numchecked++; 5054 CheckCacheExpiration(m, slot, *cp); 5055 if ((*cp)->members) cp=&(*cp)->next; 5056 else ReleaseCacheGroup(m, cp); 5057 } 5058 } 5059 // Even if we didn't need to actually check this slot yet, still need to 5060 // factor its nextcheck time into our overall NextCacheCheck value 5061 if (m->NextCacheCheck - m->rrcache_nextcheck[slot] > 0) 5062 m->NextCacheCheck = m->rrcache_nextcheck[slot]; 5063 } 5064 debugf("m->NextCacheCheck %4d checked, next in %d", numchecked, m->NextCacheCheck - m->timenow); 5065 } 5066 5067 if (m->timenow - m->NextScheduledSPS >= 0) 5068 { 5069 m->NextScheduledSPS = m->timenow + 0x3FFFFFFF; 5070 CheckProxyRecords(m, m->DuplicateRecords); // Clear m->DuplicateRecords first, then m->ResourceRecords 5071 CheckProxyRecords(m, m->ResourceRecords); 5072 } 5073 5074 SetSPSProxyListChanged(mDNSNULL); // Perform any deferred BPF reconfiguration now 5075 5076 // Check to see if we need to send any keepalives. Do this after we called CheckProxyRecords above 5077 // as records could have expired during that check 5078 if (m->timenow - m->NextScheduledKA >= 0) 5079 { 5080 m->NextScheduledKA = m->timenow + 0x3FFFFFFF; 5081 mDNS_SendKeepalives(m); 5082 } 5083 5084 // Clear AnnounceOwner if necessary. (Do this *before* SendQueries() and SendResponses().) 5085 if (m->AnnounceOwner && m->timenow - m->AnnounceOwner >= 0) 5086 { 5087 m->AnnounceOwner = 0; 5088 } 5089 5090 if (m->DelaySleep && m->timenow - m->DelaySleep >= 0) 5091 { 5092 m->DelaySleep = 0; 5093 if (m->SleepState == SleepState_Transferring) 5094 { 5095 LogSPS("Re-sleep delay passed; now checking for Sleep Proxy Servers"); 5096 BeginSleepProcessing(m); 5097 } 5098 } 5099 5100 // 4. See if we can answer any of our new local questions from the cache 5101 for (i=0; m->NewQuestions && i<1000; i++) 5102 { 5103 if (m->NewQuestions->DelayAnswering && m->timenow - m->NewQuestions->DelayAnswering < 0) break; 5104 AnswerNewQuestion(m); 5105 } 5106 if (i >= 1000) LogMsg("mDNS_Execute: AnswerNewQuestion exceeded loop limit"); 5107 5108 // Make sure we deliver *all* local RMV events, and clear the corresponding rr->AnsweredLocalQ flags, *before* 5109 // we begin generating *any* new ADD events in the m->NewLocalOnlyQuestions and m->NewLocalRecords loops below. 5110 for (i=0; i<1000 && m->LocalRemoveEvents; i++) 5111 { 5112 m->LocalRemoveEvents = mDNSfalse; 5113 m->CurrentRecord = m->ResourceRecords; 5114 CheckRmvEventsForLocalRecords(m); 5115 // Walk the LocalOnly records and deliver the RMV events 5116 for (slot = 0; slot < AUTH_HASH_SLOTS; slot++) 5117 for (ag = m->rrauth.rrauth_hash[slot]; ag; ag = ag->next) 5118 { 5119 m->CurrentRecord = ag->members; 5120 if (m->CurrentRecord) CheckRmvEventsForLocalRecords(m); 5121 } 5122 } 5123 5124 if (i >= 1000) LogMsg("mDNS_Execute: m->LocalRemoveEvents exceeded loop limit"); 5125 5126 for (i=0; m->NewLocalOnlyQuestions && i<1000; i++) AnswerNewLocalOnlyQuestion(m); 5127 if (i >= 1000) LogMsg("mDNS_Execute: AnswerNewLocalOnlyQuestion exceeded loop limit"); 5128 5129 head = tail = mDNSNULL; 5130 for (i=0; i<1000 && m->NewLocalRecords && m->NewLocalRecords != head; i++) 5131 { 5132 AuthRecord *rr = m->NewLocalRecords; 5133 m->NewLocalRecords = m->NewLocalRecords->next; 5134 if (LocalRecordReady(rr)) 5135 { 5136 debugf("mDNS_Execute: Delivering Add event with LocalAuthRecord %s", ARDisplayString(m, rr)); 5137 AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, QC_add); 5138 } 5139 else if (!rr->next) 5140 { 5141 // If we have just one record that is not ready, we don't have to unlink and 5142 // reinsert. As the NewLocalRecords will be NULL for this case, the loop will 5143 // terminate and set the NewLocalRecords to rr. 5144 debugf("mDNS_Execute: Just one LocalAuthRecord %s, breaking out of the loop early", ARDisplayString(m, rr)); 5145 if (head != mDNSNULL || m->NewLocalRecords != mDNSNULL) 5146 LogMsg("mDNS_Execute: ERROR!!: head %p, NewLocalRecords %p", head, m->NewLocalRecords); 5147 5148 head = rr; 5149 } 5150 else 5151 { 5152 AuthRecord **p = &m->ResourceRecords; // Find this record in our list of active records 5153 debugf("mDNS_Execute: Skipping LocalAuthRecord %s", ARDisplayString(m, rr)); 5154 // if this is the first record we are skipping, move to the end of the list. 5155 // if we have already skipped records before, append it at the end. 5156 while (*p && *p != rr) p=&(*p)->next; 5157 if (*p) *p = rr->next; // Cut this record from the list 5158 else { LogMsg("mDNS_Execute: ERROR!! Cannot find record %s in ResourceRecords list", ARDisplayString(m, rr)); break; } 5159 if (!head) 5160 { 5161 while (*p) p=&(*p)->next; 5162 *p = rr; 5163 head = tail = rr; 5164 } 5165 else 5166 { 5167 tail->next = rr; 5168 tail = rr; 5169 } 5170 rr->next = mDNSNULL; 5171 } 5172 } 5173 m->NewLocalRecords = head; 5174 debugf("mDNS_Execute: Setting NewLocalRecords to %s", (head ? ARDisplayString(m, head) : "NULL")); 5175 5176 if (i >= 1000) LogMsg("mDNS_Execute: m->NewLocalRecords exceeded loop limit"); 5177 5178 // Check to see if we have any new LocalOnly/P2P records to examine for delivering 5179 // to our local questions 5180 if (m->NewLocalOnlyRecords) 5181 { 5182 m->NewLocalOnlyRecords = mDNSfalse; 5183 for (slot = 0; slot < AUTH_HASH_SLOTS; slot++) 5184 for (ag = m->rrauth.rrauth_hash[slot]; ag; ag = ag->next) 5185 { 5186 for (i=0; i<100 && ag->NewLocalOnlyRecords; i++) 5187 { 5188 AuthRecord *rr = ag->NewLocalOnlyRecords; 5189 ag->NewLocalOnlyRecords = ag->NewLocalOnlyRecords->next; 5190 // LocalOnly records should always be ready as they never probe 5191 if (LocalRecordReady(rr)) 5192 { 5193 debugf("mDNS_Execute: Delivering Add event with LocalAuthRecord %s", ARDisplayString(m, rr)); 5194 AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, QC_add); 5195 } 5196 else LogMsg("mDNS_Execute: LocalOnlyRecord %s not ready", ARDisplayString(m, rr)); 5197 } 5198 // We limit about 100 per AuthGroup that can be serviced at a time 5199 if (i >= 100) LogMsg("mDNS_Execute: ag->NewLocalOnlyRecords exceeded loop limit"); 5200 } 5201 } 5202 5203 // 5. See what packets we need to send 5204 if (m->mDNSPlatformStatus != mStatus_NoError || (m->SleepState == SleepState_Sleeping)) 5205 DiscardDeregistrations(m); 5206 if (m->mDNSPlatformStatus == mStatus_NoError && (m->SuppressSending == 0 || m->timenow - m->SuppressSending >= 0)) 5207 { 5208 // If the platform code is ready, and we're not suppressing packet generation right now 5209 // then send our responses, probes, and questions. 5210 // We check the cache first, because there might be records close to expiring that trigger questions to refresh them. 5211 // We send queries next, because there might be final-stage probes that complete their probing here, causing 5212 // them to advance to announcing state, and we want those to be included in any announcements we send out. 5213 // Finally, we send responses, including the previously mentioned records that just completed probing. 5214 m->SuppressSending = 0; 5215 5216 // 6. Send Query packets. This may cause some probing records to advance to announcing state 5217 if (m->timenow - m->NextScheduledQuery >= 0 || m->timenow - m->NextScheduledProbe >= 0) SendQueries(m); 5218 if (m->timenow - m->NextScheduledQuery >= 0) 5219 { 5220 DNSQuestion *q; 5221 LogMsg("mDNS_Execute: SendQueries didn't send all its queries (%d - %d = %d) will try again in one second", 5222 m->timenow, m->NextScheduledQuery, m->timenow - m->NextScheduledQuery); 5223 m->NextScheduledQuery = m->timenow + mDNSPlatformOneSecond; 5224 for (q = m->Questions; q && q != m->NewQuestions; q=q->next) 5225 if (ActiveQuestion(q) && m->timenow - NextQSendTime(q) >= 0) 5226 LogMsg("mDNS_Execute: SendQueries didn't send %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 5227 } 5228 if (m->timenow - m->NextScheduledProbe >= 0) 5229 { 5230 LogMsg("mDNS_Execute: SendQueries didn't send all its probes (%d - %d = %d) will try again in one second", 5231 m->timenow, m->NextScheduledProbe, m->timenow - m->NextScheduledProbe); 5232 m->NextScheduledProbe = m->timenow + mDNSPlatformOneSecond; 5233 } 5234 5235 // 7. Send Response packets, including probing records just advanced to announcing state 5236 if (m->timenow - m->NextScheduledResponse >= 0) SendResponses(m); 5237 if (m->timenow - m->NextScheduledResponse >= 0) 5238 { 5239 LogMsg("mDNS_Execute: SendResponses didn't send all its responses; will try again in one second"); 5240 m->NextScheduledResponse = m->timenow + mDNSPlatformOneSecond; 5241 } 5242 } 5243 5244 // Clear RandomDelay values, ready to pick a new different value next time 5245 m->RandomQueryDelay = 0; 5246 m->RandomReconfirmDelay = 0; 5247 5248 if (m->NextScheduledStopTime && m->timenow - m->NextScheduledStopTime >= 0) TimeoutQuestions(m); 5249 #ifndef UNICAST_DISABLED 5250 if (m->NextSRVUpdate && m->timenow - m->NextSRVUpdate >= 0) UpdateAllSRVRecords(m); 5251 if (m->timenow - m->NextScheduledNATOp >= 0) CheckNATMappings(m); 5252 if (m->timenow - m->NextuDNSEvent >= 0) uDNS_Tasks(m); 5253 #endif 5254 } 5255 5256 // Note about multi-threaded systems: 5257 // On a multi-threaded system, some other thread could run right after the mDNS_Unlock(), 5258 // performing mDNS API operations that change our next scheduled event time. 5259 // 5260 // On multi-threaded systems (like the current Windows implementation) that have a single main thread 5261 // calling mDNS_Execute() (and other threads allowed to call mDNS API routines) it is the responsibility 5262 // of the mDNSPlatformUnlock() routine to signal some kind of stateful condition variable that will 5263 // signal whatever blocking primitive the main thread is using, so that it will wake up and execute one 5264 // more iteration of its loop, and immediately call mDNS_Execute() again. The signal has to be stateful 5265 // in the sense that if the main thread has not yet entered its blocking primitive, then as soon as it 5266 // does, the state of the signal will be noticed, causing the blocking primitive to return immediately 5267 // without blocking. This avoids the race condition between the signal from the other thread arriving 5268 // just *before* or just *after* the main thread enters the blocking primitive. 5269 // 5270 // On multi-threaded systems (like the current Mac OS 9 implementation) that are entirely timer-driven, 5271 // with no main mDNS_Execute() thread, it is the responsibility of the mDNSPlatformUnlock() routine to 5272 // set the timer according to the m->NextScheduledEvent value, and then when the timer fires, the timer 5273 // callback function should call mDNS_Execute() (and ignore the return value, which may already be stale 5274 // by the time it gets to the timer callback function). 5275 5276 mDNS_Unlock(m); // Calling mDNS_Unlock is what gives m->NextScheduledEvent its new value 5277 return(m->NextScheduledEvent); 5278 } 5279 5280 #ifndef UNICAST_DISABLED 5281 mDNSlocal void SuspendLLQs(mDNS *m) 5282 { 5283 DNSQuestion *q; 5284 for (q = m->Questions; q; q = q->next) 5285 if (ActiveQuestion(q) && !mDNSOpaque16IsZero(q->TargetQID) && q->LongLived && q->state == LLQ_Established) 5286 { q->ReqLease = 0; sendLLQRefresh(m, q); } 5287 } 5288 #endif // UNICAST_DISABLED 5289 5290 mDNSlocal mDNSBool QuestionHasLocalAnswers(mDNS *const m, DNSQuestion *q) 5291 { 5292 AuthRecord *rr; 5293 mDNSu32 slot; 5294 AuthGroup *ag; 5295 5296 slot = AuthHashSlot(&q->qname); 5297 ag = AuthGroupForName(&m->rrauth, slot, q->qnamehash, &q->qname); 5298 if (ag) 5299 { 5300 for (rr = ag->members; rr; rr=rr->next) 5301 // Filter the /etc/hosts records - LocalOnly, Unique, A/AAAA/CNAME 5302 if (UniqueLocalOnlyRecord(rr) && LocalOnlyRecordAnswersQuestion(rr, q)) 5303 { 5304 LogInfo("QuestionHasLocalAnswers: Question %p %##s (%s) has local answer %s", q, q->qname.c, DNSTypeName(q->qtype), ARDisplayString(m, rr)); 5305 return mDNStrue; 5306 } 5307 } 5308 return mDNSfalse; 5309 } 5310 5311 // ActivateUnicastQuery() is called from three places: 5312 // 1. When a new question is created 5313 // 2. On wake from sleep 5314 // 3. When the DNS configuration changes 5315 // In case 1 we don't want to mess with our established ThisQInterval and LastQTime (ScheduleImmediately is false) 5316 // In cases 2 and 3 we do want to cause the question to be resent immediately (ScheduleImmediately is true) 5317 mDNSlocal void ActivateUnicastQuery(mDNS *const m, DNSQuestion *const question, mDNSBool ScheduleImmediately) 5318 { 5319 // For now this AutoTunnel stuff is specific to Mac OS X. 5320 // In the future, if there's demand, we may see if we can abstract it out cleanly into the platform layer 5321 #if APPLE_OSX_mDNSResponder 5322 // Even though BTMM client tunnels are only useful for AAAA queries, we need to treat v4 and v6 queries equally. 5323 // Otherwise we can get the situation where the A query completes really fast (with an NXDOMAIN result) and the 5324 // caller then gives up waiting for the AAAA result while we're still in the process of setting up the tunnel. 5325 // To level the playing field, we block both A and AAAA queries while tunnel setup is in progress, and then 5326 // returns results for both at the same time. If we are looking for the _autotunnel6 record, then skip this logic 5327 // as this would trigger looking up _autotunnel6._autotunnel6 and end up failing the original query. 5328 5329 if (RRTypeIsAddressType(question->qtype) && PrivateQuery(question) && 5330 !SameDomainLabel(question->qname.c, (const mDNSu8 *)"\x0c_autotunnel6")&& question->QuestionCallback != AutoTunnelCallback) 5331 { 5332 question->NoAnswer = NoAnswer_Suspended; 5333 AddNewClientTunnel(m, question); 5334 return; 5335 } 5336 #endif // APPLE_OSX_mDNSResponder 5337 5338 if (!question->DuplicateOf) 5339 { 5340 debugf("ActivateUnicastQuery: %##s %s%s%s", 5341 question->qname.c, DNSTypeName(question->qtype), PrivateQuery(question) ? " (Private)" : "", ScheduleImmediately ? " ScheduleImmediately" : ""); 5342 question->CNAMEReferrals = 0; 5343 if (question->nta) { CancelGetZoneData(m, question->nta); question->nta = mDNSNULL; } 5344 if (question->LongLived) 5345 { 5346 question->state = LLQ_InitialRequest; 5347 question->id = zeroOpaque64; 5348 question->servPort = zeroIPPort; 5349 if (question->tcp) { DisposeTCPConn(question->tcp); question->tcp = mDNSNULL; } 5350 } 5351 // If the question has local answers, then we don't want answers from outside 5352 if (ScheduleImmediately && !QuestionHasLocalAnswers(m, question)) 5353 { 5354 question->ThisQInterval = InitialQuestionInterval; 5355 question->LastQTime = m->timenow - question->ThisQInterval; 5356 SetNextQueryTime(m, question); 5357 } 5358 } 5359 } 5360 5361 // Caller should hold the lock 5362 mDNSexport void mDNSCoreRestartAddressQueries(mDNS *const m, mDNSBool SearchDomainsChanged, FlushCache flushCacheRecords, 5363 CallbackBeforeStartQuery BeforeStartCallback, void *context) 5364 { 5365 DNSQuestion *q; 5366 DNSQuestion *restart = mDNSNULL; 5367 5368 mDNS_CheckLock(m); 5369 5370 // 1. Flush the cache records 5371 if (flushCacheRecords) flushCacheRecords(m); 5372 5373 // 2. Even though we may have purged the cache records above, before it can generate RMV event 5374 // we are going to stop the question. Hence we need to deliver the RMV event before we 5375 // stop the question. 5376 // 5377 // CurrentQuestion is used by RmvEventsForQuestion below. While delivering RMV events, the 5378 // application callback can potentially stop the current question (detected by CurrentQuestion) or 5379 // *any* other question which could be the next one that we may process here. RestartQuestion 5380 // points to the "next" question which will be automatically advanced in mDNS_StopQuery_internal 5381 // if the "next" question is stopped while the CurrentQuestion is stopped 5382 5383 if (m->RestartQuestion) 5384 LogMsg("mDNSCoreRestartAddressQueries: ERROR!! m->RestartQuestion already set: %##s (%s)", 5385 m->RestartQuestion->qname.c, DNSTypeName(m->RestartQuestion->qtype)); 5386 5387 m->RestartQuestion = m->Questions; 5388 while (m->RestartQuestion) 5389 { 5390 q = m->RestartQuestion; 5391 m->RestartQuestion = q->next; 5392 // GetZoneData questions are referenced by other questions (original query that started the GetZoneData 5393 // question) through their "nta" pointer. Normally when the original query stops, it stops the 5394 // GetZoneData question and also frees the memory (See CancelGetZoneData). If we stop the GetZoneData 5395 // question followed by the original query that refers to this GetZoneData question, we will end up 5396 // freeing the GetZoneData question and then start the "freed" question at the end. 5397 5398 if (IsGetZoneDataQuestion(q)) 5399 { 5400 DNSQuestion *refq = q->next; 5401 LogInfo("mDNSCoreRestartAddressQueries: Skipping GetZoneDataQuestion %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype)); 5402 // debug stuff, we just try to find the referencing question and don't do much with it 5403 while (refq) 5404 { 5405 if (q == &refq->nta->question) 5406 { 5407 LogInfo("mDNSCoreRestartAddressQueries: Question %p %##s (%s) referring to GetZoneDataQuestion %p, not stopping", refq, refq->qname.c, DNSTypeName(refq->qtype), q); 5408 } 5409 refq = refq->next; 5410 } 5411 continue; 5412 } 5413 5414 // This function is called when /etc/hosts changes and that could affect A, AAAA and CNAME queries 5415 if (q->qtype != kDNSType_A && q->qtype != kDNSType_AAAA && q->qtype != kDNSType_CNAME) continue; 5416 5417 // If the search domains did not change, then we restart all the queries. Otherwise, only 5418 // for queries for which we "might" have appended search domains ("might" because we may 5419 // find results before we apply search domains even though AppendSearchDomains is set to 1) 5420 if (!SearchDomainsChanged || q->AppendSearchDomains) 5421 { 5422 // NOTE: CacheRecordRmvEventsForQuestion will not generate RMV events for queries that have non-zero 5423 // LOAddressAnswers. Hence it is important that we call CacheRecordRmvEventsForQuestion before 5424 // LocalRecordRmvEventsForQuestion (which decrements LOAddressAnswers). Let us say that 5425 // /etc/hosts has an A Record for web.apple.com. Any queries for web.apple.com will be answered locally. 5426 // But this can't prevent a CNAME/AAAA query to not to be sent on the wire. When it is sent on the wire, 5427 // it could create cache entries. When we are restarting queries, we can't deliver the cache RMV events 5428 // for the original query using these cache entries as ADDs were never delivered using these cache 5429 // entries and hence this order is needed. 5430 5431 // If the query is suppressed, the RMV events won't be delivered 5432 if (!CacheRecordRmvEventsForQuestion(m, q)) { LogInfo("mDNSCoreRestartAddressQueries: Question deleted while delivering Cache Record RMV events"); continue; } 5433 5434 // SuppressQuery status does not affect questions that are answered using local records 5435 if (!LocalRecordRmvEventsForQuestion(m, q)) { LogInfo("mDNSCoreRestartAddressQueries: Question deleted while delivering Local Record RMV events"); continue; } 5436 5437 LogInfo("mDNSCoreRestartAddressQueries: Stop question %p %##s (%s), AppendSearchDomains %d, qnameOrig %p", q, 5438 q->qname.c, DNSTypeName(q->qtype), q->AppendSearchDomains, q->qnameOrig); 5439 mDNS_StopQuery_internal(m, q); 5440 // Reset state so that it looks like it was in the beginning i.e it should look at /etc/hosts, cache 5441 // and then search domains should be appended. At the beginning, qnameOrig was NULL. 5442 if (q->qnameOrig) 5443 { 5444 LogInfo("mDNSCoreRestartAddressQueries: qnameOrig %##s", q->qnameOrig); 5445 AssignDomainName(&q->qname, q->qnameOrig); 5446 mDNSPlatformMemFree(q->qnameOrig); 5447 q->qnameOrig = mDNSNULL; 5448 q->RetryWithSearchDomains = ApplySearchDomainsFirst(q) ? 1 : 0; 5449 } 5450 q->SearchListIndex = 0; 5451 q->next = restart; 5452 restart = q; 5453 } 5454 } 5455 5456 // 3. Callback before we start the query 5457 if (BeforeStartCallback) BeforeStartCallback(m, context); 5458 5459 // 4. Restart all the stopped queries 5460 while (restart) 5461 { 5462 q = restart; 5463 restart = restart->next; 5464 q->next = mDNSNULL; 5465 LogInfo("mDNSCoreRestartAddressQueries: Start question %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype)); 5466 mDNS_StartQuery_internal(m, q); 5467 } 5468 } 5469 5470 mDNSexport void mDNSCoreRestartQueries(mDNS *const m) 5471 { 5472 DNSQuestion *q; 5473 5474 #ifndef UNICAST_DISABLED 5475 // Retrigger all our uDNS questions 5476 if (m->CurrentQuestion) 5477 LogMsg("mDNSCoreRestartQueries: ERROR m->CurrentQuestion already set: %##s (%s)", 5478 m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype)); 5479 m->CurrentQuestion = m->Questions; 5480 while (m->CurrentQuestion) 5481 { 5482 q = m->CurrentQuestion; 5483 m->CurrentQuestion = m->CurrentQuestion->next; 5484 if (!mDNSOpaque16IsZero(q->TargetQID) && ActiveQuestion(q)) ActivateUnicastQuery(m, q, mDNStrue); 5485 } 5486 #endif 5487 5488 // Retrigger all our mDNS questions 5489 for (q = m->Questions; q; q=q->next) // Scan our list of questions 5490 mDNSCoreRestartQuestion(m, q); 5491 } 5492 5493 // restart question if it's multicast and currently active 5494 mDNSexport void mDNSCoreRestartQuestion(mDNS *const m, DNSQuestion *q) 5495 { 5496 if (mDNSOpaque16IsZero(q->TargetQID) && ActiveQuestion(q)) 5497 { 5498 q->ThisQInterval = InitialQuestionInterval; // MUST be > zero for an active question 5499 #if mDNS_REQUEST_UNICAST_RESPONSE 5500 q->RequestUnicast = SET_QU_IN_FIRST_FOUR_QUERIES; 5501 #else // mDNS_REQUEST_UNICAST_RESPONSE 5502 q->RequestUnicast = SET_QU_IN_FIRST_QUERY; 5503 #endif // mDNS_REQUEST_UNICAST_RESPONSE 5504 q->LastQTime = m->timenow - q->ThisQInterval; 5505 q->RecentAnswerPkts = 0; 5506 ExpireDupSuppressInfo(q->DupSuppress, m->timenow); 5507 m->NextScheduledQuery = m->timenow; 5508 } 5509 } 5510 5511 // restart the probe/announce cycle for multicast record 5512 mDNSexport void mDNSCoreRestartRegistration(mDNS *const m, AuthRecord *rr, int announceCount) 5513 { 5514 if (!AuthRecord_uDNS(rr)) 5515 { 5516 if (rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->DependentOn) rr->resrec.RecordType = kDNSRecordTypeUnique; 5517 rr->ProbeCount = DefaultProbeCountForRecordType(rr->resrec.RecordType); 5518 5519 // announceCount < 0 indicates default announce count should be used 5520 if (announceCount < 0) 5521 announceCount = InitialAnnounceCount; 5522 if (rr->AnnounceCount < announceCount) 5523 rr->AnnounceCount = announceCount; 5524 5525 if (mDNS_KeepaliveRecord(&rr->resrec)) 5526 rr->AnnounceCount = 0; // Do not announce keepalive records 5527 else 5528 rr->AnnounceCount = InitialAnnounceCount; 5529 rr->SendNSECNow = mDNSNULL; 5530 InitializeLastAPTime(m, rr); 5531 } 5532 } 5533 5534 // *************************************************************************** 5535 #if COMPILER_LIKES_PRAGMA_MARK 5536 #pragma mark - 5537 #pragma mark - Power Management (Sleep/Wake) 5538 #endif 5539 5540 mDNSexport void mDNS_UpdateAllowSleep(mDNS *const m) 5541 { 5542 #ifndef IDLESLEEPCONTROL_DISABLED 5543 mDNSBool allowSleep = mDNStrue; 5544 char reason[128]; 5545 5546 reason[0] = 0; 5547 5548 if (m->SystemSleepOnlyIfWakeOnLAN) 5549 { 5550 // Don't sleep if we are a proxy for any services 5551 if (m->ProxyRecords) 5552 { 5553 allowSleep = mDNSfalse; 5554 mDNS_snprintf(reason, sizeof(reason), "sleep proxy for %d records", m->ProxyRecords); 5555 LogInfo("mDNS_UpdateAllowSleep: Sleep disabled because we are proxying %d records", m->ProxyRecords); 5556 } 5557 5558 if (allowSleep && mDNSCoreHaveAdvertisedMulticastServices(m)) 5559 { 5560 // Scan the list of active interfaces 5561 NetworkInterfaceInfo *intf; 5562 for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next)) 5563 { 5564 if (intf->McastTxRx && !intf->Loopback && !mDNSPlatformInterfaceIsD2D(intf->InterfaceID)) 5565 { 5566 // Disallow sleep if this interface doesn't support NetWake 5567 if (!intf->NetWake) 5568 { 5569 allowSleep = mDNSfalse; 5570 mDNS_snprintf(reason, sizeof(reason), "%s does not support NetWake", intf->ifname); 5571 LogInfo("mDNS_UpdateAllowSleep: Sleep disabled because %s does not support NetWake", intf->ifname); 5572 break; 5573 } 5574 5575 // Disallow sleep if there is no sleep proxy server 5576 const CacheRecord *cr = FindSPSInCache1(m, &intf->NetWakeBrowse, mDNSNULL, mDNSNULL); 5577 if ( cr == mDNSNULL) 5578 { 5579 allowSleep = mDNSfalse; 5580 mDNS_snprintf(reason, sizeof(reason), "No sleep proxy server on %s", intf->ifname); 5581 LogInfo("mDNS_UpdateAllowSleep: Sleep disabled because %s has no sleep proxy server", intf->ifname); 5582 break; 5583 } 5584 else if (m->SPSType != 0) 5585 { 5586 mDNSu32 mymetric = LocalSPSMetric(m); 5587 mDNSu32 metric = SPSMetric(cr->resrec.rdata->u.name.c); 5588 if (metric >= mymetric) 5589 { 5590 allowSleep = mDNSfalse; 5591 mDNS_snprintf(reason, sizeof(reason), "No sleep proxy server with better metric on %s", intf->ifname); 5592 LogInfo("mDNS_UpdateAllowSleep: Sleep disabled because %s has no sleep proxy server with a better metric", intf->ifname); 5593 break; 5594 } 5595 } 5596 } 5597 } 5598 } 5599 } 5600 5601 // Call the platform code to enable/disable sleep 5602 mDNSPlatformSetAllowSleep(m, allowSleep, reason); 5603 #else 5604 (void) m; 5605 #endif /* !defined(IDLESLEEPCONTROL_DISABLED) */ 5606 } 5607 5608 mDNSlocal mDNSBool mDNSUpdateOkToSend(mDNS *const m, AuthRecord *rr, NetworkInterfaceInfo *const intf, mDNSu32 scopeid) 5609 { 5610 // If it is not a uDNS record, check to see if the updateid is zero. "updateid" is cleared when we have 5611 // sent the resource record on all the interfaces. If the update id is not zero, check to see if it is time 5612 // to send. 5613 if (AuthRecord_uDNS(rr) || (rr->AuthFlags & AuthFlagsWakeOnly) || mDNSOpaque16IsZero(rr->updateid) || 5614 m->timenow - (rr->LastAPTime + rr->ThisAPInterval) < 0) 5615 { 5616 return mDNSfalse; 5617 } 5618 5619 // If we have a pending registration for "scopeid", it is ok to send the update on that interface. 5620 // If the scopeid is too big to check for validity, we don't check against updateIntID. When 5621 // we successfully update on all the interfaces (with whatever set in "rr->updateIntID"), we clear 5622 // updateid and we should have returned from above. 5623 // 5624 // Note: scopeid is the same as intf->InterfaceID. It is passed in so that we don't have to call the 5625 // platform function to extract the value from "intf" everytime. 5626 5627 if ((scopeid >= (sizeof(rr->updateIntID) * mDNSNBBY) || bit_get_opaque64(rr->updateIntID, scopeid)) && 5628 (!rr->resrec.InterfaceID || rr->resrec.InterfaceID == intf->InterfaceID)) 5629 return mDNStrue; 5630 5631 return mDNSfalse; 5632 } 5633 5634 mDNSexport void UpdateRMACCallback(mDNS *const m, void *context) 5635 { 5636 IPAddressMACMapping *addrmap = (IPAddressMACMapping *)context ; 5637 m->CurrentRecord = m->ResourceRecords; 5638 5639 if (!addrmap) 5640 { 5641 LogMsg("UpdateRMACCallback: Address mapping is NULL"); 5642 return; 5643 } 5644 5645 while (m->CurrentRecord) 5646 { 5647 AuthRecord *rr = m->CurrentRecord; 5648 // If this is a keepalive record and the remote IP address matches, update the RData 5649 if (mDNS_KeepaliveRecord(&rr->resrec)) 5650 { 5651 mDNSAddr raddr; 5652 getKeepaliveRaddr(m, rr, &raddr); 5653 if (mDNSSameAddress(&raddr, &addrmap->ipaddr)) 5654 { 5655 UpdateKeepaliveRData(m, rr, mDNSNULL, mDNStrue, (char *)(addrmap->ethaddr)); 5656 } 5657 } 5658 m->CurrentRecord = rr->next; 5659 } 5660 5661 if (addrmap) 5662 { 5663 mDNSPlatformMemFree(addrmap); 5664 } 5665 } 5666 5667 mDNSexport mStatus UpdateKeepaliveRData(mDNS *const m, AuthRecord *rr, NetworkInterfaceInfo *const intf, mDNSBool updateMac, char *ethAddr) 5668 { 5669 mDNSu16 newrdlength; 5670 mDNSAddr laddr, raddr; 5671 mDNSEthAddr eth; 5672 mDNSIPPort lport, rport; 5673 mDNSu32 timeout, seq, ack; 5674 mDNSu16 win; 5675 UTF8str255 txt; 5676 int rdsize; 5677 RData *newrd; 5678 mDNSTCPInfo mti; 5679 mStatus ret; 5680 5681 // Note: If we fail to update the DNS NULL record with additional information in this function, it will be registered 5682 // with the SPS like any other record. SPS will not send keepalives if it does not have additional information. 5683 mDNS_ExtractKeepaliveInfo(rr, &timeout, &laddr, &raddr, ð, &seq, &ack, &lport, &rport, &win); 5684 if (!timeout || mDNSAddressIsZero(&laddr) || mDNSAddressIsZero(&raddr) || mDNSIPPortIsZero(lport) || 5685 mDNSIPPortIsZero(rport)) 5686 { 5687 LogMsg("UpdateKeepaliveRData: not a valid record %s for keepalive %#a:%d %#a:%d", ARDisplayString(m, rr), &laddr, lport.NotAnInteger, &raddr, rport.NotAnInteger); 5688 return mStatus_UnknownErr; 5689 } 5690 5691 if (updateMac) 5692 { 5693 if (laddr.type == mDNSAddrType_IPv4) 5694 newrdlength = mDNS_snprintf((char *)&txt.c[1], sizeof(txt.c) - 1, "t=%d i=%d c=%d h=%#a d=%#a l=%u r=%u m=%s", timeout, kKeepaliveRetryInterval, kKeepaliveRetryCount, &laddr, &raddr, mDNSVal16(lport), mDNSVal16(rport), ethAddr); 5695 else 5696 newrdlength = mDNS_snprintf((char *)&txt.c[1], sizeof(txt.c) - 1, "t=%d i=%d c=%d H=%#a D=%#a l=%u r=%u m=%s", timeout, kKeepaliveRetryInterval, kKeepaliveRetryCount, &laddr, &raddr, mDNSVal16(lport), mDNSVal16(rport), ethAddr); 5697 5698 } 5699 else 5700 { 5701 // If this keepalive packet would be sent on a different interface than the current one that we are processing 5702 // now, then we don't update the DNS NULL record. But we do not prevent it from registering with the SPS. When SPS sees 5703 // this DNS NULL record, it does not send any keepalives as it does not have all the information 5704 mDNSPlatformMemZero(&mti, sizeof (mDNSTCPInfo)); 5705 ret = mDNSPlatformRetrieveTCPInfo(m, &laddr, &lport, &raddr, &rport, &mti); 5706 if (ret != mStatus_NoError) 5707 { 5708 LogMsg("mDNSPlatformRetrieveTCPInfo: mDNSPlatformRetrieveTCPInfo failed %d", ret); 5709 return ret; 5710 } 5711 if ((intf != mDNSNULL) && (mti.IntfId != intf->InterfaceID)) 5712 { 5713 LogInfo("mDNSPlatformRetrieveTCPInfo: InterfaceID mismatch mti.IntfId = %p InterfaceID = %p", mti.IntfId, intf->InterfaceID); 5714 return mStatus_BadParamErr; 5715 } 5716 5717 if (laddr.type == mDNSAddrType_IPv4) 5718 newrdlength = mDNS_snprintf((char *)&txt.c[1], sizeof(txt.c) - 1, "t=%d i=%d c=%d h=%#a d=%#a l=%u r=%u m=%.6a s=%u a=%u w=%u", timeout, kKeepaliveRetryInterval, kKeepaliveRetryCount, &laddr, &raddr, mDNSVal16(lport), mDNSVal16(rport), ð, mti.seq, mti.ack, mti.window); 5719 else 5720 newrdlength = mDNS_snprintf((char *)&txt.c[1], sizeof(txt.c) - 1, "t=%d i=%d c=%d H=%#a D=%#a l=%u r=%u m=%.6a s=%u a=%u w=%u", timeout, kKeepaliveRetryInterval, kKeepaliveRetryCount, &laddr, &raddr, mDNSVal16(lport), mDNSVal16(rport), ð, mti.seq, mti.ack, mti.window); 5721 } 5722 5723 // Did we insert a null byte at the end ? 5724 if (newrdlength == (sizeof(txt.c) - 1)) 5725 { 5726 LogMsg("UpdateKeepaliveRData: could not allocate memory %s", ARDisplayString(m, rr)); 5727 return mStatus_NoMemoryErr; 5728 } 5729 5730 // Include the length for the null byte at the end 5731 txt.c[0] = newrdlength + 1; 5732 // Account for the first length byte and the null byte at the end 5733 newrdlength += 2; 5734 5735 rdsize = newrdlength > sizeof(RDataBody) ? newrdlength : sizeof(RDataBody); 5736 newrd = mDNSPlatformMemAllocate(sizeof(RData) - sizeof(RDataBody) + rdsize); 5737 if (!newrd) { LogMsg("UpdateKeepaliveRData: ptr NULL"); return mStatus_NoMemoryErr; } 5738 5739 newrd->MaxRDLength = (mDNSu16) rdsize; 5740 mDNSPlatformMemCopy(&newrd->u, txt.c, newrdlength); 5741 5742 // If we are updating the record for the first time, rdata points to rdatastorage as the rdata memory 5743 // was allocated as part of the AuthRecord itself. We allocate memory when we update the AuthRecord. 5744 // If the resource record has data that we allocated in a previous pass (to update MAC address), 5745 // free that memory here before copying in the new data. 5746 if ( rr->resrec.rdata != &rr->rdatastorage) 5747 { 5748 mDNSPlatformMemFree(rr->resrec.rdata); 5749 LogSPS("UpdateKeepaliveRData: Freed allocated memory for keep alive packet: %s ", ARDisplayString(m, rr)); 5750 } 5751 SetNewRData(&rr->resrec, newrd, newrdlength); // Update our rdata 5752 5753 LogSPS("UpdateKeepaliveRData: successfully updated the record %s", ARDisplayString(m, rr)); 5754 return mStatus_NoError; 5755 } 5756 5757 mDNSlocal void SendSPSRegistrationForOwner(mDNS *const m, NetworkInterfaceInfo *const intf, const mDNSOpaque16 id, const OwnerOptData *const owner) 5758 { 5759 const int optspace = DNSOpt_Header_Space + DNSOpt_LeaseData_Space + DNSOpt_Owner_Space(&m->PrimaryMAC, &intf->MAC); 5760 const int sps = intf->NextSPSAttempt / 3; 5761 AuthRecord *rr; 5762 mDNSOpaque16 msgid; 5763 mDNSu32 scopeid; 5764 5765 scopeid = mDNSPlatformInterfaceIndexfromInterfaceID(m, intf->InterfaceID, mDNStrue); 5766 if (!intf->SPSAddr[sps].type) 5767 { 5768 intf->NextSPSAttemptTime = m->timenow + mDNSPlatformOneSecond; 5769 if (m->NextScheduledSPRetry - intf->NextSPSAttemptTime > 0) 5770 m->NextScheduledSPRetry = intf->NextSPSAttemptTime; 5771 LogSPS("SendSPSRegistration: %s SPS %d (%d) %##s not yet resolved", intf->ifname, intf->NextSPSAttempt, sps, intf->NetWakeResolve[sps].qname.c); 5772 goto exit; 5773 } 5774 5775 // Mark our mDNS records (not unicast records) for transfer to SPS 5776 if (mDNSOpaque16IsZero(id)) 5777 { 5778 // We may have to register this record over multiple interfaces and we don't want to 5779 // overwrite the id. We send the registration over interface X with id "IDX" and before 5780 // we get a response, we overwrite with id "IDY" for interface Y and we won't accept responses 5781 // for "IDX". Hence, we want to use the same ID across all interfaces. 5782 // 5783 // In the case of sleep proxy server transfering its records when it goes to sleep, the owner 5784 // option check below will set the same ID across the records from the same owner. Records 5785 // with different owner option gets different ID. 5786 msgid = mDNS_NewMessageID(m); 5787 for (rr = m->ResourceRecords; rr; rr=rr->next) 5788 { 5789 if (!(rr->AuthFlags & AuthFlagsWakeOnly) && rr->resrec.RecordType > kDNSRecordTypeDeregistering) 5790 { 5791 if (rr->resrec.InterfaceID == intf->InterfaceID || (!rr->resrec.InterfaceID && (rr->ForceMCast || IsLocalDomain(rr->resrec.name)))) 5792 { 5793 if (mDNSPlatformMemSame(owner, &rr->WakeUp, sizeof(*owner))) 5794 { 5795 rr->SendRNow = mDNSInterfaceMark; // mark it now 5796 // When we are registering on the first interface, rr->updateid is zero in which case 5797 // initialize with the new ID. For subsequent interfaces, we want to use the same ID. 5798 // At the end, all the updates sent across all the interfaces with the same ID. 5799 if (mDNSOpaque16IsZero(rr->updateid)) 5800 rr->updateid = msgid; 5801 else 5802 msgid = rr->updateid; 5803 } 5804 } 5805 } 5806 } 5807 } 5808 else 5809 msgid = id; 5810 5811 while (1) 5812 { 5813 mDNSu8 *p = m->omsg.data; 5814 // To comply with RFC 2782, PutResourceRecord suppresses name compression for SRV records in unicast updates. 5815 // For now we follow that same logic for SPS registrations too. 5816 // If we decide to compress SRV records in SPS registrations in the future, we can achieve that by creating our 5817 // initial DNSMessage with h.flags set to zero, and then update it to UpdateReqFlags right before sending the packet. 5818 InitializeDNSMessage(&m->omsg.h, msgid, UpdateReqFlags); 5819 5820 for (rr = m->ResourceRecords; rr; rr=rr->next) 5821 if (rr->SendRNow || mDNSUpdateOkToSend(m, rr, intf, scopeid)) 5822 { 5823 if (mDNSPlatformMemSame(owner, &rr->WakeUp, sizeof(*owner))) 5824 { 5825 mDNSu8 *newptr; 5826 const mDNSu8 *const limit = m->omsg.data + (m->omsg.h.mDNS_numUpdates ? NormalMaxDNSMessageData : AbsoluteMaxDNSMessageData) - optspace; 5827 5828 // If we can't update the keepalive record, don't send it 5829 if (mDNS_KeepaliveRecord(&rr->resrec) && (UpdateKeepaliveRData(m, rr, intf, mDNSfalse, mDNSNULL) != mStatus_NoError)) 5830 { 5831 if (scopeid < (sizeof(rr->updateIntID) * mDNSNBBY)) 5832 { 5833 bit_clr_opaque64(rr->updateIntID, scopeid); 5834 } 5835 rr->SendRNow = mDNSNULL; 5836 continue; 5837 } 5838 5839 if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask) 5840 rr->resrec.rrclass |= kDNSClass_UniqueRRSet; // Temporarily set the 'unique' bit so PutResourceRecord will set it 5841 newptr = PutResourceRecordTTLWithLimit(&m->omsg, p, &m->omsg.h.mDNS_numUpdates, &rr->resrec, rr->resrec.rroriginalttl, limit); 5842 rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet; // Make sure to clear 'unique' bit back to normal state 5843 if (!newptr) 5844 LogSPS("SendSPSRegistration put %s FAILED %d/%d %s", intf->ifname, p - m->omsg.data, limit - m->omsg.data, ARDisplayString(m, rr)); 5845 else 5846 { 5847 LogSPS("SendSPSRegistration put %s 0x%x 0x%x (updateid %d) %s", intf->ifname, rr->updateIntID.l[1], rr->updateIntID.l[0], mDNSVal16(m->omsg.h.id), ARDisplayString(m, rr)); 5848 rr->SendRNow = mDNSNULL; 5849 rr->ThisAPInterval = mDNSPlatformOneSecond; 5850 rr->LastAPTime = m->timenow; 5851 // should be initialized above 5852 if (mDNSOpaque16IsZero(rr->updateid)) LogMsg("SendSPSRegistration: ERROR!! rr %s updateid is zero", ARDisplayString(m, rr)); 5853 if (m->NextScheduledResponse - (rr->LastAPTime + rr->ThisAPInterval) >= 0) 5854 m->NextScheduledResponse = (rr->LastAPTime + rr->ThisAPInterval); 5855 p = newptr; 5856 } 5857 } 5858 } 5859 5860 if (!m->omsg.h.mDNS_numUpdates) break; 5861 else 5862 { 5863 AuthRecord opt; 5864 mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL); 5865 opt.resrec.rrclass = NormalMaxDNSMessageData; 5866 opt.resrec.rdlength = sizeof(rdataOPT) * 2; // Two options in this OPT record 5867 opt.resrec.rdestimate = sizeof(rdataOPT) * 2; 5868 opt.resrec.rdata->u.opt[0].opt = kDNSOpt_Lease; 5869 opt.resrec.rdata->u.opt[0].optlen = DNSOpt_LeaseData_Space - 4; 5870 opt.resrec.rdata->u.opt[0].u.updatelease = DEFAULT_UPDATE_LEASE; 5871 if (!owner->HMAC.l[0]) // If no owner data, 5872 SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[1]); // use our own interface information 5873 else // otherwise, use the owner data we were given 5874 { 5875 opt.resrec.rdata->u.opt[1].u.owner = *owner; 5876 opt.resrec.rdata->u.opt[1].opt = kDNSOpt_Owner; 5877 opt.resrec.rdata->u.opt[1].optlen = DNSOpt_Owner_Space(&owner->HMAC, &owner->IMAC) - 4; 5878 } 5879 LogSPS("SendSPSRegistration put %s %s", intf->ifname, ARDisplayString(m, &opt)); 5880 p = PutResourceRecordTTLWithLimit(&m->omsg, p, &m->omsg.h.numAdditionals, &opt.resrec, opt.resrec.rroriginalttl, m->omsg.data + AbsoluteMaxDNSMessageData); 5881 if (!p) 5882 LogMsg("SendSPSRegistration: Failed to put OPT record (%d updates) %s", m->omsg.h.mDNS_numUpdates, ARDisplayString(m, &opt)); 5883 else 5884 { 5885 mStatus err; 5886 5887 LogSPS("SendSPSRegistration: Sending Update %s %d (%d) id %5d with %d records %d bytes to %#a:%d", intf->ifname, intf->NextSPSAttempt, sps, 5888 mDNSVal16(m->omsg.h.id), m->omsg.h.mDNS_numUpdates, p - m->omsg.data, &intf->SPSAddr[sps], mDNSVal16(intf->SPSPort[sps])); 5889 // if (intf->NextSPSAttempt < 5) m->omsg.h.flags = zeroID; // For simulating packet loss 5890 err = mDNSSendDNSMessage(m, &m->omsg, p, intf->InterfaceID, mDNSNULL, &intf->SPSAddr[sps], intf->SPSPort[sps], mDNSNULL, mDNSNULL, mDNSfalse); 5891 if (err) LogSPS("SendSPSRegistration: mDNSSendDNSMessage err %d", err); 5892 if (err && intf->SPSAddr[sps].type == mDNSAddrType_IPv4 && intf->NetWakeResolve[sps].ThisQInterval == -1) 5893 { 5894 LogSPS("SendSPSRegistration %d %##s failed to send to IPv4 address; will try IPv6 instead", sps, intf->NetWakeResolve[sps].qname.c); 5895 intf->NetWakeResolve[sps].qtype = kDNSType_AAAA; 5896 mDNS_StartQuery_internal(m, &intf->NetWakeResolve[sps]); 5897 return; 5898 } 5899 } 5900 } 5901 } 5902 5903 intf->NextSPSAttemptTime = m->timenow + mDNSPlatformOneSecond * 10; // If successful, update NextSPSAttemptTime 5904 5905 exit: 5906 if (mDNSOpaque16IsZero(id) && intf->NextSPSAttempt < 8) intf->NextSPSAttempt++; 5907 } 5908 5909 mDNSlocal mDNSBool RecordIsFirstOccurrenceOfOwner(mDNS *const m, const AuthRecord *const rr) 5910 { 5911 AuthRecord *ar; 5912 for (ar = m->ResourceRecords; ar && ar != rr; ar=ar->next) 5913 if (mDNSPlatformMemSame(&rr->WakeUp, &ar->WakeUp, sizeof(rr->WakeUp))) return mDNSfalse; 5914 return mDNStrue; 5915 } 5916 5917 mDNSlocal void mDNSCoreStoreProxyRR(mDNS *const m, const mDNSInterfaceID InterfaceID, AuthRecord *const rr) 5918 { 5919 AuthRecord *newRR = mDNSPlatformMemAllocate(sizeof(AuthRecord)); 5920 5921 if (newRR == mDNSNULL) 5922 { 5923 LogSPS("%s : could not allocate memory for new resource record", __func__); 5924 return; 5925 } 5926 5927 mDNSPlatformMemZero(newRR, sizeof(AuthRecord)); 5928 mDNS_SetupResourceRecord(newRR, mDNSNULL, InterfaceID, rr->resrec.rrtype, 5929 rr->resrec.rroriginalttl, rr->resrec.RecordType, 5930 rr->ARType, mDNSNULL, mDNSNULL); 5931 5932 AssignDomainName(&newRR->namestorage, &rr->namestorage); 5933 newRR->resrec.rdlength = DomainNameLength(rr->resrec.name); 5934 newRR->resrec.namehash = DomainNameHashValue(newRR->resrec.name); 5935 newRR->resrec.rrclass = rr->resrec.rrclass; 5936 5937 if (rr->resrec.rrtype == kDNSType_A) 5938 { 5939 newRR->resrec.rdata->u.ipv4 = rr->resrec.rdata->u.ipv4; 5940 } 5941 else if (rr->resrec.rrtype == kDNSType_AAAA) 5942 { 5943 newRR->resrec.rdata->u.ipv6 = rr->resrec.rdata->u.ipv6; 5944 } 5945 SetNewRData(&newRR->resrec, mDNSNULL, 0); 5946 5947 // Insert the new node at the head of the list. 5948 newRR->next = m->SPSRRSet; 5949 m->SPSRRSet = newRR; 5950 LogSPS("%s : Storing proxy record : %s ", __func__, ARDisplayString(m, rr)); 5951 } 5952 5953 // Some records are interface specific and some are not. The ones that are supposed to be registered 5954 // on multiple interfaces need to be initialized with all the valid interfaces on which it will be sent. 5955 // updateIntID bit field tells us on which interfaces we need to register this record. When we get an 5956 // ack from the sleep proxy server, we clear the interface bit. This way, we know when a record completes 5957 // registration on all the interfaces 5958 mDNSlocal void SPSInitRecordsBeforeUpdate(mDNS *const m, mDNSOpaque64 updateIntID, mDNSBool *WakeOnlyService) 5959 { 5960 AuthRecord *ar; 5961 LogSPS("SPSInitRecordsBeforeUpdate: UpdateIntID 0x%x 0x%x", updateIntID.l[1], updateIntID.l[0]); 5962 5963 *WakeOnlyService = mDNSfalse; 5964 5965 // Before we store the A and AAAA records that we are going to register with the sleep proxy, 5966 // make sure that the old sleep proxy records are removed. 5967 mDNSCoreFreeProxyRR(m); 5968 5969 // For records that are registered only on a specific interface, mark only that bit as it will 5970 // never be registered on any other interface. For others, it should be sent on all interfaces. 5971 for (ar = m->ResourceRecords; ar; ar=ar->next) 5972 { 5973 ar->updateIntID = zeroOpaque64; 5974 ar->updateid = zeroID; 5975 if (AuthRecord_uDNS(ar)) 5976 { 5977 continue; 5978 } 5979 if (ar->AuthFlags & AuthFlagsWakeOnly) 5980 { 5981 if (ar->resrec.RecordType == kDNSRecordTypeShared && ar->RequireGoodbye) 5982 { 5983 ar->ImmedAnswer = mDNSInterfaceMark; 5984 *WakeOnlyService = mDNStrue; 5985 continue; 5986 } 5987 } 5988 if (!ar->resrec.InterfaceID) 5989 { 5990 LogSPS("Setting scopeid (ALL) 0x%x 0x%x for %s", updateIntID.l[1], updateIntID.l[0], ARDisplayString(m, ar)); 5991 ar->updateIntID = updateIntID; 5992 } 5993 else 5994 { 5995 // Filter records that belong to interfaces that we won't register the records on. UpdateIntID captures 5996 // exactly this. 5997 mDNSu32 scopeid = mDNSPlatformInterfaceIndexfromInterfaceID(m, ar->resrec.InterfaceID, mDNStrue); 5998 if ((scopeid < (sizeof(updateIntID) * mDNSNBBY)) && bit_get_opaque64(updateIntID, scopeid)) 5999 { 6000 bit_set_opaque64(ar->updateIntID, scopeid); 6001 LogSPS("SPSInitRecordsBeforeUpdate: Setting scopeid(%d) 0x%x 0x%x for %s", scopeid, ar->updateIntID.l[1], 6002 ar->updateIntID.l[0], ARDisplayString(m, ar)); 6003 } 6004 else 6005 { 6006 LogSPS("SPSInitRecordsBeforeUpdate: scopeid %d beyond range or not valid for SPS registration", scopeid); 6007 } 6008 } 6009 // Store the A and AAAA records that we registered with the sleep proxy. 6010 // We will use this to prevent spurious name conflicts that may occur when we wake up 6011 if (ar->resrec.rrtype == kDNSType_A || ar->resrec.rrtype == kDNSType_AAAA) 6012 { 6013 mDNSCoreStoreProxyRR(m, ar->resrec.InterfaceID, ar); 6014 } 6015 } 6016 } 6017 6018 mDNSlocal void SendSPSRegistration(mDNS *const m, NetworkInterfaceInfo *const intf, const mDNSOpaque16 id) 6019 { 6020 AuthRecord *ar; 6021 OwnerOptData owner = zeroOwner; 6022 6023 SendSPSRegistrationForOwner(m, intf, id, &owner); 6024 6025 for (ar = m->ResourceRecords; ar; ar=ar->next) 6026 { 6027 if (!mDNSPlatformMemSame(&owner, &ar->WakeUp, sizeof(owner)) && RecordIsFirstOccurrenceOfOwner(m, ar)) 6028 { 6029 owner = ar->WakeUp; 6030 SendSPSRegistrationForOwner(m, intf, id, &owner); 6031 } 6032 } 6033 } 6034 6035 // RetrySPSRegistrations is called from SendResponses, with the lock held 6036 mDNSlocal void RetrySPSRegistrations(mDNS *const m) 6037 { 6038 AuthRecord *rr; 6039 NetworkInterfaceInfo *intf; 6040 6041 // First make sure none of our interfaces' NextSPSAttemptTimes are inadvertently set to m->timenow + mDNSPlatformOneSecond * 10 6042 for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next)) 6043 if (intf->NextSPSAttempt && intf->NextSPSAttemptTime == m->timenow + mDNSPlatformOneSecond * 10) 6044 intf->NextSPSAttemptTime++; 6045 6046 // Retry any record registrations that are due 6047 for (rr = m->ResourceRecords; rr; rr=rr->next) 6048 if (!AuthRecord_uDNS(rr) && !mDNSOpaque16IsZero(rr->updateid) && m->timenow - (rr->LastAPTime + rr->ThisAPInterval) >= 0) 6049 { 6050 for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next)) 6051 { 6052 // If we still have registrations pending on this interface, send it now 6053 mDNSu32 scopeid = mDNSPlatformInterfaceIndexfromInterfaceID(m, intf->InterfaceID, mDNStrue); 6054 if ((scopeid >= (sizeof(rr->updateIntID) * mDNSNBBY) || bit_get_opaque64(rr->updateIntID, scopeid)) && 6055 (!rr->resrec.InterfaceID || rr->resrec.InterfaceID == intf->InterfaceID)) 6056 { 6057 LogSPS("RetrySPSRegistrations: 0x%x 0x%x (updateid %d) %s", rr->updateIntID.l[1], rr->updateIntID.l[0], mDNSVal16(rr->updateid), ARDisplayString(m, rr)); 6058 SendSPSRegistration(m, intf, rr->updateid); 6059 } 6060 } 6061 } 6062 6063 // For interfaces where we did an SPS registration attempt, increment intf->NextSPSAttempt 6064 for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next)) 6065 if (intf->NextSPSAttempt && intf->NextSPSAttemptTime == m->timenow + mDNSPlatformOneSecond * 10 && intf->NextSPSAttempt < 8) 6066 intf->NextSPSAttempt++; 6067 } 6068 6069 mDNSlocal void NetWakeResolve(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) 6070 { 6071 NetworkInterfaceInfo *intf = (NetworkInterfaceInfo *)question->QuestionContext; 6072 int sps = (int)(question - intf->NetWakeResolve); 6073 (void)m; // Unused 6074 LogSPS("NetWakeResolve: SPS: %d Add: %d %s", sps, AddRecord, RRDisplayString(m, answer)); 6075 6076 if (!AddRecord) return; // Don't care about REMOVE events 6077 if (answer->rrtype != question->qtype) return; // Don't care about CNAMEs 6078 6079 // if (answer->rrtype == kDNSType_AAAA && sps == 0) return; // To test failing to resolve sleep proxy's address 6080 6081 if (answer->rrtype == kDNSType_SRV) 6082 { 6083 // 1. Got the SRV record; now look up the target host's IP address 6084 mDNS_StopQuery(m, question); 6085 intf->SPSPort[sps] = answer->rdata->u.srv.port; 6086 AssignDomainName(&question->qname, &answer->rdata->u.srv.target); 6087 question->qtype = kDNSType_A; 6088 mDNS_StartQuery(m, question); 6089 } 6090 else if (answer->rrtype == kDNSType_A && answer->rdlength == sizeof(mDNSv4Addr)) 6091 { 6092 // 2. Got an IPv4 address for the target host; record address and initiate an SPS registration if appropriate 6093 mDNS_StopQuery(m, question); 6094 question->ThisQInterval = -1; 6095 intf->SPSAddr[sps].type = mDNSAddrType_IPv4; 6096 intf->SPSAddr[sps].ip.v4 = answer->rdata->u.ipv4; 6097 mDNS_Lock(m); 6098 if (sps == intf->NextSPSAttempt/3) SendSPSRegistration(m, intf, zeroID); // If we're ready for this result, use it now 6099 mDNS_Unlock(m); 6100 } 6101 else if (answer->rrtype == kDNSType_A && answer->rdlength == 0) 6102 { 6103 // 3. Got negative response -- target host apparently has IPv6 disabled -- so try looking up the target host's IPv4 address(es) instead 6104 mDNS_StopQuery(m, question); 6105 LogSPS("NetWakeResolve: SPS %d %##s has no IPv4 address, will try IPv6 instead", sps, question->qname.c); 6106 question->qtype = kDNSType_AAAA; 6107 mDNS_StartQuery(m, question); 6108 } 6109 else if (answer->rrtype == kDNSType_AAAA && answer->rdlength == sizeof(mDNSv6Addr) && mDNSv6AddressIsLinkLocal(&answer->rdata->u.ipv6)) 6110 { 6111 // 4. Got the target host's IPv6 link-local address; record address and initiate an SPS registration if appropriate 6112 mDNS_StopQuery(m, question); 6113 question->ThisQInterval = -1; 6114 intf->SPSAddr[sps].type = mDNSAddrType_IPv6; 6115 intf->SPSAddr[sps].ip.v6 = answer->rdata->u.ipv6; 6116 mDNS_Lock(m); 6117 if (sps == intf->NextSPSAttempt/3) SendSPSRegistration(m, intf, zeroID); // If we're ready for this result, use it now 6118 mDNS_Unlock(m); 6119 } 6120 } 6121 6122 mDNSexport mDNSBool mDNSCoreHaveAdvertisedMulticastServices(mDNS *const m) 6123 { 6124 AuthRecord *rr; 6125 for (rr = m->ResourceRecords; rr; rr=rr->next) 6126 if (mDNS_KeepaliveRecord(&rr->resrec) || (rr->resrec.rrtype == kDNSType_SRV && !AuthRecord_uDNS(rr) && !mDNSSameIPPort(rr->resrec.rdata->u.srv.port, DiscardPort))) 6127 return mDNStrue; 6128 return mDNSfalse; 6129 } 6130 6131 #ifdef APPLE_OSX_mDNSResponder 6132 // This function is used only in the case of local NIC proxy. For external 6133 // sleep proxy server, we do this in SPSInitRecordsBeforeUpdate when we 6134 // walk the resource records. 6135 mDNSlocal void SendGoodbyesForWakeOnlyService(mDNS *const m, mDNSBool *WakeOnlyService) 6136 { 6137 AuthRecord *rr; 6138 6139 *WakeOnlyService = mDNSfalse; 6140 6141 // Mark all the records we need to deregister and send them 6142 for (rr = m->ResourceRecords; rr; rr=rr->next) 6143 { 6144 if ((rr->AuthFlags & AuthFlagsWakeOnly) && 6145 rr->resrec.RecordType == kDNSRecordTypeShared && rr->RequireGoodbye) 6146 { 6147 rr->ImmedAnswer = mDNSInterfaceMark; 6148 *WakeOnlyService = mDNStrue; 6149 } 6150 } 6151 } 6152 #endif // APPLE_OSx_mDNSResponder 6153 6154 mDNSlocal void SendSleepGoodbyes(mDNS *const m, mDNSBool AllInterfaces, mDNSBool unicast) 6155 { 6156 AuthRecord *rr; 6157 m->SleepState = SleepState_Sleeping; 6158 6159 // If AllInterfaces is not set, the caller has already marked it appropriately 6160 // on which interfaces this should be sent. 6161 if (AllInterfaces) 6162 { 6163 NetworkInterfaceInfo *intf; 6164 for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next)) 6165 { 6166 intf->SendGoodbyes = 1; 6167 } 6168 } 6169 if (unicast) 6170 { 6171 #ifndef UNICAST_DISABLED 6172 SleepRecordRegistrations(m); // If we have no SPS, need to deregister our uDNS records 6173 #endif /* UNICAST_DISABLED */ 6174 } 6175 6176 // Mark all the records we need to deregister and send them 6177 for (rr = m->ResourceRecords; rr; rr=rr->next) 6178 if (rr->resrec.RecordType == kDNSRecordTypeShared && rr->RequireGoodbye) 6179 rr->ImmedAnswer = mDNSInterfaceMark; 6180 SendResponses(m); 6181 } 6182 6183 /* 6184 * This function attempts to detect if multiple interfaces are on the same subnet. 6185 * It makes this determination based only on the IPv4 Addresses and subnet masks. 6186 * IPv6 link local addresses that are configured by default on all interfaces make 6187 * it hard to make this determination 6188 * 6189 * The 'real' fix for this would be to send out multicast packets over one interface 6190 * and conclude that multiple interfaces are on the same subnet only if these packets 6191 * are seen on other interfaces on the same system 6192 */ 6193 mDNSlocal mDNSBool skipSameSubnetRegistration(mDNS *const m, mDNSInterfaceID *regID, mDNSu32 count, mDNSInterfaceID intfid) 6194 { 6195 NetworkInterfaceInfo *intf; 6196 NetworkInterfaceInfo *newIntf; 6197 mDNSu32 i; 6198 6199 for (newIntf = FirstInterfaceForID(m, intfid); newIntf; newIntf = newIntf->next) 6200 { 6201 if ((newIntf->InterfaceID != intfid) || 6202 (newIntf->ip.type != mDNSAddrType_IPv4)) 6203 { 6204 continue; 6205 } 6206 for ( i = 0; i < count; i++) 6207 { 6208 for (intf = FirstInterfaceForID(m, regID[i]); intf; intf = intf->next) 6209 { 6210 if ((intf->InterfaceID != regID[i]) || 6211 (intf->ip.type != mDNSAddrType_IPv4)) 6212 { 6213 continue; 6214 } 6215 if ((intf->ip.ip.v4.NotAnInteger & intf->mask.ip.v4.NotAnInteger) == (newIntf->ip.ip.v4.NotAnInteger & newIntf->mask.ip.v4.NotAnInteger)) 6216 { 6217 LogSPS("%s : Already registered for the same subnet (IPv4) for interface %s", __func__, intf->ifname); 6218 return (mDNStrue); 6219 } 6220 } 6221 } 6222 } 6223 return (mDNSfalse); 6224 } 6225 6226 mDNSlocal void DoKeepaliveCallbacks(mDNS *m) 6227 { 6228 // Loop through the keepalive records and callback with an error 6229 m->CurrentRecord = m->ResourceRecords; 6230 while (m->CurrentRecord) 6231 { 6232 AuthRecord *const rr = m->CurrentRecord; 6233 if ((mDNS_KeepaliveRecord(&rr->resrec)) && (rr->resrec.RecordType != kDNSRecordTypeDeregistering)) 6234 { 6235 LogSPS("DoKeepaliveCallbacks: Invoking the callback for %s", ARDisplayString(m, rr)); 6236 if (rr->RecordCallback) 6237 rr->RecordCallback(m, rr, mStatus_BadStateErr); 6238 } 6239 if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now 6240 m->CurrentRecord = rr->next; 6241 } 6242 } 6243 6244 // BeginSleepProcessing is called, with the lock held, from either mDNS_Execute or mDNSCoreMachineSleep 6245 mDNSlocal void BeginSleepProcessing(mDNS *const m) 6246 { 6247 mDNSBool SendGoodbyes = mDNStrue; 6248 mDNSBool WakeOnlyService = mDNSfalse; 6249 mDNSBool invokeKACallback = mDNStrue; 6250 const CacheRecord *sps[3] = { mDNSNULL }; 6251 mDNSOpaque64 updateIntID = zeroOpaque64; 6252 mDNSInterfaceID registeredIntfIDS[128]; 6253 mDNSu32 registeredCount = 0; 6254 int skippedRegistrations = 0; 6255 6256 m->NextScheduledSPRetry = m->timenow; 6257 6258 if (!m->SystemWakeOnLANEnabled) LogSPS("BeginSleepProcessing: m->SystemWakeOnLANEnabled is false"); 6259 else if (!mDNSCoreHaveAdvertisedMulticastServices(m)) LogSPS("BeginSleepProcessing: No advertised services"); 6260 else // If we have at least one advertised service 6261 { 6262 NetworkInterfaceInfo *intf; 6263 6264 // Clear out the SCDynamic entry that stores the external SPS information 6265 mDNSPlatformClearSPSMACAddr(); 6266 6267 for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next)) 6268 { 6269 // Intialize it to false. These values make sense only when SleepState is set to Sleeping. 6270 intf->SendGoodbyes = 0; 6271 6272 // If it is not multicast capable, we could not have possibly discovered sleep proxy 6273 // servers. 6274 if (!intf->McastTxRx || mDNSPlatformInterfaceIsD2D(intf->InterfaceID)) 6275 { 6276 LogSPS("BeginSleepProcessing: %-6s Ignoring for registrations", intf->ifname); 6277 continue; 6278 } 6279 6280 // If we are not capable of WOMP, then don't register with sleep proxy. 6281 // 6282 // Note: If we are not NetWake capable, we don't browse for the sleep proxy server. 6283 // We might find sleep proxy servers in the cache and start a resolve on them. 6284 // But then if the interface goes away, we won't stop these questions because 6285 // mDNS_DeactivateNetWake_internal assumes that a browse has been started for it 6286 // to stop both the browse and resolve questions. 6287 if (!intf->NetWake) 6288 { 6289 LogSPS("BeginSleepProcessing: %-6s not capable of magic packet wakeup", intf->ifname); 6290 intf->SendGoodbyes = 1; 6291 skippedRegistrations++; 6292 continue; 6293 } 6294 6295 // Check if we have already registered with a sleep proxy for this subnet 6296 if (skipSameSubnetRegistration(m, registeredIntfIDS, registeredCount, intf->InterfaceID)) 6297 { 6298 LogSPS("%s : Skipping sleep proxy registration on %s", __func__, intf->ifname); 6299 continue; 6300 } 6301 6302 #if APPLE_OSX_mDNSResponder 6303 else if (SupportsInNICProxy(intf)) 6304 { 6305 if (ActivateLocalProxy(m, intf) == mStatus_NoError) 6306 { 6307 SendGoodbyesForWakeOnlyService(m, &WakeOnlyService); 6308 SendGoodbyes = mDNSfalse; 6309 invokeKACallback = mDNSfalse; 6310 LogSPS("BeginSleepProcessing: %-6s using local proxy", intf->ifname); 6311 // This will leave m->SleepState set to SleepState_Transferring, 6312 // which is okay because with no outstanding resolves, or updates in flight, 6313 // mDNSCoreReadyForSleep() will conclude correctly that all the updates have already completed 6314 6315 registeredIntfIDS[registeredCount] = intf->InterfaceID; 6316 registeredCount++; 6317 } 6318 } 6319 #endif // APPLE_OSX_mDNSResponder 6320 else 6321 { 6322 #if APPLE_OSX_mDNSResponder 6323 // If on battery, do not attempt to offload to external sleep proxies 6324 if (m->SystemWakeOnLANEnabled == mDNS_WakeOnBattery) 6325 { 6326 LogSPS("BegingSleepProcessing: Not connected to AC power - Not registering with an external sleep proxy."); 6327 return; 6328 } 6329 #endif // APPLE_OSX_mDNSResponder 6330 FindSPSInCache(m, &intf->NetWakeBrowse, sps); 6331 if (!sps[0]) LogSPS("BeginSleepProcessing: %-6s %#a No Sleep Proxy Server found (Next Browse Q in %d, interval %d)", 6332 intf->ifname, &intf->ip, NextQSendTime(&intf->NetWakeBrowse) - m->timenow, intf->NetWakeBrowse.ThisQInterval); 6333 else 6334 { 6335 int i; 6336 mDNSu32 scopeid; 6337 SendGoodbyes = mDNSfalse; 6338 intf->NextSPSAttempt = 0; 6339 intf->NextSPSAttemptTime = m->timenow + mDNSPlatformOneSecond; 6340 6341 scopeid = mDNSPlatformInterfaceIndexfromInterfaceID(m, intf->InterfaceID, mDNStrue); 6342 // Now we know for sure that we have to wait for registration to complete on this interface. 6343 if (scopeid < (sizeof(updateIntID) * mDNSNBBY)) 6344 bit_set_opaque64(updateIntID, scopeid); 6345 6346 // Don't need to set m->NextScheduledSPRetry here because we already set "m->NextScheduledSPRetry = m->timenow" above 6347 for (i=0; i<3; i++) 6348 { 6349 #if ForceAlerts 6350 if (intf->SPSAddr[i].type) 6351 { LogMsg("BeginSleepProcessing: %s %d intf->SPSAddr[i].type %d", intf->ifname, i, intf->SPSAddr[i].type); *(long*)0 = 0; } 6352 if (intf->NetWakeResolve[i].ThisQInterval >= 0) 6353 { LogMsg("BeginSleepProcessing: %s %d intf->NetWakeResolve[i].ThisQInterval %d", intf->ifname, i, intf->NetWakeResolve[i].ThisQInterval); *(long*)0 = 0; } 6354 #endif 6355 intf->SPSAddr[i].type = mDNSAddrType_None; 6356 if (intf->NetWakeResolve[i].ThisQInterval >= 0) mDNS_StopQuery(m, &intf->NetWakeResolve[i]); 6357 intf->NetWakeResolve[i].ThisQInterval = -1; 6358 if (sps[i]) 6359 { 6360 LogSPS("BeginSleepProcessing: %-6s Found Sleep Proxy Server %d TTL %d %s", intf->ifname, i, sps[i]->resrec.rroriginalttl, CRDisplayString(m, sps[i])); 6361 mDNS_SetupQuestion(&intf->NetWakeResolve[i], intf->InterfaceID, &sps[i]->resrec.rdata->u.name, kDNSType_SRV, NetWakeResolve, intf); 6362 intf->NetWakeResolve[i].ReturnIntermed = mDNStrue; 6363 mDNS_StartQuery_internal(m, &intf->NetWakeResolve[i]); 6364 6365 // If we are registering with a Sleep Proxy for a new subnet, add it to our list 6366 registeredIntfIDS[registeredCount] = intf->InterfaceID; 6367 registeredCount++; 6368 } 6369 } 6370 } 6371 } 6372 } 6373 } 6374 6375 // If we have at least one interface on which we are registering with an external sleep proxy, 6376 // initialize all the records appropriately. 6377 if (!mDNSOpaque64IsZero(&updateIntID)) 6378 SPSInitRecordsBeforeUpdate(m, updateIntID, &WakeOnlyService); 6379 6380 // Call the applicaitons that registered a keepalive record to inform them that we failed to offload 6381 // the records to a sleep proxy. 6382 if (invokeKACallback) 6383 { 6384 LogSPS("BeginSleepProcessing: Did not register with an in-NIC proxy - invoking the callbacks for KA records"); 6385 DoKeepaliveCallbacks(m); 6386 } 6387 6388 // SendSleepGoodbyes last two arguments control whether we send goodbyes on all 6389 // interfaces and also deregister unicast registrations. 6390 // 6391 // - If there are no sleep proxy servers, then send goodbyes on all interfaces 6392 // for both multicast and unicast. 6393 // 6394 // - If we skipped registrations on some interfaces, then we have already marked 6395 // them appropriately above. We don't need to send goodbyes for unicast as 6396 // we have registered with at least one sleep proxy. 6397 // 6398 // - If we are not planning to send any goodbyes, then check for WakeOnlyServices. 6399 // 6400 // Note: If we are planning to send goodbyes, we mark the record with mDNSInterfaceAny 6401 // and call SendResponses which inturn calls ShouldSendGoodbyesBeforeSleep which looks 6402 // at WakeOnlyServices first. 6403 if (SendGoodbyes) 6404 { 6405 LogSPS("BeginSleepProcessing: Not registering with Sleep Proxy Server"); 6406 SendSleepGoodbyes(m, mDNStrue, mDNStrue); 6407 } 6408 else if (skippedRegistrations) 6409 { 6410 LogSPS("BeginSleepProcessing: Not registering with Sleep Proxy Server on all interfaces"); 6411 SendSleepGoodbyes(m, mDNSfalse, mDNSfalse); 6412 } 6413 else if (WakeOnlyService) 6414 { 6415 // If we saw WakeOnly service above, send the goodbyes now. 6416 LogSPS("BeginSleepProcessing: Sending goodbyes for WakeOnlyServices"); 6417 SendResponses(m); 6418 } 6419 } 6420 6421 // Call mDNSCoreMachineSleep(m, mDNStrue) when the machine is about to go to sleep. 6422 // Call mDNSCoreMachineSleep(m, mDNSfalse) when the machine is has just woken up. 6423 // Normally, the platform support layer below mDNSCore should call this, not the client layer above. 6424 mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleep) 6425 { 6426 AuthRecord *rr; 6427 6428 LogSPS("%s (old state %d) at %ld", sleep ? "Sleeping" : "Waking", m->SleepState, m->timenow); 6429 6430 if (sleep && !m->SleepState) // Going to sleep 6431 { 6432 mDNS_Lock(m); 6433 // If we're going to sleep, need to stop advertising that we're a Sleep Proxy Server 6434 if (m->SPSSocket) 6435 { 6436 mDNSu8 oldstate = m->SPSState; 6437 mDNS_DropLockBeforeCallback(); // mDNS_DeregisterService expects to be called without the lock held, so we emulate that here 6438 m->SPSState = 2; 6439 #ifndef SPC_DISABLED 6440 if (oldstate == 1) mDNS_DeregisterService(m, &m->SPSRecords); 6441 #else 6442 (void)oldstate; 6443 #endif 6444 mDNS_ReclaimLockAfterCallback(); 6445 } 6446 6447 m->SleepState = SleepState_Transferring; 6448 if (m->SystemWakeOnLANEnabled && m->DelaySleep) 6449 { 6450 // If we just woke up moments ago, allow ten seconds for networking to stabilize before going back to sleep 6451 LogSPS("mDNSCoreMachineSleep: Re-sleeping immediately after waking; will delay for %d ticks", m->DelaySleep - m->timenow); 6452 m->SleepLimit = NonZeroTime(m->DelaySleep + mDNSPlatformOneSecond * 10); 6453 } 6454 else 6455 { 6456 m->DelaySleep = 0; 6457 m->SleepLimit = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 10); 6458 m->mDNSStats.Sleeps++; 6459 BeginSleepProcessing(m); 6460 } 6461 6462 #ifndef UNICAST_DISABLED 6463 SuspendLLQs(m); 6464 #endif 6465 #if APPLE_OSX_mDNSResponder 6466 RemoveAutoTunnel6Record(m); 6467 #endif 6468 LogSPS("mDNSCoreMachineSleep: m->SleepState %d (%s) seq %d", m->SleepState, 6469 m->SleepState == SleepState_Transferring ? "Transferring" : 6470 m->SleepState == SleepState_Sleeping ? "Sleeping" : "?", m->SleepSeqNum); 6471 mDNS_Unlock(m); 6472 } 6473 else if (!sleep) // Waking up 6474 { 6475 mDNSu32 slot; 6476 CacheGroup *cg; 6477 CacheRecord *cr; 6478 NetworkInterfaceInfo *intf; 6479 mDNSs32 currtime, diff; 6480 6481 mDNS_Lock(m); 6482 // Reset SleepLimit back to 0 now that we're awake again. 6483 m->SleepLimit = 0; 6484 6485 // If we were previously sleeping, but now we're not, increment m->SleepSeqNum to indicate that we're entering a new period of wakefulness 6486 if (m->SleepState != SleepState_Awake) 6487 { 6488 m->SleepState = SleepState_Awake; 6489 m->SleepSeqNum++; 6490 // If the machine wakes and then immediately tries to sleep again (e.g. a maintenance wake) 6491 // then we enforce a minimum delay of 16 seconds before we begin sleep processing. 6492 // This is to allow time for the Ethernet link to come up, DHCP to get an address, mDNS to issue queries, etc., 6493 // before we make our determination of whether there's a Sleep Proxy out there we should register with. 6494 m->DelaySleep = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 16); 6495 } 6496 6497 if (m->SPSState == 3) 6498 { 6499 m->SPSState = 0; 6500 mDNSCoreBeSleepProxyServer_internal(m, m->SPSType, m->SPSPortability, m->SPSMarginalPower, m->SPSTotalPower, m->SPSFeatureFlags); 6501 } 6502 m->mDNSStats.Wakes++; 6503 6504 // ... and the same for NextSPSAttempt 6505 for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next)) intf->NextSPSAttempt = -1; 6506 6507 // Restart unicast and multicast queries 6508 mDNSCoreRestartQueries(m); 6509 6510 // and reactivtate service registrations 6511 m->NextSRVUpdate = NonZeroTime(m->timenow + mDNSPlatformOneSecond); 6512 LogInfo("mDNSCoreMachineSleep waking: NextSRVUpdate in %d %d", m->NextSRVUpdate - m->timenow, m->timenow); 6513 6514 // 2. Re-validate our cache records 6515 currtime = mDNSPlatformUTC(); 6516 6517 #if APPLE_OSX_mDNSResponder 6518 // start time of this statistics gathering interval 6519 m->StatStartTime = currtime; 6520 #endif // APPLE_OSX_mDNSResponder 6521 6522 diff = currtime - m->TimeSlept; 6523 FORALL_CACHERECORDS(slot, cg, cr) 6524 { 6525 // Temporary fix: For unicast cache records, look at how much time we slept. 6526 // Adjust the RecvTime by the amount of time we slept so that we age the 6527 // cache record appropriately. If it is expired already, purge. If there 6528 // is a network change that happens after the wakeup, we might purge the 6529 // cache anyways and this helps only in the case where there are no network 6530 // changes across sleep/wakeup transition. 6531 // 6532 // Note: If there is a network/DNS server change that already happened and 6533 // these cache entries are already refreshed and we are getting a delayed 6534 // wake up notification, we might adjust the TimeRcvd based on the time slept 6535 // now which can cause the cache to purge pre-maturely. As this is not a very 6536 // common case, this should happen rarely. 6537 if (!cr->resrec.InterfaceID) 6538 { 6539 if (diff > 0) 6540 { 6541 mDNSu32 uTTL = RRUnadjustedTTL(cr->resrec.rroriginalttl); 6542 const mDNSs32 remain = uTTL - (m->timenow - cr->TimeRcvd) / mDNSPlatformOneSecond; 6543 6544 // -if we have slept longer than the remaining TTL, purge and start fresh. 6545 // -if we have been sleeping for a long time, we could reduce TimeRcvd below by 6546 // a sufficiently big value which could cause the value to go into the future 6547 // because of the signed comparison of time. For this to happen, we should have been 6548 // sleeping really long (~24 days). For now, we want to be conservative and flush even 6549 // if we have slept for more than two days. 6550 6551 if (diff >= remain || diff > (2 * 24 * 3600)) 6552 { 6553 LogInfo("mDNSCoreMachineSleep: %s: Purging cache entry SleptTime %d, Remaining TTL %d", 6554 CRDisplayString(m, cr), diff, remain); 6555 mDNS_PurgeCacheResourceRecord(m, cr); 6556 continue; 6557 } 6558 cr->TimeRcvd -= (diff * mDNSPlatformOneSecond); 6559 if (m->timenow - (cr->TimeRcvd + ((mDNSs32)uTTL * mDNSPlatformOneSecond)) >= 0) 6560 { 6561 LogInfo("mDNSCoreMachineSleep: %s: Purging after adjusting the remaining TTL %d by %d seconds", 6562 CRDisplayString(m, cr), remain, diff); 6563 mDNS_PurgeCacheResourceRecord(m, cr); 6564 } 6565 else 6566 { 6567 LogInfo("mDNSCoreMachineSleep: %s: Adjusted the remain ttl %u by %d seconds", CRDisplayString(m, cr), remain, diff); 6568 } 6569 } 6570 } 6571 else 6572 { 6573 mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForWake); 6574 } 6575 } 6576 6577 // 3. Retrigger probing and announcing for all our authoritative records 6578 for (rr = m->ResourceRecords; rr; rr=rr->next) 6579 { 6580 if (AuthRecord_uDNS(rr)) 6581 { 6582 ActivateUnicastRegistration(m, rr); 6583 } 6584 else 6585 { 6586 mDNSCoreRestartRegistration(m, rr, -1); 6587 } 6588 } 6589 6590 // 4. Refresh NAT mappings 6591 // We don't want to have to assume that all hardware can necessarily keep accurate 6592 // track of passage of time while asleep, so on wake we refresh our NAT mappings. 6593 // We typically wake up with no interfaces active, so there's no need to rush to try to find our external address. 6594 // But if we do get a network configuration change, mDNSMacOSXNetworkChanged will call uDNS_SetupDNSConfig, which 6595 // will call mDNS_SetPrimaryInterfaceInfo, which will call RecreateNATMappings to refresh them, potentially sooner 6596 // than five seconds from now. 6597 LogInfo("mDNSCoreMachineSleep: recreating NAT mappings in 5 seconds"); 6598 RecreateNATMappings(m, mDNSPlatformOneSecond * 5); 6599 mDNS_Unlock(m); 6600 } 6601 } 6602 6603 mDNSexport mDNSBool mDNSCoreReadyForSleep(mDNS *m, mDNSs32 now) 6604 { 6605 DNSQuestion *q; 6606 AuthRecord *rr; 6607 NetworkInterfaceInfo *intf; 6608 6609 mDNS_Lock(m); 6610 6611 if (m->DelaySleep) goto notready; 6612 6613 // If we've not hit the sleep limit time, and it's not time for our next retry, we can skip these checks 6614 if (m->SleepLimit - now > 0 && m->NextScheduledSPRetry - now > 0) goto notready; 6615 6616 m->NextScheduledSPRetry = now + 0x40000000UL; 6617 6618 // See if we might need to retransmit any lost Sleep Proxy Registrations 6619 for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next)) 6620 if (intf->NextSPSAttempt >= 0) 6621 { 6622 if (now - intf->NextSPSAttemptTime >= 0) 6623 { 6624 LogSPS("mDNSCoreReadyForSleep: retrying for %s SPS %d try %d", 6625 intf->ifname, intf->NextSPSAttempt/3, intf->NextSPSAttempt); 6626 SendSPSRegistration(m, intf, zeroID); 6627 // Don't need to "goto notready" here, because if we do still have record registrations 6628 // that have not been acknowledged yet, we'll catch that in the record list scan below. 6629 } 6630 else 6631 if (m->NextScheduledSPRetry - intf->NextSPSAttemptTime > 0) 6632 m->NextScheduledSPRetry = intf->NextSPSAttemptTime; 6633 } 6634 6635 // Scan list of interfaces, and see if we're still waiting for any sleep proxy resolves to complete 6636 for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next)) 6637 { 6638 int sps = (intf->NextSPSAttempt == 0) ? 0 : (intf->NextSPSAttempt-1)/3; 6639 if (intf->NetWakeResolve[sps].ThisQInterval >= 0) 6640 { 6641 LogSPS("mDNSCoreReadyForSleep: waiting for SPS Resolve %s %##s (%s)", 6642 intf->ifname, intf->NetWakeResolve[sps].qname.c, DNSTypeName(intf->NetWakeResolve[sps].qtype)); 6643 goto spsnotready; 6644 } 6645 } 6646 6647 // Scan list of registered records 6648 for (rr = m->ResourceRecords; rr; rr = rr->next) 6649 if (!AuthRecord_uDNS(rr)) 6650 if (!mDNSOpaque64IsZero(&rr->updateIntID)) 6651 { LogSPS("mDNSCoreReadyForSleep: waiting for SPS updateIntID 0x%x 0x%x (updateid %d) %s", rr->updateIntID.l[1], rr->updateIntID.l[0], mDNSVal16(rr->updateid), ARDisplayString(m,rr)); goto spsnotready; } 6652 6653 // Scan list of private LLQs, and make sure they've all completed their handshake with the server 6654 for (q = m->Questions; q; q = q->next) 6655 if (!mDNSOpaque16IsZero(q->TargetQID) && q->LongLived && q->ReqLease == 0 && q->tcp) 6656 { 6657 LogSPS("mDNSCoreReadyForSleep: waiting for LLQ %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 6658 goto notready; 6659 } 6660 6661 // Scan list of registered records 6662 for (rr = m->ResourceRecords; rr; rr = rr->next) 6663 if (AuthRecord_uDNS(rr)) 6664 { 6665 if (rr->state == regState_Refresh && rr->tcp) 6666 { LogSPS("mDNSCoreReadyForSleep: waiting for Record updateIntID 0x%x 0x%x (updateid %d) %s", rr->updateIntID.l[1], rr->updateIntID.l[0], mDNSVal16(rr->updateid), ARDisplayString(m,rr)); goto notready; } 6667 #if APPLE_OSX_mDNSResponder 6668 if (!RecordReadyForSleep(m, rr)) { LogSPS("mDNSCoreReadyForSleep: waiting for %s", ARDisplayString(m, rr)); goto notready; } 6669 #endif 6670 } 6671 6672 mDNS_Unlock(m); 6673 return mDNStrue; 6674 6675 spsnotready: 6676 6677 // If we failed to complete sleep proxy registration within ten seconds, we give up on that 6678 // and allow up to ten seconds more to complete wide-area deregistration instead 6679 if (now - m->SleepLimit >= 0) 6680 { 6681 LogMsg("Failed to register with SPS, now sending goodbyes"); 6682 6683 for (intf = GetFirstActiveInterface(m->HostInterfaces); intf; intf = GetFirstActiveInterface(intf->next)) 6684 if (intf->NetWakeBrowse.ThisQInterval >= 0) 6685 { 6686 LogSPS("ReadyForSleep mDNS_DeactivateNetWake %s %##s (%s)", 6687 intf->ifname, intf->NetWakeResolve[0].qname.c, DNSTypeName(intf->NetWakeResolve[0].qtype)); 6688 mDNS_DeactivateNetWake_internal(m, intf); 6689 } 6690 6691 for (rr = m->ResourceRecords; rr; rr = rr->next) 6692 if (!AuthRecord_uDNS(rr)) 6693 if (!mDNSOpaque64IsZero(&rr->updateIntID)) 6694 { 6695 LogSPS("ReadyForSleep clearing updateIntID 0x%x 0x%x (updateid %d) for %s", rr->updateIntID.l[1], rr->updateIntID.l[0], mDNSVal16(rr->updateid), ARDisplayString(m, rr)); 6696 rr->updateIntID = zeroOpaque64; 6697 } 6698 6699 // We'd really like to allow up to ten seconds more here, 6700 // but if we don't respond to the sleep notification within 30 seconds 6701 // we'll be put back to sleep forcibly without the chance to schedule the next maintenance wake. 6702 // Right now we wait 16 sec after wake for all the interfaces to come up, then we wait up to 10 seconds 6703 // more for SPS resolves and record registrations to complete, which puts us at 26 seconds. 6704 // If we allow just one more second to send our goodbyes, that puts us at 27 seconds. 6705 m->SleepLimit = now + mDNSPlatformOneSecond * 1; 6706 6707 SendSleepGoodbyes(m, mDNStrue, mDNStrue); 6708 } 6709 6710 notready: 6711 mDNS_Unlock(m); 6712 return mDNSfalse; 6713 } 6714 6715 mDNSexport mDNSs32 mDNSCoreIntervalToNextWake(mDNS *const m, mDNSs32 now) 6716 { 6717 AuthRecord *ar; 6718 6719 // Even when we have no wake-on-LAN-capable interfaces, or we failed to find a sleep proxy, or we have other 6720 // failure scenarios, we still want to wake up in at most 120 minutes, to see if the network environment has changed. 6721 // E.g. we might wake up and find no wireless network because the base station got rebooted just at that moment, 6722 // and if that happens we don't want to just give up and go back to sleep and never try again. 6723 mDNSs32 e = now + (120 * 60 * mDNSPlatformOneSecond); // Sleep for at most 120 minutes 6724 6725 NATTraversalInfo *nat; 6726 for (nat = m->NATTraversals; nat; nat=nat->next) 6727 if (nat->Protocol && nat->ExpiryTime && nat->ExpiryTime - now > mDNSPlatformOneSecond*4) 6728 { 6729 mDNSs32 t = nat->ExpiryTime - (nat->ExpiryTime - now) / 10; // Wake up when 90% of the way to the expiry time 6730 if (e - t > 0) e = t; 6731 LogSPS("ComputeWakeTime: %p %s Int %5d Ext %5d Err %d Retry %5d Interval %5d Expire %5d Wake %5d", 6732 nat, nat->Protocol == NATOp_MapTCP ? "TCP" : "UDP", 6733 mDNSVal16(nat->IntPort), mDNSVal16(nat->ExternalPort), nat->Result, 6734 nat->retryPortMap ? (nat->retryPortMap - now) / mDNSPlatformOneSecond : 0, 6735 nat->retryInterval / mDNSPlatformOneSecond, 6736 nat->ExpiryTime ? (nat->ExpiryTime - now) / mDNSPlatformOneSecond : 0, 6737 (t - now) / mDNSPlatformOneSecond); 6738 } 6739 6740 // This loop checks both the time we need to renew wide-area registrations, 6741 // and the time we need to renew Sleep Proxy registrations 6742 for (ar = m->ResourceRecords; ar; ar = ar->next) 6743 if (ar->expire && ar->expire - now > mDNSPlatformOneSecond*4) 6744 { 6745 mDNSs32 t = ar->expire - (ar->expire - now) / 10; // Wake up when 90% of the way to the expiry time 6746 if (e - t > 0) e = t; 6747 LogSPS("ComputeWakeTime: %p Int %7d Next %7d Expire %7d Wake %7d %s", 6748 ar, ar->ThisAPInterval / mDNSPlatformOneSecond, 6749 (ar->LastAPTime + ar->ThisAPInterval - now) / mDNSPlatformOneSecond, 6750 ar->expire ? (ar->expire - now) / mDNSPlatformOneSecond : 0, 6751 (t - now) / mDNSPlatformOneSecond, ARDisplayString(m, ar)); 6752 } 6753 6754 return(e - now); 6755 } 6756 6757 // *************************************************************************** 6758 #if COMPILER_LIKES_PRAGMA_MARK 6759 #pragma mark - 6760 #pragma mark - Packet Reception Functions 6761 #endif 6762 6763 #define MustSendRecord(RR) ((RR)->NR_AnswerTo || (RR)->NR_AdditionalTo) 6764 6765 mDNSlocal mDNSu8 *GenerateUnicastResponse(const DNSMessage *const query, const mDNSu8 *const end, 6766 const mDNSInterfaceID InterfaceID, mDNSBool LegacyQuery, DNSMessage *const response, AuthRecord *ResponseRecords) 6767 { 6768 mDNSu8 *responseptr = response->data; 6769 const mDNSu8 *const limit = response->data + sizeof(response->data); 6770 const mDNSu8 *ptr = query->data; 6771 AuthRecord *rr; 6772 mDNSu32 maxttl = 0x70000000; 6773 int i; 6774 6775 // Initialize the response fields so we can answer the questions 6776 InitializeDNSMessage(&response->h, query->h.id, ResponseFlags); 6777 6778 // *** 6779 // *** 1. Write out the list of questions we are actually going to answer with this packet 6780 // *** 6781 if (LegacyQuery) 6782 { 6783 maxttl = kStaticCacheTTL; 6784 for (i=0; i<query->h.numQuestions; i++) // For each question... 6785 { 6786 DNSQuestion q; 6787 ptr = getQuestion(query, ptr, end, InterfaceID, &q); // get the question... 6788 if (!ptr) return(mDNSNULL); 6789 6790 for (rr=ResponseRecords; rr; rr=rr->NextResponse) // and search our list of proposed answers 6791 { 6792 if (rr->NR_AnswerTo == ptr) // If we're going to generate a record answering this question 6793 { // then put the question in the question section 6794 responseptr = putQuestion(response, responseptr, limit, &q.qname, q.qtype, q.qclass); 6795 if (!responseptr) { debugf("GenerateUnicastResponse: Ran out of space for questions!"); return(mDNSNULL); } 6796 break; // break out of the ResponseRecords loop, and go on to the next question 6797 } 6798 } 6799 } 6800 6801 if (response->h.numQuestions == 0) { LogMsg("GenerateUnicastResponse: ERROR! Why no questions?"); return(mDNSNULL); } 6802 } 6803 6804 // *** 6805 // *** 2. Write Answers 6806 // *** 6807 for (rr=ResponseRecords; rr; rr=rr->NextResponse) 6808 if (rr->NR_AnswerTo) 6809 { 6810 mDNSu8 *p = PutResourceRecordTTL(response, responseptr, &response->h.numAnswers, &rr->resrec, 6811 maxttl < rr->resrec.rroriginalttl ? maxttl : rr->resrec.rroriginalttl); 6812 if (p) responseptr = p; 6813 else { debugf("GenerateUnicastResponse: Ran out of space for answers!"); response->h.flags.b[0] |= kDNSFlag0_TC; } 6814 } 6815 6816 // *** 6817 // *** 3. Write Additionals 6818 // *** 6819 for (rr=ResponseRecords; rr; rr=rr->NextResponse) 6820 if (rr->NR_AdditionalTo && !rr->NR_AnswerTo) 6821 { 6822 mDNSu8 *p = PutResourceRecordTTL(response, responseptr, &response->h.numAdditionals, &rr->resrec, 6823 maxttl < rr->resrec.rroriginalttl ? maxttl : rr->resrec.rroriginalttl); 6824 if (p) responseptr = p; 6825 else debugf("GenerateUnicastResponse: No more space for additionals"); 6826 } 6827 6828 return(responseptr); 6829 } 6830 6831 // AuthRecord *our is our Resource Record 6832 // CacheRecord *pkt is the Resource Record from the response packet we've witnessed on the network 6833 // Returns 0 if there is no conflict 6834 // Returns +1 if there was a conflict and we won 6835 // Returns -1 if there was a conflict and we lost and have to rename 6836 mDNSlocal int CompareRData(const AuthRecord *const our, const CacheRecord *const pkt) 6837 { 6838 mDNSu8 ourdata[256], *ourptr = ourdata, *ourend; 6839 mDNSu8 pktdata[256], *pktptr = pktdata, *pktend; 6840 if (!our) { LogMsg("CompareRData ERROR: our is NULL"); return(+1); } 6841 if (!pkt) { LogMsg("CompareRData ERROR: pkt is NULL"); return(+1); } 6842 6843 ourend = putRData(mDNSNULL, ourdata, ourdata + sizeof(ourdata), &our->resrec); 6844 pktend = putRData(mDNSNULL, pktdata, pktdata + sizeof(pktdata), &pkt->resrec); 6845 while (ourptr < ourend && pktptr < pktend && *ourptr == *pktptr) { ourptr++; pktptr++; } 6846 if (ourptr >= ourend && pktptr >= pktend) return(0); // If data identical, not a conflict 6847 6848 if (ourptr >= ourend) return(-1); // Our data ran out first; We lost 6849 if (pktptr >= pktend) return(+1); // Packet data ran out first; We won 6850 if (*pktptr > *ourptr) return(-1); // Our data is numerically lower; We lost 6851 if (*pktptr < *ourptr) return(+1); // Packet data is numerically lower; We won 6852 6853 LogMsg("CompareRData ERROR: Invalid state"); 6854 return(-1); 6855 } 6856 6857 // See if we have an authoritative record that's identical to this packet record, 6858 // whose canonical DependentOn record is the specified master record. 6859 // The DependentOn pointer is typically used for the TXT record of service registrations 6860 // It indicates that there is no inherent conflict detection for the TXT record 6861 // -- it depends on the SRV record to resolve name conflicts 6862 // If we find any identical ResourceRecords in our authoritative list, then follow their DependentOn 6863 // pointer chain (if any) to make sure we reach the canonical DependentOn record 6864 // If the record has no DependentOn, then just return that record's pointer 6865 // Returns NULL if we don't have any local RRs that are identical to the one from the packet 6866 mDNSlocal mDNSBool MatchDependentOn(const mDNS *const m, const CacheRecord *const pktrr, const AuthRecord *const master) 6867 { 6868 const AuthRecord *r1; 6869 for (r1 = m->ResourceRecords; r1; r1=r1->next) 6870 { 6871 if (IdenticalResourceRecord(&r1->resrec, &pktrr->resrec)) 6872 { 6873 const AuthRecord *r2 = r1; 6874 while (r2->DependentOn) r2 = r2->DependentOn; 6875 if (r2 == master) return(mDNStrue); 6876 } 6877 } 6878 for (r1 = m->DuplicateRecords; r1; r1=r1->next) 6879 { 6880 if (IdenticalResourceRecord(&r1->resrec, &pktrr->resrec)) 6881 { 6882 const AuthRecord *r2 = r1; 6883 while (r2->DependentOn) r2 = r2->DependentOn; 6884 if (r2 == master) return(mDNStrue); 6885 } 6886 } 6887 return(mDNSfalse); 6888 } 6889 6890 // Find the canonical RRSet pointer for this RR received in a packet. 6891 // If we find any identical AuthRecord in our authoritative list, then follow its RRSet 6892 // pointers (if any) to make sure we return the canonical member of this name/type/class 6893 // Returns NULL if we don't have any local RRs that are identical to the one from the packet 6894 mDNSlocal const AuthRecord *FindRRSet(const mDNS *const m, const CacheRecord *const pktrr) 6895 { 6896 const AuthRecord *rr; 6897 for (rr = m->ResourceRecords; rr; rr=rr->next) 6898 { 6899 if (IdenticalResourceRecord(&rr->resrec, &pktrr->resrec)) 6900 { 6901 while (rr->RRSet && rr != rr->RRSet) rr = rr->RRSet; 6902 return(rr); 6903 } 6904 } 6905 return(mDNSNULL); 6906 } 6907 6908 // PacketRRConflict is called when we've received an RR (pktrr) which has the same name 6909 // as one of our records (our) but different rdata. 6910 // 1. If our record is not a type that's supposed to be unique, we don't care. 6911 // 2a. If our record is marked as dependent on some other record for conflict detection, ignore this one. 6912 // 2b. If the packet rr exactly matches one of our other RRs, and *that* record's DependentOn pointer 6913 // points to our record, ignore this conflict (e.g. the packet record matches one of our 6914 // TXT records, and that record is marked as dependent on 'our', its SRV record). 6915 // 3. If we have some *other* RR that exactly matches the one from the packet, and that record and our record 6916 // are members of the same RRSet, then this is not a conflict. 6917 mDNSlocal mDNSBool PacketRRConflict(const mDNS *const m, const AuthRecord *const our, const CacheRecord *const pktrr) 6918 { 6919 // If not supposed to be unique, not a conflict 6920 if (!(our->resrec.RecordType & kDNSRecordTypeUniqueMask)) return(mDNSfalse); 6921 6922 // If a dependent record, not a conflict 6923 if (our->DependentOn || MatchDependentOn(m, pktrr, our)) return(mDNSfalse); 6924 else 6925 { 6926 // If the pktrr matches a member of ourset, not a conflict 6927 const AuthRecord *ourset = our->RRSet ? our->RRSet : our; 6928 const AuthRecord *pktset = FindRRSet(m, pktrr); 6929 if (pktset == ourset) return(mDNSfalse); 6930 6931 // For records we're proxying, where we don't know the full 6932 // relationship between the records, having any matching record 6933 // in our AuthRecords list is sufficient evidence of non-conflict 6934 if (our->WakeUp.HMAC.l[0] && pktset) return(mDNSfalse); 6935 } 6936 6937 // Okay, this is a conflict 6938 return(mDNStrue); 6939 } 6940 6941 // Note: ResolveSimultaneousProbe calls mDNS_Deregister_internal which can call a user callback, which may change 6942 // the record list and/or question list. 6943 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this. 6944 mDNSlocal void ResolveSimultaneousProbe(mDNS *const m, const DNSMessage *const query, const mDNSu8 *const end, 6945 DNSQuestion *q, AuthRecord *our) 6946 { 6947 int i; 6948 const mDNSu8 *ptr = LocateAuthorities(query, end); 6949 mDNSBool FoundUpdate = mDNSfalse; 6950 6951 for (i = 0; i < query->h.numAuthorities; i++) 6952 { 6953 ptr = GetLargeResourceRecord(m, query, ptr, end, q->InterfaceID, kDNSRecordTypePacketAuth, &m->rec); 6954 if (!ptr) break; 6955 if (m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && ResourceRecordAnswersQuestion(&m->rec.r.resrec, q)) 6956 { 6957 FoundUpdate = mDNStrue; 6958 if (PacketRRConflict(m, our, &m->rec.r)) 6959 { 6960 int result = (int)our->resrec.rrclass - (int)m->rec.r.resrec.rrclass; 6961 if (!result) result = (int)our->resrec.rrtype - (int)m->rec.r.resrec.rrtype; 6962 if (!result) result = CompareRData(our, &m->rec.r); 6963 if (result) 6964 { 6965 const char *const msg = (result < 0) ? "lost:" : (result > 0) ? "won: " : "tie: "; 6966 LogMsg("ResolveSimultaneousProbe: %p Pkt Record: %08lX %s", q->InterfaceID, m->rec.r.resrec.rdatahash, CRDisplayString(m, &m->rec.r)); 6967 LogMsg("ResolveSimultaneousProbe: %p Our Record %d %s %08lX %s", our->resrec.InterfaceID, our->ProbeCount, msg, our->resrec.rdatahash, ARDisplayString(m, our)); 6968 } 6969 // If we lost the tie-break for simultaneous probes, we don't immediately give up, because we might be seeing stale packets on the network. 6970 // Instead we pause for one second, to give the other host (if real) a chance to establish its name, and then try probing again. 6971 // If there really is another live host out there with the same name, it will answer our probes and we'll then rename. 6972 if (result < 0) 6973 { 6974 m->SuppressProbes = NonZeroTime(m->timenow + mDNSPlatformOneSecond); 6975 our->ProbeCount = DefaultProbeCountForTypeUnique; 6976 our->AnnounceCount = InitialAnnounceCount; 6977 InitializeLastAPTime(m, our); 6978 goto exit; 6979 } 6980 } 6981 #if 0 6982 else 6983 { 6984 LogMsg("ResolveSimultaneousProbe: %p Pkt Record: %08lX %s", q->InterfaceID, m->rec.r.resrec.rdatahash, CRDisplayString(m, &m->rec.r)); 6985 LogMsg("ResolveSimultaneousProbe: %p Our Record %d ign: %08lX %s", our->resrec.InterfaceID, our->ProbeCount, our->resrec.rdatahash, ARDisplayString(m, our)); 6986 } 6987 #endif 6988 } 6989 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 6990 } 6991 if (!FoundUpdate) 6992 LogInfo("ResolveSimultaneousProbe: %##s (%s): No Update Record found", our->resrec.name->c, DNSTypeName(our->resrec.rrtype)); 6993 exit: 6994 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 6995 } 6996 6997 mDNSlocal CacheRecord *FindIdenticalRecordInCache(const mDNS *const m, const ResourceRecord *const pktrr) 6998 { 6999 mDNSu32 slot = HashSlot(pktrr->name); 7000 CacheGroup *cg = CacheGroupForRecord(m, slot, pktrr); 7001 CacheRecord *rr; 7002 mDNSBool match; 7003 for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) 7004 { 7005 if (!pktrr->InterfaceID) 7006 { 7007 mDNSu16 id1 = (pktrr->rDNSServer ? pktrr->rDNSServer->resGroupID : 0); 7008 mDNSu16 id2 = (rr->resrec.rDNSServer ? rr->resrec.rDNSServer->resGroupID : 0); 7009 match = (id1 == id2); 7010 } 7011 else match = (pktrr->InterfaceID == rr->resrec.InterfaceID); 7012 7013 if (match && IdenticalSameNameRecord(pktrr, &rr->resrec)) break; 7014 } 7015 return(rr); 7016 } 7017 mDNSlocal void DeregisterProxyRecord(mDNS *const m, AuthRecord *const rr) 7018 { 7019 rr->WakeUp.HMAC = zeroEthAddr; // Clear HMAC so that mDNS_Deregister_internal doesn't waste packets trying to wake this host 7020 rr->RequireGoodbye = mDNSfalse; // and we don't want to send goodbye for it 7021 mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal); 7022 SetSPSProxyListChanged(m->rec.r.resrec.InterfaceID); 7023 } 7024 7025 mDNSlocal void ClearKeepaliveProxyRecords(mDNS *const m, const OwnerOptData *const owner, AuthRecord *const thelist, const mDNSInterfaceID InterfaceID) 7026 { 7027 if (m->CurrentRecord) 7028 LogMsg("ClearIdenticalProxyRecords ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord)); 7029 m->CurrentRecord = thelist; 7030 7031 // Normally, the RDATA of the keepalive record will be different each time and hence we always 7032 // clean up the keepalive record. 7033 while (m->CurrentRecord) 7034 { 7035 AuthRecord *const rr = m->CurrentRecord; 7036 if (InterfaceID == rr->resrec.InterfaceID && mDNSSameEthAddress(&owner->HMAC, &rr->WakeUp.HMAC)) 7037 { 7038 if (mDNS_KeepaliveRecord(&m->rec.r.resrec)) 7039 { 7040 LogSPS("ClearKeepaliveProxyRecords: Removing %3d H-MAC %.6a I-MAC %.6a %d %d %s", 7041 m->ProxyRecords, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, rr->WakeUp.seq, owner->seq, ARDisplayString(m, rr)); 7042 DeregisterProxyRecord(m, rr); 7043 } 7044 } 7045 // Mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal, because 7046 // new records could have been added to the end of the list as a result of that call. 7047 if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now 7048 m->CurrentRecord = rr->next; 7049 } 7050 } 7051 7052 // Called from mDNSCoreReceiveUpdate when we get a sleep proxy registration request, 7053 // to check our lists and discard any stale duplicates of this record we already have 7054 mDNSlocal void ClearIdenticalProxyRecords(mDNS *const m, const OwnerOptData *const owner, AuthRecord *const thelist) 7055 { 7056 if (m->CurrentRecord) 7057 LogMsg("ClearIdenticalProxyRecords ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord)); 7058 m->CurrentRecord = thelist; 7059 while (m->CurrentRecord) 7060 { 7061 AuthRecord *const rr = m->CurrentRecord; 7062 if (m->rec.r.resrec.InterfaceID == rr->resrec.InterfaceID && mDNSSameEthAddress(&owner->HMAC, &rr->WakeUp.HMAC)) 7063 if (IdenticalResourceRecord(&rr->resrec, &m->rec.r.resrec)) 7064 { 7065 LogSPS("ClearIdenticalProxyRecords: Removing %3d H-MAC %.6a I-MAC %.6a %d %d %s", 7066 m->ProxyRecords, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, rr->WakeUp.seq, owner->seq, ARDisplayString(m, rr)); 7067 DeregisterProxyRecord(m, rr); 7068 } 7069 // Mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal, because 7070 // new records could have been added to the end of the list as a result of that call. 7071 if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now 7072 m->CurrentRecord = rr->next; 7073 } 7074 } 7075 7076 // Called from ProcessQuery when we get an mDNS packet with an owner record in it 7077 mDNSlocal void ClearProxyRecords(mDNS *const m, const OwnerOptData *const owner, AuthRecord *const thelist) 7078 { 7079 if (m->CurrentRecord) 7080 LogMsg("ClearProxyRecords ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord)); 7081 m->CurrentRecord = thelist; 7082 while (m->CurrentRecord) 7083 { 7084 AuthRecord *const rr = m->CurrentRecord; 7085 if (m->rec.r.resrec.InterfaceID == rr->resrec.InterfaceID && mDNSSameEthAddress(&owner->HMAC, &rr->WakeUp.HMAC)) 7086 if (owner->seq != rr->WakeUp.seq || m->timenow - rr->TimeRcvd > mDNSPlatformOneSecond * 60) 7087 { 7088 if (rr->AddressProxy.type == mDNSAddrType_IPv6) 7089 { 7090 // We don't do this here because we know that the host is waking up at this point, so we don't send 7091 // Unsolicited Neighbor Advertisements -- even Neighbor Advertisements agreeing with what the host should be 7092 // saying itself -- because it can cause some IPv6 stacks to falsely conclude that there's an address conflict. 7093 #if MDNS_USE_Unsolicited_Neighbor_Advertisements 7094 LogSPS("NDP Announcement -- Releasing traffic for H-MAC %.6a I-MAC %.6a %s", 7095 &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m,rr)); 7096 SendNDP(m, NDP_Adv, NDP_Override, rr, &rr->AddressProxy.ip.v6, &rr->WakeUp.IMAC, &AllHosts_v6, &AllHosts_v6_Eth); 7097 #endif 7098 } 7099 LogSPS("ClearProxyRecords: Removing %3d AC %2d %02X H-MAC %.6a I-MAC %.6a %d %d %s", 7100 m->ProxyRecords, rr->AnnounceCount, rr->resrec.RecordType, 7101 &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, rr->WakeUp.seq, owner->seq, ARDisplayString(m, rr)); 7102 if (rr->resrec.RecordType == kDNSRecordTypeDeregistering) rr->resrec.RecordType = kDNSRecordTypeShared; 7103 rr->WakeUp.HMAC = zeroEthAddr; // Clear HMAC so that mDNS_Deregister_internal doesn't waste packets trying to wake this host 7104 rr->RequireGoodbye = mDNSfalse; // and we don't want to send goodbye for it, since real host is now back and functional 7105 mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal); 7106 SetSPSProxyListChanged(m->rec.r.resrec.InterfaceID); 7107 } 7108 // Mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal, because 7109 // new records could have been added to the end of the list as a result of that call. 7110 if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now 7111 m->CurrentRecord = rr->next; 7112 } 7113 } 7114 7115 // ProcessQuery examines a received query to see if we have any answers to give 7116 mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, const mDNSu8 *const end, 7117 const mDNSAddr *srcaddr, const mDNSInterfaceID InterfaceID, mDNSBool LegacyQuery, mDNSBool QueryWasMulticast, 7118 mDNSBool QueryWasLocalUnicast, DNSMessage *const response) 7119 { 7120 mDNSBool FromLocalSubnet = srcaddr && mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr, mDNSNULL); 7121 AuthRecord *ResponseRecords = mDNSNULL; 7122 AuthRecord **nrp = &ResponseRecords; 7123 7124 #if POOF_ENABLED 7125 CacheRecord *ExpectedAnswers = mDNSNULL; // Records in our cache we expect to see updated 7126 CacheRecord **eap = &ExpectedAnswers; 7127 #endif // POOF_ENABLED 7128 7129 DNSQuestion *DupQuestions = mDNSNULL; // Our questions that are identical to questions in this packet 7130 DNSQuestion **dqp = &DupQuestions; 7131 mDNSs32 delayresponse = 0; 7132 mDNSBool SendLegacyResponse = mDNSfalse; 7133 const mDNSu8 *ptr; 7134 mDNSu8 *responseptr = mDNSNULL; 7135 AuthRecord *rr; 7136 int i; 7137 CacheRecord *McastNSEC3Records = mDNSNULL; 7138 7139 // *** 7140 // *** 1. Look in Additional Section for an OPT record 7141 // *** 7142 ptr = LocateOptRR(query, end, DNSOpt_OwnerData_ID_Space); 7143 if (ptr) 7144 { 7145 ptr = GetLargeResourceRecord(m, query, ptr, end, InterfaceID, kDNSRecordTypePacketAdd, &m->rec); 7146 if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && m->rec.r.resrec.rrtype == kDNSType_OPT) 7147 { 7148 const rdataOPT *opt; 7149 const rdataOPT *const e = (const rdataOPT *)&m->rec.r.resrec.rdata->u.data[m->rec.r.resrec.rdlength]; 7150 // Find owner sub-option(s). We verify that the MAC is non-zero, otherwise we could inadvertently 7151 // delete all our own AuthRecords (which are identified by having zero MAC tags on them). 7152 for (opt = &m->rec.r.resrec.rdata->u.opt[0]; opt < e; opt++) 7153 if (opt->opt == kDNSOpt_Owner && opt->u.owner.vers == 0 && opt->u.owner.HMAC.l[0]) 7154 { 7155 ClearProxyRecords(m, &opt->u.owner, m->DuplicateRecords); 7156 ClearProxyRecords(m, &opt->u.owner, m->ResourceRecords); 7157 } 7158 } 7159 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 7160 } 7161 7162 // 7163 // Look in Authority Section for NSEC3 record 7164 // 7165 7166 mDNSParseNSEC3Records(m, query, end, InterfaceID, &McastNSEC3Records); 7167 7168 // *** 7169 // *** 2. Parse Question Section and mark potential answers 7170 // *** 7171 ptr = query->data; 7172 for (i=0; i<query->h.numQuestions; i++) // For each question... 7173 { 7174 mDNSBool QuestionNeedsMulticastResponse; 7175 int NumAnswersForThisQuestion = 0; 7176 AuthRecord *NSECAnswer = mDNSNULL; 7177 DNSQuestion pktq, *q; 7178 ptr = getQuestion(query, ptr, end, InterfaceID, &pktq); // get the question... 7179 if (!ptr) goto exit; 7180 7181 pktq.AnonInfo = mDNSNULL; 7182 if (McastNSEC3Records) 7183 InitializeAnonInfoForQuestion(m, &McastNSEC3Records, &pktq); 7184 // The only queries that *need* a multicast response are: 7185 // * Queries sent via multicast 7186 // * from port 5353 7187 // * that don't have the kDNSQClass_UnicastResponse bit set 7188 // These queries need multicast responses because other clients will: 7189 // * suppress their own identical questions when they see these questions, and 7190 // * expire their cache records if they don't see the expected responses 7191 // For other queries, we may still choose to send the occasional multicast response anyway, 7192 // to keep our neighbours caches warm, and for ongoing conflict detection. 7193 QuestionNeedsMulticastResponse = QueryWasMulticast && !LegacyQuery && !(pktq.qclass & kDNSQClass_UnicastResponse); 7194 7195 if (pktq.qclass & kDNSQClass_UnicastResponse) 7196 m->mDNSStats.UnicastBitInQueries++; 7197 else 7198 m->mDNSStats.NormalQueries++; 7199 7200 // Clear the UnicastResponse flag -- don't want to confuse the rest of the code that follows later 7201 pktq.qclass &= ~kDNSQClass_UnicastResponse; 7202 7203 // Note: We use the m->CurrentRecord mechanism here because calling ResolveSimultaneousProbe 7204 // can result in user callbacks which may change the record list and/or question list. 7205 // Also note: we just mark potential answer records here, without trying to build the 7206 // "ResponseRecords" list, because we don't want to risk user callbacks deleting records 7207 // from that list while we're in the middle of trying to build it. 7208 if (m->CurrentRecord) 7209 LogMsg("ProcessQuery ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord)); 7210 m->CurrentRecord = m->ResourceRecords; 7211 while (m->CurrentRecord) 7212 { 7213 rr = m->CurrentRecord; 7214 m->CurrentRecord = rr->next; 7215 if (AnyTypeRecordAnswersQuestion(&rr->resrec, &pktq) && (QueryWasMulticast || QueryWasLocalUnicast || rr->AllowRemoteQuery)) 7216 { 7217 m->mDNSStats.MatchingAnswersForQueries++; 7218 if (RRTypeAnswersQuestionType(&rr->resrec, pktq.qtype)) 7219 { 7220 if (rr->resrec.RecordType == kDNSRecordTypeUnique) 7221 ResolveSimultaneousProbe(m, query, end, &pktq, rr); 7222 else if (ResourceRecordIsValidAnswer(rr)) 7223 { 7224 NumAnswersForThisQuestion++; 7225 // As we have verified this question to be part of the same subset, 7226 // set the anonymous data which is needed below when walk the cache 7227 // records to see what answers we should be expecting. The cache records 7228 // may cache only the nsec3RR and not the anonymous data itself. 7229 if (pktq.AnonInfo && rr->resrec.AnonInfo) 7230 SetAnonData(&pktq, &rr->resrec, mDNStrue); 7231 7232 // Note: We should check here if this is a probe-type query, and if so, generate an immediate 7233 // unicast answer back to the source, because timeliness in answering probes is important. 7234 7235 // Notes: 7236 // NR_AnswerTo pointing into query packet means "answer via immediate legacy unicast" (may *also* choose to multicast) 7237 // NR_AnswerTo == NR_AnswerUnicast means "answer via delayed unicast" (to modern querier; may promote to multicast instead) 7238 // NR_AnswerTo == NR_AnswerMulticast means "definitely answer via multicast" (can't downgrade to unicast later) 7239 // If we're not multicasting this record because the kDNSQClass_UnicastResponse bit was set, 7240 // but the multicast querier is not on a matching subnet (e.g. because of overlaid subnets on one link) 7241 // then we'll multicast it anyway (if we unicast, the receiver will ignore it because it has an apparently non-local source) 7242 if (QuestionNeedsMulticastResponse || (!FromLocalSubnet && QueryWasMulticast && !LegacyQuery)) 7243 { 7244 // We only mark this question for sending if it is at least one second since the last time we multicast it 7245 // on this interface. If it is more than a second, or LastMCInterface is different, then we may multicast it. 7246 // This is to guard against the case where someone blasts us with queries as fast as they can. 7247 if (m->timenow - (rr->LastMCTime + mDNSPlatformOneSecond) >= 0 || 7248 (rr->LastMCInterface != mDNSInterfaceMark && rr->LastMCInterface != InterfaceID)) 7249 rr->NR_AnswerTo = NR_AnswerMulticast; 7250 } 7251 else if (!rr->NR_AnswerTo) rr->NR_AnswerTo = LegacyQuery ? ptr : NR_AnswerUnicast; 7252 } 7253 } 7254 else if ((rr->resrec.RecordType & kDNSRecordTypeActiveUniqueMask) && ResourceRecordIsValidAnswer(rr)) 7255 { 7256 // If we don't have any answers for this question, but we do own another record with the same name, 7257 // then we'll want to mark it to generate an NSEC record on this interface 7258 if (!NSECAnswer) NSECAnswer = rr; 7259 } 7260 } 7261 } 7262 7263 if (NumAnswersForThisQuestion == 0 && NSECAnswer) 7264 { 7265 NumAnswersForThisQuestion++; 7266 NSECAnswer->SendNSECNow = InterfaceID; 7267 m->NextScheduledResponse = m->timenow; 7268 } 7269 7270 // If we couldn't answer this question, someone else might be able to, 7271 // so use random delay on response to reduce collisions 7272 if (NumAnswersForThisQuestion == 0) delayresponse = mDNSPlatformOneSecond; // Divided by 50 = 20ms 7273 7274 if (query->h.flags.b[0] & kDNSFlag0_TC) 7275 m->mDNSStats.KnownAnswerMultiplePkts++; 7276 #if ENABLE_MULTI_PACKET_QUERY_SNOOPING 7277 if (QuestionNeedsMulticastResponse) 7278 #else 7279 // We only do the following accelerated cache expiration and duplicate question suppression processing 7280 // for non-truncated multicast queries with multicast responses. 7281 // For any query generating a unicast response we don't do this because we can't assume we will see the response. 7282 // For truncated queries we don't do this because a response we're expecting might be suppressed by a subsequent 7283 // known-answer packet, and when there's packet loss we can't safely assume we'll receive *all* known-answer packets. 7284 if (QuestionNeedsMulticastResponse && !(query->h.flags.b[0] & kDNSFlag0_TC)) 7285 #endif 7286 { 7287 #if POOF_ENABLED 7288 const mDNSu32 slot = HashSlot(&pktq.qname); 7289 CacheGroup *cg = CacheGroupForName(m, slot, pktq.qnamehash, &pktq.qname); 7290 CacheRecord *cr; 7291 7292 // Make a list indicating which of our own cache records we expect to see updated as a result of this query 7293 // Note: Records larger than 1K are not habitually multicast, so don't expect those to be updated 7294 #if ENABLE_MULTI_PACKET_QUERY_SNOOPING 7295 if (!(query->h.flags.b[0] & kDNSFlag0_TC)) 7296 #endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING 7297 for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next) 7298 if (SameNameRecordAnswersQuestion(&cr->resrec, &pktq) && cr->resrec.rdlength <= SmallRecordLimit) 7299 if (!cr->NextInKAList && eap != &cr->NextInKAList) 7300 { 7301 *eap = cr; 7302 eap = &cr->NextInKAList; 7303 #if ENABLE_MULTI_PACKET_QUERY_SNOOPING 7304 if (cr->MPUnansweredQ == 0 || m->timenow - cr->MPLastUnansweredQT >= mDNSPlatformOneSecond) 7305 { 7306 // Although MPUnansweredQ is only really used for multi-packet query processing, 7307 // we increment it for both single-packet and multi-packet queries, so that it stays in sync 7308 // with the MPUnansweredKA value, which by necessity is incremented for both query types. 7309 cr->MPUnansweredQ++; 7310 cr->MPLastUnansweredQT = m->timenow; 7311 cr->MPExpectingKA = mDNStrue; 7312 } 7313 #endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING 7314 } 7315 #endif // POOF_ENABLED 7316 7317 // Check if this question is the same as any of mine. 7318 // We only do this for non-truncated queries. Right now it would be too complicated to try 7319 // to keep track of duplicate suppression state between multiple packets, especially when we 7320 // can't guarantee to receive all of the Known Answer packets that go with a particular query. 7321 #if ENABLE_MULTI_PACKET_QUERY_SNOOPING 7322 if (!(query->h.flags.b[0] & kDNSFlag0_TC)) 7323 #endif 7324 // For anonymous question, the duplicate suppressesion should happen if the 7325 // question belongs in the same group. As the group is expected to be 7326 // small, we don't do the optimization for now. 7327 if (!pktq.AnonInfo) 7328 { 7329 for (q = m->Questions; q; q=q->next) 7330 if (!q->Target.type && ActiveQuestion(q) && m->timenow - q->LastQTxTime > mDNSPlatformOneSecond / 4) 7331 if (!q->InterfaceID || q->InterfaceID == InterfaceID) 7332 if (q->NextInDQList == mDNSNULL && dqp != &q->NextInDQList) 7333 if (q->qtype == pktq.qtype && 7334 q->qclass == pktq.qclass && 7335 q->qnamehash == pktq.qnamehash && SameDomainName(&q->qname, &pktq.qname)) 7336 { *dqp = q; dqp = &q->NextInDQList; } 7337 } 7338 } 7339 if (pktq.AnonInfo) 7340 { 7341 FreeAnonInfo(pktq.AnonInfo); 7342 } 7343 } 7344 7345 // *** 7346 // *** 3. Now we can safely build the list of marked answers 7347 // *** 7348 for (rr = m->ResourceRecords; rr; rr=rr->next) // Now build our list of potential answers 7349 if (rr->NR_AnswerTo) // If we marked the record... 7350 AddRecordToResponseList(&nrp, rr, mDNSNULL); // ... add it to the list 7351 7352 // *** 7353 // *** 4. Add additional records 7354 // *** 7355 AddAdditionalsToResponseList(m, ResponseRecords, &nrp, InterfaceID); 7356 7357 // *** 7358 // *** 5. Parse Answer Section and cancel any records disallowed by Known-Answer list 7359 // *** 7360 for (i=0; i<query->h.numAnswers; i++) // For each record in the query's answer section... 7361 { 7362 // Get the record... 7363 CacheRecord *ourcacherr; 7364 ptr = GetLargeResourceRecord(m, query, ptr, end, InterfaceID, kDNSRecordTypePacketAns, &m->rec); 7365 if (!ptr) goto exit; 7366 if (m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative) 7367 { 7368 // See if this Known-Answer suppresses any of our currently planned answers 7369 for (rr=ResponseRecords; rr; rr=rr->NextResponse) 7370 { 7371 if (MustSendRecord(rr) && ShouldSuppressKnownAnswer(&m->rec.r, rr)) 7372 { 7373 m->mDNSStats.KnownAnswerSuppressions++; 7374 rr->NR_AnswerTo = mDNSNULL; 7375 rr->NR_AdditionalTo = mDNSNULL; 7376 } 7377 } 7378 7379 // See if this Known-Answer suppresses any previously scheduled answers (for multi-packet KA suppression) 7380 for (rr=m->ResourceRecords; rr; rr=rr->next) 7381 { 7382 // If we're planning to send this answer on this interface, and only on this interface, then allow KA suppression 7383 if (rr->ImmedAnswer == InterfaceID && ShouldSuppressKnownAnswer(&m->rec.r, rr)) 7384 { 7385 if (srcaddr->type == mDNSAddrType_IPv4) 7386 { 7387 if (mDNSSameIPv4Address(rr->v4Requester, srcaddr->ip.v4)) rr->v4Requester = zerov4Addr; 7388 } 7389 else if (srcaddr->type == mDNSAddrType_IPv6) 7390 { 7391 if (mDNSSameIPv6Address(rr->v6Requester, srcaddr->ip.v6)) rr->v6Requester = zerov6Addr; 7392 } 7393 if (mDNSIPv4AddressIsZero(rr->v4Requester) && mDNSIPv6AddressIsZero(rr->v6Requester)) 7394 { 7395 m->mDNSStats.KnownAnswerSuppressions++; 7396 rr->ImmedAnswer = mDNSNULL; 7397 rr->ImmedUnicast = mDNSfalse; 7398 #if MDNS_LOG_ANSWER_SUPPRESSION_TIMES 7399 LogMsg("Suppressed after%4d: %s", m->timenow - rr->ImmedAnswerMarkTime, ARDisplayString(m, rr)); 7400 #endif 7401 } 7402 } 7403 } 7404 7405 ourcacherr = FindIdenticalRecordInCache(m, &m->rec.r.resrec); 7406 7407 #if ENABLE_MULTI_PACKET_QUERY_SNOOPING 7408 // See if this Known-Answer suppresses any answers we were expecting for our cache records. We do this always, 7409 // even if the TC bit is not set (the TC bit will *not* be set in the *last* packet of a multi-packet KA list). 7410 if (ourcacherr && ourcacherr->MPExpectingKA && m->timenow - ourcacherr->MPLastUnansweredQT < mDNSPlatformOneSecond) 7411 { 7412 ourcacherr->MPUnansweredKA++; 7413 ourcacherr->MPExpectingKA = mDNSfalse; 7414 } 7415 #endif 7416 7417 #if POOF_ENABLED 7418 // Having built our ExpectedAnswers list from the questions in this packet, we then remove 7419 // any records that are suppressed by the Known Answer list in this packet. 7420 eap = &ExpectedAnswers; 7421 while (*eap) 7422 { 7423 CacheRecord *cr = *eap; 7424 if (cr->resrec.InterfaceID == InterfaceID && IdenticalResourceRecord(&m->rec.r.resrec, &cr->resrec)) 7425 { *eap = cr->NextInKAList; cr->NextInKAList = mDNSNULL; } 7426 else eap = &cr->NextInKAList; 7427 } 7428 #endif // POOF_ENABLED 7429 7430 // See if this Known-Answer is a surprise to us. If so, we shouldn't suppress our own query. 7431 if (!ourcacherr) 7432 { 7433 dqp = &DupQuestions; 7434 while (*dqp) 7435 { 7436 DNSQuestion *q = *dqp; 7437 if (ResourceRecordAnswersQuestion(&m->rec.r.resrec, q)) 7438 { *dqp = q->NextInDQList; q->NextInDQList = mDNSNULL; } 7439 else dqp = &q->NextInDQList; 7440 } 7441 } 7442 } 7443 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 7444 } 7445 7446 // *** 7447 // *** 6. Cancel any additionals that were added because of now-deleted records 7448 // *** 7449 for (rr=ResponseRecords; rr; rr=rr->NextResponse) 7450 if (rr->NR_AdditionalTo && !MustSendRecord(rr->NR_AdditionalTo)) 7451 { rr->NR_AnswerTo = mDNSNULL; rr->NR_AdditionalTo = mDNSNULL; } 7452 7453 // *** 7454 // *** 7. Mark the send flags on the records we plan to send 7455 // *** 7456 for (rr=ResponseRecords; rr; rr=rr->NextResponse) 7457 { 7458 if (rr->NR_AnswerTo) 7459 { 7460 mDNSBool SendMulticastResponse = mDNSfalse; // Send modern multicast response 7461 mDNSBool SendUnicastResponse = mDNSfalse; // Send modern unicast response (not legacy unicast response) 7462 7463 #if !TARGET_OS_EMBEDDED 7464 // always honor kDNSQClass_UnicastResponse in embedded environment to increase reliability 7465 // in high multicast packet loss environments. 7466 7467 // If it's been one TTL/4 since we multicast this, then send a multicast response 7468 // for conflict detection, etc. 7469 if (m->timenow - (rr->LastMCTime + TicksTTL(rr)/4) >= 0) 7470 { 7471 SendMulticastResponse = mDNStrue; 7472 // If this record was marked for modern (delayed) unicast response, then mark it as promoted to 7473 // multicast response instead (don't want to end up ALSO setting SendUnicastResponse in the check below). 7474 // If this record was marked for legacy unicast response, then we mustn't change the NR_AnswerTo value. 7475 if (rr->NR_AnswerTo == NR_AnswerUnicast) 7476 { 7477 m->mDNSStats.UnicastDemotedToMulticast++; 7478 rr->NR_AnswerTo = NR_AnswerMulticast; 7479 } 7480 } 7481 #endif // !TARGET_OS_EMBEDDED 7482 7483 // If the client insists on a multicast response, then we'd better send one 7484 if (rr->NR_AnswerTo == NR_AnswerMulticast) 7485 { 7486 m->mDNSStats.MulticastResponses++; 7487 SendMulticastResponse = mDNStrue; 7488 } 7489 else if (rr->NR_AnswerTo == NR_AnswerUnicast) 7490 { 7491 m->mDNSStats.UnicastResponses++; 7492 SendUnicastResponse = mDNStrue; 7493 } 7494 else if (rr->NR_AnswerTo) 7495 { 7496 SendLegacyResponse = mDNStrue; 7497 } 7498 7499 7500 if (SendMulticastResponse || SendUnicastResponse) 7501 { 7502 #if MDNS_LOG_ANSWER_SUPPRESSION_TIMES 7503 rr->ImmedAnswerMarkTime = m->timenow; 7504 #endif 7505 m->NextScheduledResponse = m->timenow; 7506 // If we're already planning to send this on another interface, just send it on all interfaces 7507 if (rr->ImmedAnswer && rr->ImmedAnswer != InterfaceID) 7508 rr->ImmedAnswer = mDNSInterfaceMark; 7509 else 7510 { 7511 rr->ImmedAnswer = InterfaceID; // Record interface to send it on 7512 if (SendUnicastResponse) rr->ImmedUnicast = mDNStrue; 7513 if (srcaddr->type == mDNSAddrType_IPv4) 7514 { 7515 if (mDNSIPv4AddressIsZero(rr->v4Requester)) rr->v4Requester = srcaddr->ip.v4; 7516 else if (!mDNSSameIPv4Address(rr->v4Requester, srcaddr->ip.v4)) rr->v4Requester = onesIPv4Addr; 7517 } 7518 else if (srcaddr->type == mDNSAddrType_IPv6) 7519 { 7520 if (mDNSIPv6AddressIsZero(rr->v6Requester)) rr->v6Requester = srcaddr->ip.v6; 7521 else if (!mDNSSameIPv6Address(rr->v6Requester, srcaddr->ip.v6)) rr->v6Requester = onesIPv6Addr; 7522 } 7523 } 7524 } 7525 // If TC flag is set, it means we should expect that additional known answers may be coming in another packet, 7526 // so we allow roughly half a second before deciding to reply (we've observed inter-packet delays of 100-200ms on 802.11) 7527 // else, if record is a shared one, spread responses over 100ms to avoid implosion of simultaneous responses 7528 // else, for a simple unique record reply, we can reply immediately; no need for delay 7529 if (query->h.flags.b[0] & kDNSFlag0_TC) delayresponse = mDNSPlatformOneSecond * 20; // Divided by 50 = 400ms 7530 else if (rr->resrec.RecordType == kDNSRecordTypeShared) delayresponse = mDNSPlatformOneSecond; // Divided by 50 = 20ms 7531 } 7532 else if (rr->NR_AdditionalTo && rr->NR_AdditionalTo->NR_AnswerTo == NR_AnswerMulticast) 7533 { 7534 // Since additional records are an optimization anyway, we only ever send them on one interface at a time 7535 // If two clients on different interfaces do queries that invoke the same optional additional answer, 7536 // then the earlier client is out of luck 7537 rr->ImmedAdditional = InterfaceID; 7538 // No need to set m->NextScheduledResponse here 7539 // We'll send these additional records when we send them, or not, as the case may be 7540 } 7541 } 7542 7543 // *** 7544 // *** 8. If we think other machines are likely to answer these questions, set our packet suppression timer 7545 // *** 7546 if (delayresponse && (!m->SuppressSending || (m->SuppressSending - m->timenow) < (delayresponse + 49) / 50)) 7547 { 7548 #if MDNS_LOG_ANSWER_SUPPRESSION_TIMES 7549 mDNSs32 oldss = m->SuppressSending; 7550 if (oldss && delayresponse) 7551 LogMsg("Current SuppressSending delay%5ld; require%5ld", m->SuppressSending - m->timenow, (delayresponse + 49) / 50); 7552 #endif 7553 // Pick a random delay: 7554 // We start with the base delay chosen above (typically either 1 second or 20 seconds), 7555 // and add a random value in the range 0-5 seconds (making 1-6 seconds or 20-25 seconds). 7556 // This is an integer value, with resolution determined by the platform clock rate. 7557 // We then divide that by 50 to get the delay value in ticks. We defer the division until last 7558 // to get better results on platforms with coarse clock granularity (e.g. ten ticks per second). 7559 // The +49 before dividing is to ensure we round up, not down, to ensure that even 7560 // on platforms where the native clock rate is less than fifty ticks per second, 7561 // we still guarantee that the final calculated delay is at least one platform tick. 7562 // We want to make sure we don't ever allow the delay to be zero ticks, 7563 // because if that happens we'll fail the Bonjour Conformance Test. 7564 // Our final computed delay is 20-120ms for normal delayed replies, 7565 // or 400-500ms in the case of multi-packet known-answer lists. 7566 m->SuppressSending = m->timenow + (delayresponse + (mDNSs32)mDNSRandom((mDNSu32)mDNSPlatformOneSecond*5) + 49) / 50; 7567 if (m->SuppressSending == 0) m->SuppressSending = 1; 7568 #if MDNS_LOG_ANSWER_SUPPRESSION_TIMES 7569 if (oldss && delayresponse) 7570 LogMsg("Set SuppressSending to %5ld", m->SuppressSending - m->timenow); 7571 #endif 7572 } 7573 7574 // *** 7575 // *** 9. If query is from a legacy client, or from a new client requesting a unicast reply, then generate a unicast response too 7576 // *** 7577 if (SendLegacyResponse) 7578 responseptr = GenerateUnicastResponse(query, end, InterfaceID, LegacyQuery, response, ResponseRecords); 7579 7580 exit: 7581 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 7582 7583 // *** 7584 // *** 10. Finally, clear our link chains ready for use next time 7585 // *** 7586 while (ResponseRecords) 7587 { 7588 rr = ResponseRecords; 7589 ResponseRecords = rr->NextResponse; 7590 rr->NextResponse = mDNSNULL; 7591 rr->NR_AnswerTo = mDNSNULL; 7592 rr->NR_AdditionalTo = mDNSNULL; 7593 } 7594 7595 #if POOF_ENABLED 7596 while (ExpectedAnswers) 7597 { 7598 CacheRecord *cr = ExpectedAnswers; 7599 ExpectedAnswers = cr->NextInKAList; 7600 cr->NextInKAList = mDNSNULL; 7601 7602 // For non-truncated queries, we can definitively say that we should expect 7603 // to be seeing a response for any records still left in the ExpectedAnswers list 7604 if (!(query->h.flags.b[0] & kDNSFlag0_TC)) 7605 if (cr->UnansweredQueries == 0 || m->timenow - cr->LastUnansweredTime >= mDNSPlatformOneSecond) 7606 { 7607 cr->UnansweredQueries++; 7608 cr->LastUnansweredTime = m->timenow; 7609 #if ENABLE_MULTI_PACKET_QUERY_SNOOPING 7610 if (cr->UnansweredQueries > 1) 7611 debugf("ProcessQuery: (!TC) UAQ %lu MPQ %lu MPKA %lu %s", 7612 cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr)); 7613 #endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING 7614 SetNextCacheCheckTimeForRecord(m, cr); 7615 } 7616 7617 // If we've seen multiple unanswered queries for this record, 7618 // then mark it to expire in five seconds if we don't get a response by then. 7619 if (cr->UnansweredQueries >= MaxUnansweredQueries) 7620 { 7621 #if ENABLE_MULTI_PACKET_QUERY_SNOOPING 7622 // Only show debugging message if this record was not about to expire anyway 7623 if (RRExpireTime(cr) - m->timenow > 4 * mDNSPlatformOneSecond) 7624 debugf("ProcessQuery: (Max) UAQ %lu MPQ %lu MPKA %lu mDNS_Reconfirm() for %s", 7625 cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr)); 7626 #endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING 7627 m->mDNSStats.PoofCacheDeletions++; 7628 mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer); 7629 } 7630 #if ENABLE_MULTI_PACKET_QUERY_SNOOPING 7631 // Make a guess, based on the multi-packet query / known answer counts, whether we think we 7632 // should have seen an answer for this. (We multiply MPQ by 4 and MPKA by 5, to allow for 7633 // possible packet loss of up to 20% of the additional KA packets.) 7634 else if (cr->MPUnansweredQ * 4 > cr->MPUnansweredKA * 5 + 8) 7635 { 7636 // We want to do this conservatively. 7637 // If there are so many machines on the network that they have to use multi-packet known-answer lists, 7638 // then we don't want them to all hit the network simultaneously with their final expiration queries. 7639 // By setting the record to expire in four minutes, we achieve two things: 7640 // (a) the 90-95% final expiration queries will be less bunched together 7641 // (b) we allow some time for us to witness enough other failed queries that we don't have to do our own 7642 mDNSu32 remain = (mDNSu32)(RRExpireTime(cr) - m->timenow) / 4; 7643 if (remain > 240 * (mDNSu32)mDNSPlatformOneSecond) 7644 remain = 240 * (mDNSu32)mDNSPlatformOneSecond; 7645 7646 // Only show debugging message if this record was not about to expire anyway 7647 if (RRExpireTime(cr) - m->timenow > 4 * mDNSPlatformOneSecond) 7648 debugf("ProcessQuery: (MPQ) UAQ %lu MPQ %lu MPKA %lu mDNS_Reconfirm() for %s", 7649 cr->UnansweredQueries, cr->MPUnansweredQ, cr->MPUnansweredKA, CRDisplayString(m, cr)); 7650 7651 if (remain <= 60 * (mDNSu32)mDNSPlatformOneSecond) 7652 cr->UnansweredQueries++; // Treat this as equivalent to one definite unanswered query 7653 cr->MPUnansweredQ = 0; // Clear MPQ/MPKA statistics 7654 cr->MPUnansweredKA = 0; 7655 cr->MPExpectingKA = mDNSfalse; 7656 7657 if (remain < kDefaultReconfirmTimeForNoAnswer) 7658 remain = kDefaultReconfirmTimeForNoAnswer; 7659 mDNS_Reconfirm_internal(m, cr, remain); 7660 } 7661 #endif // ENABLE_MULTI_PACKET_QUERY_SNOOPING 7662 } 7663 #endif // POOF_ENABLED 7664 7665 while (DupQuestions) 7666 { 7667 DNSQuestion *q = DupQuestions; 7668 DupQuestions = q->NextInDQList; 7669 q->NextInDQList = mDNSNULL; 7670 i = RecordDupSuppressInfo(q->DupSuppress, m->timenow, InterfaceID, srcaddr->type); 7671 debugf("ProcessQuery: Recorded DSI for %##s (%s) on %p/%s %d", q->qname.c, DNSTypeName(q->qtype), InterfaceID, 7672 srcaddr->type == mDNSAddrType_IPv4 ? "v4" : "v6", i); 7673 } 7674 7675 if (McastNSEC3Records) 7676 { 7677 debugf("ProcessQuery: McastNSEC3Records not used"); 7678 FreeNSECRecords(m, McastNSEC3Records); 7679 } 7680 7681 return(responseptr); 7682 } 7683 7684 mDNSlocal void mDNSCoreReceiveQuery(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, 7685 const mDNSAddr *srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, mDNSIPPort dstport, 7686 const mDNSInterfaceID InterfaceID) 7687 { 7688 mDNSu8 *responseend = mDNSNULL; 7689 mDNSBool QueryWasLocalUnicast = srcaddr && dstaddr && 7690 !mDNSAddrIsDNSMulticast(dstaddr) && mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr, mDNSNULL); 7691 7692 if (!InterfaceID && dstaddr && mDNSAddrIsDNSMulticast(dstaddr)) 7693 { 7694 LogMsg("Ignoring Query from %#-15a:%-5d to %#-15a:%-5d on 0x%p with " 7695 "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s %d bytes (Multicast, but no InterfaceID)", 7696 srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), InterfaceID, 7697 msg->h.numQuestions, msg->h.numQuestions == 1 ? ", " : "s,", 7698 msg->h.numAnswers, msg->h.numAnswers == 1 ? ", " : "s,", 7699 msg->h.numAuthorities, msg->h.numAuthorities == 1 ? "y, " : "ies,", 7700 msg->h.numAdditionals, msg->h.numAdditionals == 1 ? " " : "s", end - msg->data); 7701 return; 7702 } 7703 7704 verbosedebugf("Received Query from %#-15a:%-5d to %#-15a:%-5d on 0x%p with " 7705 "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s %d bytes", 7706 srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), InterfaceID, 7707 msg->h.numQuestions, msg->h.numQuestions == 1 ? ", " : "s,", 7708 msg->h.numAnswers, msg->h.numAnswers == 1 ? ", " : "s,", 7709 msg->h.numAuthorities, msg->h.numAuthorities == 1 ? "y, " : "ies,", 7710 msg->h.numAdditionals, msg->h.numAdditionals == 1 ? " " : "s", end - msg->data); 7711 7712 responseend = ProcessQuery(m, msg, end, srcaddr, InterfaceID, 7713 !mDNSSameIPPort(srcport, MulticastDNSPort), mDNSAddrIsDNSMulticast(dstaddr), QueryWasLocalUnicast, &m->omsg); 7714 7715 if (responseend) // If responseend is non-null, that means we built a unicast response packet 7716 { 7717 debugf("Unicast Response: %d Question%s, %d Answer%s, %d Additional%s to %#-15a:%d on %p/%ld", 7718 m->omsg.h.numQuestions, m->omsg.h.numQuestions == 1 ? "" : "s", 7719 m->omsg.h.numAnswers, m->omsg.h.numAnswers == 1 ? "" : "s", 7720 m->omsg.h.numAdditionals, m->omsg.h.numAdditionals == 1 ? "" : "s", 7721 srcaddr, mDNSVal16(srcport), InterfaceID, srcaddr->type); 7722 mDNSSendDNSMessage(m, &m->omsg, responseend, InterfaceID, mDNSNULL, srcaddr, srcport, mDNSNULL, mDNSNULL, mDNSfalse); 7723 } 7724 } 7725 7726 #if 0 7727 mDNSlocal mDNSBool TrustedSource(const mDNS *const m, const mDNSAddr *const srcaddr) 7728 { 7729 DNSServer *s; 7730 (void)m; // Unused 7731 (void)srcaddr; // Unused 7732 for (s = m->DNSServers; s; s = s->next) 7733 if (mDNSSameAddress(srcaddr, &s->addr)) return(mDNStrue); 7734 return(mDNSfalse); 7735 } 7736 #endif 7737 7738 struct UDPSocket_struct 7739 { 7740 mDNSIPPort port; // MUST BE FIRST FIELD -- mDNSCoreReceive expects every UDPSocket_struct to begin with mDNSIPPort port 7741 }; 7742 7743 mDNSlocal DNSQuestion *ExpectingUnicastResponseForQuestion(const mDNS *const m, const mDNSIPPort port, const mDNSOpaque16 id, const DNSQuestion *const question, mDNSBool tcp) 7744 { 7745 DNSQuestion *q; 7746 for (q = m->Questions; q; q=q->next) 7747 { 7748 if (!tcp && !q->LocalSocket) continue; 7749 if (mDNSSameIPPort(tcp ? q->tcpSrcPort : q->LocalSocket->port, port) && 7750 mDNSSameOpaque16(q->TargetQID, id) && 7751 q->qtype == question->qtype && 7752 q->qclass == question->qclass && 7753 q->qnamehash == question->qnamehash && 7754 SameDomainName(&q->qname, &question->qname)) 7755 return(q); 7756 } 7757 return(mDNSNULL); 7758 } 7759 7760 // This function is called when we receive a unicast response. This could be the case of a unicast response from the 7761 // DNS server or a response to the QU query. Hence, the cache record's InterfaceId can be both NULL or non-NULL (QU case) 7762 mDNSlocal DNSQuestion *ExpectingUnicastResponseForRecord(mDNS *const m, 7763 const mDNSAddr *const srcaddr, const mDNSBool SrcLocal, const mDNSIPPort port, const mDNSOpaque16 id, const CacheRecord *const rr, mDNSBool tcp) 7764 { 7765 DNSQuestion *q; 7766 (void)id; 7767 (void)srcaddr; 7768 7769 for (q = m->Questions; q; q=q->next) 7770 { 7771 if (!q->DuplicateOf && ResourceRecordAnswersUnicastResponse(&rr->resrec, q)) 7772 { 7773 if (!mDNSOpaque16IsZero(q->TargetQID)) 7774 { 7775 debugf("ExpectingUnicastResponseForRecord msg->h.id %d q->TargetQID %d for %s", mDNSVal16(id), mDNSVal16(q->TargetQID), CRDisplayString(m, rr)); 7776 7777 if (mDNSSameOpaque16(q->TargetQID, id)) 7778 { 7779 mDNSIPPort srcp; 7780 if (!tcp) 7781 { 7782 if (q->LocalSocket) 7783 srcp = q->LocalSocket->port; 7784 else 7785 srcp = zeroIPPort; 7786 } 7787 else 7788 { 7789 srcp = q->tcpSrcPort; 7790 } 7791 if (mDNSSameIPPort(srcp, port)) return(q); 7792 7793 // if (mDNSSameAddress(srcaddr, &q->Target)) return(mDNStrue); 7794 // if (q->LongLived && mDNSSameAddress(srcaddr, &q->servAddr)) return(mDNStrue); Shouldn't need this now that we have LLQType checking 7795 // if (TrustedSource(m, srcaddr)) return(mDNStrue); 7796 LogInfo("WARNING: Ignoring suspect uDNS response for %##s (%s) [q->Target %#a:%d] from %#a:%d %s", 7797 q->qname.c, DNSTypeName(q->qtype), &q->Target, mDNSVal16(srcp), srcaddr, mDNSVal16(port), CRDisplayString(m, rr)); 7798 return(mDNSNULL); 7799 } 7800 } 7801 else 7802 { 7803 if (SrcLocal && q->ExpectUnicastResp && (mDNSu32)(m->timenow - q->ExpectUnicastResp) < (mDNSu32)(mDNSPlatformOneSecond*2)) 7804 return(q); 7805 } 7806 } 7807 } 7808 return(mDNSNULL); 7809 } 7810 7811 // Return a pointer to the primary service name, skipping subtype name if present. 7812 mDNSlocal const domainname *getPrimaryServiceName(const domainname *domainName) 7813 { 7814 const domainname *primaryName = domainName; 7815 const domainname *subName = SkipLeadingLabels(domainName, 1); 7816 7817 if (SameDomainLabel(subName->c, (const mDNSu8 *)mDNSSubTypeLabel)) 7818 { 7819 // skip "<sub type name>._sub" portion of name 7820 primaryName = SkipLeadingLabels(domainName, 2); 7821 debugf("getPrimaryServiceName: returning %##s for _sub type", primaryName); 7822 } 7823 7824 return primaryName; 7825 } 7826 7827 // This function is not called if the packet is from us, which implies that we accept all multicast packets coming from us. 7828 mDNSlocal mDNSBool ExpectingMulticastResponseForRecord(mDNS *const m, CacheRecord *rr, const mDNSAddr *srcaddr, mDNSBool recordAccepted, 7829 CacheRecord **McastNSEC3Records) 7830 { 7831 DNSQuestion *q; 7832 7833 // Accept A and AAAA if we accepted something before in the same packet as most likely related to the 7834 // service records that we may have accepted. 7835 if (recordAccepted && (rr->resrec.rrtype == kDNSType_A || rr->resrec.rrtype == kDNSType_AAAA)) 7836 { 7837 LogInfo("ExpectingMulticastResponseForRecord:A:AAAA: accepting %s, from %#a due to same packet %d", CRDisplayString(m, rr), srcaddr, m->PktNum); 7838 return mDNStrue; 7839 } 7840 for (q = m->Questions; q; q=q->next) 7841 { 7842 if (!q->DuplicateOf && mDNSOpaque16IsZero(q->TargetQID)) 7843 { 7844 mDNSBool ret; 7845 // 1. If a resource record answers question, cache it. This also will cache NSECs if it asserts 7846 // non-existence of q->qtype. If we have any matching NSEC3 Records for the question, send 7847 // it along with the resource record. Do it only for questions that are expecting to 7848 // discover only its peers (q->AnonInfo not NULL) 7849 if (q->AnonInfo && McastNSEC3Records && !rr->resrec.AnonInfo) 7850 { 7851 InitializeAnonInfoForCR(m, McastNSEC3Records, rr); 7852 } 7853 ret = ResourceRecordAnswersQuestion(&rr->resrec, q); 7854 if (ret) 7855 { 7856 // The record and the question belong to the same subset. Set the 7857 // anonymous data in the cache record. 7858 if (q->AnonInfo && rr->resrec.AnonInfo) 7859 { 7860 SetAnonData(q, &rr->resrec, mDNSfalse); 7861 } 7862 LogInfo("ExpectingMulticastResponseForRecord: Name and Type match, accepting %s, from %#a", CRDisplayString(m, rr), srcaddr); 7863 if (rr->resrec.rrtype == kDNSType_NSEC) 7864 LogInfo("ExpectingMulticastResponseForRecord: record %s, question %##s (%s)", CRDisplayString(m, rr), q->qname.c, DNSTypeName(q->qtype)); 7865 return mDNStrue; 7866 } 7867 if (rr->resrec.rrtype == kDNSType_SRV || rr->resrec.rrtype == kDNSType_TXT) 7868 { 7869 // Point to the service type in the record name 7870 const domainname *name = SkipLeadingLabels(rr->resrec.name, 1); 7871 7872 // If question is for a sub type, just compare against the primary service type 7873 const domainname *primaryName = getPrimaryServiceName(&q->qname); 7874 7875 // 2. If the SRV or TXT record matches the service name, then cache it. If the TXT or SRV record is 7876 // before the PTR record in the packet, PTR record may not be in the cache yet and hence the logic 7877 // in (3) below will fail to cache it. 7878 if (q->qtype == kDNSType_PTR && name && SameDomainName(primaryName, name)) 7879 { 7880 LogInfo("ExpectingMulticastResponseForRecord: Accepting %s due to PTR match, question %##s from %#a, pktnum %d", 7881 CRDisplayString(m, rr), q->qname.c, srcaddr, m->PktNum); 7882 return mDNStrue; 7883 } 7884 7885 if (name) 7886 { 7887 const mDNSu32 slot = HashSlot(name); 7888 const mDNSu32 namehash = DomainNameHashValue(name); 7889 CacheGroup *cg = CacheGroupForName(m, slot, namehash, name); 7890 CacheRecord *cr; 7891 7892 // 3. Same as in (2), but look in the cache in case we don't have the PTR question. 7893 7894 for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next) 7895 { 7896 if (cr->resrec.rrtype == kDNSType_PTR) 7897 { 7898 primaryName = getPrimaryServiceName(cr->resrec.name); 7899 7900 if (SameDomainName(primaryName, name)) 7901 { 7902 LogInfo("ExpectingMulticastResponseForRecord: accepting %s, from %#a, pktnum %d", 7903 CRDisplayString(m, rr), srcaddr, m->PktNum); 7904 return mDNStrue; 7905 } 7906 } 7907 } 7908 } 7909 } 7910 } 7911 } 7912 debugf("ExpectingMulticastResponseForRecord: discarding %s, from %#a, pktnum %d", CRDisplayString(m, rr), srcaddr, m->PktNum); 7913 return(mDNSfalse); 7914 } 7915 7916 // Certain data types need more space for in-memory storage than their in-packet rdlength would imply 7917 // Currently this applies only to rdata types containing more than one domainname, 7918 // or types where the domainname is not the last item in the structure. 7919 mDNSlocal mDNSu16 GetRDLengthMem(const ResourceRecord *const rr) 7920 { 7921 switch (rr->rrtype) 7922 { 7923 case kDNSType_SOA: return sizeof(rdataSOA); 7924 case kDNSType_RP: return sizeof(rdataRP); 7925 case kDNSType_PX: return sizeof(rdataPX); 7926 default: return rr->rdlength; 7927 } 7928 } 7929 7930 mDNSexport CacheRecord *CreateNewCacheEntry(mDNS *const m, const mDNSu32 slot, CacheGroup *cg, mDNSs32 delay, mDNSBool Add, const mDNSAddr *sourceAddress) 7931 { 7932 CacheRecord *rr = mDNSNULL; 7933 mDNSu16 RDLength = GetRDLengthMem(&m->rec.r.resrec); 7934 7935 if (!m->rec.r.resrec.InterfaceID) debugf("CreateNewCacheEntry %s", CRDisplayString(m, &m->rec.r)); 7936 7937 //if (RDLength > InlineCacheRDSize) 7938 // LogInfo("Rdata len %4d > InlineCacheRDSize %d %s", RDLength, InlineCacheRDSize, CRDisplayString(m, &m->rec.r)); 7939 7940 if (!cg) cg = GetCacheGroup(m, slot, &m->rec.r.resrec); // If we don't have a CacheGroup for this name, make one now 7941 if (cg) rr = GetCacheRecord(m, cg, RDLength); // Make a cache record, being careful not to recycle cg 7942 if (!rr) NoCacheAnswer(m, &m->rec.r); 7943 else 7944 { 7945 RData *saveptr = rr->resrec.rdata; // Save the rr->resrec.rdata pointer 7946 *rr = m->rec.r; // Block copy the CacheRecord object 7947 rr->resrec.rdata = saveptr; // Restore rr->resrec.rdata after the structure assignment 7948 rr->resrec.name = cg->name; // And set rr->resrec.name to point into our CacheGroup header 7949 7950 // We need to add the anonymous info before we call CacheRecordAdd so that 7951 // if it finds a matching question with this record, it bumps up the counters like 7952 // CurrentAnswers etc. Otherwise, when a cache entry gets removed, CacheRecordRmv 7953 // will complain. 7954 if (m->rec.r.resrec.AnonInfo) 7955 { 7956 rr->resrec.AnonInfo = m->rec.r.resrec.AnonInfo; 7957 m->rec.r.resrec.AnonInfo = mDNSNULL; 7958 } 7959 rr->DelayDelivery = delay; 7960 7961 // If this is an oversized record with external storage allocated, copy rdata to external storage 7962 if (rr->resrec.rdata == (RData*)&rr->smallrdatastorage && RDLength > InlineCacheRDSize) 7963 LogMsg("rr->resrec.rdata == &rr->rdatastorage but length > InlineCacheRDSize %##s", m->rec.r.resrec.name->c); 7964 else if (rr->resrec.rdata != (RData*)&rr->smallrdatastorage && RDLength <= InlineCacheRDSize) 7965 LogMsg("rr->resrec.rdata != &rr->rdatastorage but length <= InlineCacheRDSize %##s", m->rec.r.resrec.name->c); 7966 if (RDLength > InlineCacheRDSize) 7967 mDNSPlatformMemCopy(rr->resrec.rdata, m->rec.r.resrec.rdata, sizeofRDataHeader + RDLength); 7968 7969 rr->next = mDNSNULL; // Clear 'next' pointer 7970 rr->nsec = mDNSNULL; 7971 rr->soa = mDNSNULL; 7972 7973 if (sourceAddress) 7974 rr->sourceAddress = *sourceAddress; 7975 7976 if (!rr->resrec.InterfaceID) 7977 { 7978 m->rrcache_totalused_unicast += rr->resrec.rdlength; 7979 if (DNSSECRecordType(rr->resrec.rrtype)) 7980 BumpDNSSECStats(m, kStatsActionIncrement, kStatsTypeMemoryUsage, rr->resrec.rdlength); 7981 } 7982 7983 if (Add) 7984 { 7985 *(cg->rrcache_tail) = rr; // Append this record to tail of cache slot list 7986 cg->rrcache_tail = &(rr->next); // Advance tail pointer 7987 CacheRecordAdd(m, rr); // CacheRecordAdd calls SetNextCacheCheckTimeForRecord(m, rr); for us 7988 } 7989 else 7990 { 7991 // Can't use the "cg->name" if we are not adding to the cache as the 7992 // CacheGroup may be released anytime if it is empty 7993 domainname *name = mDNSPlatformMemAllocate(DomainNameLength(cg->name)); 7994 if (name) 7995 { 7996 AssignDomainName(name, cg->name); 7997 rr->resrec.name = name; 7998 } 7999 else 8000 { 8001 ReleaseCacheRecord(m, rr); 8002 NoCacheAnswer(m, &m->rec.r); 8003 rr = mDNSNULL; 8004 } 8005 } 8006 } 8007 return(rr); 8008 } 8009 8010 mDNSlocal void RefreshCacheRecord(mDNS *const m, CacheRecord *rr, mDNSu32 ttl) 8011 { 8012 rr->TimeRcvd = m->timenow; 8013 rr->resrec.rroriginalttl = ttl; 8014 rr->UnansweredQueries = 0; 8015 #if ENABLE_MULTI_PACKET_QUERY_SNOOPING 8016 rr->MPUnansweredQ = 0; 8017 rr->MPUnansweredKA = 0; 8018 rr->MPExpectingKA = mDNSfalse; 8019 #endif 8020 SetNextCacheCheckTimeForRecord(m, rr); 8021 } 8022 8023 mDNSexport void GrantCacheExtensions(mDNS *const m, DNSQuestion *q, mDNSu32 lease) 8024 { 8025 CacheRecord *rr; 8026 const mDNSu32 slot = HashSlot(&q->qname); 8027 CacheGroup *cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); 8028 for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) 8029 if (rr->CRActiveQuestion == q) 8030 { 8031 //LogInfo("GrantCacheExtensions: new lease %d / %s", lease, CRDisplayString(m, rr)); 8032 RefreshCacheRecord(m, rr, lease); 8033 } 8034 } 8035 8036 mDNSlocal mDNSu32 GetEffectiveTTL(const uDNS_LLQType LLQType, mDNSu32 ttl) // TTL in seconds 8037 { 8038 if (LLQType == uDNS_LLQ_Entire) ttl = kLLQ_DefLease; 8039 else if (LLQType == uDNS_LLQ_Events) 8040 { 8041 // If the TTL is -1 for uDNS LLQ event packet, that means "remove" 8042 if (ttl == 0xFFFFFFFF) ttl = 0; 8043 else ttl = kLLQ_DefLease; 8044 } 8045 else // else not LLQ (standard uDNS response) 8046 { 8047 // The TTL is already capped to a maximum value in GetLargeResourceRecord, but just to be extra safe we 8048 // also do this check here to make sure we can't get overflow below when we add a quarter to the TTL 8049 if (ttl > 0x60000000UL / mDNSPlatformOneSecond) ttl = 0x60000000UL / mDNSPlatformOneSecond; 8050 8051 ttl = RRAdjustTTL(ttl); 8052 8053 // For mDNS, TTL zero means "delete this record" 8054 // For uDNS, TTL zero means: this data is true at this moment, but don't cache it. 8055 // For the sake of network efficiency, we impose a minimum effective TTL of 15 seconds. 8056 // This means that we'll do our 80, 85, 90, 95% queries at 12.00, 12.75, 13.50, 14.25 seconds 8057 // respectively, and then if we get no response, delete the record from the cache at 15 seconds. 8058 // This gives the server up to three seconds to respond between when we send our 80% query at 12 seconds 8059 // and when we delete the record at 15 seconds. Allowing cache lifetimes less than 15 seconds would 8060 // (with the current code) result in the server having even less than three seconds to respond 8061 // before we deleted the record and reported a "remove" event to any active questions. 8062 // Furthermore, with the current code, if we were to allow a TTL of less than 2 seconds 8063 // then things really break (e.g. we end up making a negative cache entry). 8064 // In the future we may want to revisit this and consider properly supporting non-cached (TTL=0) uDNS answers. 8065 if (ttl < 15) ttl = 15; 8066 } 8067 8068 return ttl; 8069 } 8070 8071 // When the response does not match the question directly, we still want to cache them sometimes. The current response is 8072 // in m->rec. 8073 mDNSlocal mDNSBool IsResponseAcceptable(mDNS *const m, const CacheRecord *crlist, DNSQuestion *q, mDNSBool *nseclist) 8074 { 8075 CacheRecord *const newcr = &m->rec.r; 8076 ResourceRecord *rr = &newcr->resrec; 8077 const CacheRecord *cr; 8078 8079 *nseclist = mDNSfalse; 8080 for (cr = crlist; cr != (CacheRecord*)1; cr = cr->NextInCFList) 8081 { 8082 domainname *target = GetRRDomainNameTarget(&cr->resrec); 8083 // When we issue a query for A record, the response might contain both a CNAME and A records. Only the CNAME would 8084 // match the question and we already created a cache entry in the previous pass of this loop. Now when we process 8085 // the A record, it does not match the question because the record name here is the CNAME. Hence we try to 8086 // match with the previous records to make it an AcceptableResponse. We have to be careful about setting the 8087 // DNSServer value that we got in the previous pass. This can happen for other record types like SRV also. 8088 8089 if (target && cr->resrec.rdatahash == rr->namehash && SameDomainName(target, rr->name)) 8090 { 8091 LogInfo("IsResponseAcceptable: Found a matching entry for %##s in the CacheFlushRecords %s", rr->name->c, CRDisplayString(m, cr)); 8092 return (mDNStrue); 8093 } 8094 } 8095 8096 // Either the question requires validation or we are validating a response with DNSSEC in which case 8097 // we need to accept the RRSIGs also so that we can validate the response. It is also possible that 8098 // we receive NSECs for our query which does not match the qname and we need to cache in that case 8099 // too. nseclist is set if they have to be cached as part of the negative cache record. 8100 if (q && DNSSECQuestion(q)) 8101 { 8102 mDNSBool same = SameDomainName(&q->qname, rr->name); 8103 if (same && (q->qtype == rr->rrtype || rr->rrtype == kDNSType_CNAME)) 8104 { 8105 LogInfo("IsResponseAcceptable: Accepting, same name and qtype %s, CR %s", DNSTypeName(q->qtype), 8106 CRDisplayString(m, newcr)); 8107 return mDNStrue; 8108 } 8109 // We cache RRSIGS if it covers the question type or NSEC. If it covers a NSEC, 8110 // "nseclist" is set 8111 if (rr->rrtype == kDNSType_RRSIG) 8112 { 8113 RDataBody2 *const rdb = (RDataBody2 *)newcr->smallrdatastorage.data; 8114 rdataRRSig *rrsig = &rdb->rrsig; 8115 mDNSu16 typeCovered = swap16(rrsig->typeCovered); 8116 8117 // Note the ordering. If we are looking up the NSEC record, then the RRSIG's typeCovered 8118 // would match the qtype and they are cached normally as they are not used to prove the 8119 // non-existence of any name. In that case, it is like any other normal dnssec validation 8120 // and hence nseclist should not be set. 8121 8122 if (same && ((typeCovered == q->qtype) || (typeCovered == kDNSType_CNAME))) 8123 { 8124 LogInfo("IsResponseAcceptable: Accepting RRSIG %s matches question type %s", CRDisplayString(m, newcr), 8125 DNSTypeName(q->qtype)); 8126 return mDNStrue; 8127 } 8128 else if (typeCovered == kDNSType_NSEC || typeCovered == kDNSType_NSEC3) 8129 { 8130 LogInfo("IsResponseAcceptable: Accepting RRSIG %s matches %s type (nseclist = 1)", CRDisplayString(m, newcr), DNSTypeName(typeCovered)); 8131 *nseclist = mDNStrue; 8132 return mDNStrue; 8133 } 8134 else if (typeCovered == kDNSType_SOA) 8135 { 8136 LogInfo("IsResponseAcceptable: Accepting RRSIG %s matches SOA type (nseclist = 1)", CRDisplayString(m, newcr)); 8137 *nseclist = mDNStrue; 8138 return mDNStrue; 8139 } 8140 else return mDNSfalse; 8141 } 8142 if (rr->rrtype == kDNSType_NSEC) 8143 { 8144 if (!UNICAST_NSEC(rr)) 8145 { 8146 LogMsg("IsResponseAcceptable: ERROR!! Not a unicast NSEC %s", CRDisplayString(m, newcr)); 8147 return mDNSfalse; 8148 } 8149 LogInfo("IsResponseAcceptable: Accepting NSEC %s (nseclist = 1)", CRDisplayString(m, newcr)); 8150 *nseclist = mDNStrue; 8151 return mDNStrue; 8152 } 8153 if (rr->rrtype == kDNSType_SOA) 8154 { 8155 LogInfo("IsResponseAcceptable: Accepting SOA %s (nseclist = 1)", CRDisplayString(m, newcr)); 8156 *nseclist = mDNStrue; 8157 return mDNStrue; 8158 } 8159 else if (rr->rrtype == kDNSType_NSEC3) 8160 { 8161 LogInfo("IsResponseAcceptable: Accepting NSEC3 %s (nseclist = 1)", CRDisplayString(m, newcr)); 8162 *nseclist = mDNStrue; 8163 return mDNStrue; 8164 } 8165 } 8166 return mDNSfalse; 8167 } 8168 8169 mDNSlocal void FreeNSECRecords(mDNS *const m, CacheRecord *NSECRecords) 8170 { 8171 CacheRecord *rp, *next; 8172 8173 for (rp = NSECRecords; rp; rp = next) 8174 { 8175 next = rp->next; 8176 ReleaseCacheRecord(m, rp); 8177 } 8178 } 8179 8180 // If we received zero DNSSEC records even when the DO/EDNS0 bit was set, we need to provide this 8181 // information to ValidatingResponse question to indicate the DNSSEC status to the application 8182 mDNSlocal void mDNSCoreReceiveNoDNSSECAnswers(mDNS *const m, const DNSMessage *const response, const mDNSu8 *end, const mDNSAddr *dstaddr, 8183 mDNSIPPort dstport, const mDNSInterfaceID InterfaceID) 8184 { 8185 int i; 8186 const mDNSu8 *ptr = response->data; 8187 8188 for (i = 0; i < response->h.numQuestions && ptr && ptr < end; i++) 8189 { 8190 DNSQuestion pktq; 8191 DNSQuestion *qptr = mDNSNULL; 8192 ptr = getQuestion(response, ptr, end, InterfaceID, &pktq); 8193 if (ptr && (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &pktq, !dstaddr)) && 8194 qptr->ValidatingResponse) 8195 { 8196 DNSQuestion *next, *q; 8197 8198 if (qptr->DuplicateOf) 8199 LogMsg("mDNSCoreReceiveNoDNSSECAnswers: ERROR!! qptr %##s (%s) Duplicate question matching response", qptr->qname.c, DNSTypeName(qptr->qtype)); 8200 8201 // Be careful to call the callback for duplicate questions first and then the original 8202 // question. If we called the callback on the original question, it could stop and 8203 // a duplicate question would become the original question. 8204 mDNS_DropLockBeforeCallback(); // Allow client (and us) to legally make mDNS API calls 8205 for (q = qptr->next ; q && q != m->NewQuestions; q = next) 8206 { 8207 next = q->next; 8208 if (q->DuplicateOf == qptr) 8209 { 8210 if (q->ValidatingResponse) 8211 LogInfo("mDNSCoreReceiveNoDNSSECAnswers: qptr %##s (%s) Duplicate question found", q->qname.c, DNSTypeName(q->qtype)); 8212 else 8213 LogMsg("mDNSCoreReceiveNoDNSSECAnswers: ERROR!! qptr %##s (%s) Duplicate question not ValidatingResponse", q->qname.c, DNSTypeName(q->qtype)); 8214 if (q->QuestionCallback) 8215 q->QuestionCallback(m, q, mDNSNULL, QC_nodnssec); 8216 } 8217 } 8218 if (qptr->QuestionCallback) 8219 qptr->QuestionCallback(m, qptr, mDNSNULL, QC_nodnssec); 8220 mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again 8221 } 8222 } 8223 } 8224 8225 mDNSlocal void mDNSCoreReceiveNoUnicastAnswers(mDNS *const m, const DNSMessage *const response, const mDNSu8 *end, const mDNSAddr *dstaddr, 8226 mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, uDNS_LLQType LLQType, mDNSu8 rcode, CacheRecord *NSECRecords) 8227 { 8228 int i; 8229 const mDNSu8 *ptr = response->data; 8230 CacheRecord *SOARecord = mDNSNULL; 8231 8232 for (i = 0; i < response->h.numQuestions && ptr && ptr < end; i++) 8233 { 8234 DNSQuestion q; 8235 DNSQuestion *qptr = mDNSNULL; 8236 ptr = getQuestion(response, ptr, end, InterfaceID, &q); 8237 if (ptr && (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q, !dstaddr))) 8238 { 8239 CacheRecord *rr, *neg = mDNSNULL; 8240 mDNSu32 slot = HashSlot(&q.qname); 8241 CacheGroup *cg = CacheGroupForName(m, slot, q.qnamehash, &q.qname); 8242 for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) 8243 if (SameNameRecordAnswersQuestion(&rr->resrec, qptr)) 8244 { 8245 // 1. If we got a fresh answer to this query, then don't need to generate a negative entry 8246 if (RRExpireTime(rr) - m->timenow > 0) break; 8247 // 2. If we already had a negative entry, keep track of it so we can resurrect it instead of creating a new one 8248 if (rr->resrec.RecordType == kDNSRecordTypePacketNegative) neg = rr; 8249 } 8250 // When we're doing parallel unicast and multicast queries for dot-local names (for supporting Microsoft 8251 // Active Directory sites) we don't want to waste memory making negative cache entries for all the unicast answers. 8252 // Otherwise we just fill up our cache with negative entries for just about every single multicast name we ever look up 8253 // (since the Microsoft Active Directory server is going to assert that pretty much every single multicast name doesn't exist). 8254 // This is not only a waste of memory, but there's also the problem of those negative entries confusing us later -- e.g. we 8255 // suppress sending our mDNS query packet because we think we already have a valid (negative) answer to that query in our cache. 8256 // The one exception is that we *DO* want to make a negative cache entry for "local. SOA", for the (common) case where we're 8257 // *not* on a Microsoft Active Directory network, and there is no authoritative server for "local". Note that this is not 8258 // in conflict with the mDNS spec, because that spec says, "Multicast DNS Zones have no SOA record," so it's okay to cache 8259 // negative answers for "local. SOA" from a uDNS server, because the mDNS spec already says that such records do not exist :-) 8260 // 8261 // By suppressing negative responses, it might take longer to timeout a .local question as it might be expecting a 8262 // response e.g., we deliver a positive "A" response and suppress negative "AAAA" response and the upper layer may 8263 // be waiting longer to get the AAAA response before returning the "A" response to the application. To handle this 8264 // case without creating the negative cache entries, we generate a negative response and let the layer above us 8265 // do the appropriate thing. This negative response is also needed for appending new search domains. 8266 if (!InterfaceID && q.qtype != kDNSType_SOA && IsLocalDomain(&q.qname)) 8267 { 8268 if (!rr) 8269 { 8270 LogInfo("mDNSCoreReceiveNoUnicastAnswers: Generate negative response for %##s (%s)", q.qname.c, DNSTypeName(q.qtype)); 8271 m->CurrentQuestion = qptr; 8272 // We are not creating a cache record in this case, we need to pass back 8273 // the error we got so that the proxy code can return the right one to 8274 // the application 8275 if (qptr->ProxyQuestion) 8276 qptr->responseFlags = response->h.flags; 8277 GenerateNegativeResponse(m, QC_forceresponse); 8278 m->CurrentQuestion = mDNSNULL; 8279 } 8280 else 8281 { 8282 LogInfo("mDNSCoreReceiveNoUnicastAnswers: Skipping check and not creating a negative cache entry for %##s (%s)", q.qname.c, DNSTypeName(q.qtype)); 8283 } 8284 } 8285 else 8286 { 8287 if (!rr) 8288 { 8289 // We start off assuming a negative caching TTL of 60 seconds 8290 // but then look to see if we can find an SOA authority record to tell us a better value we should be using 8291 mDNSu32 negttl = 60; 8292 int repeat = 0; 8293 const domainname *name = &q.qname; 8294 mDNSu32 hash = q.qnamehash; 8295 8296 // Special case for our special Microsoft Active Directory "local SOA" check. 8297 // Some cheap home gateways don't include an SOA record in the authority section when 8298 // they send negative responses, so we don't know how long to cache the negative result. 8299 // Because we don't want to keep hitting the root name servers with our query to find 8300 // if we're on a network using Microsoft Active Directory using "local" as a private 8301 // internal top-level domain, we make sure to cache the negative result for at least one day. 8302 if (q.qtype == kDNSType_SOA && SameDomainName(&q.qname, &localdomain)) negttl = 60 * 60 * 24; 8303 8304 // If we're going to make (or update) a negative entry, then look for the appropriate TTL from the SOA record 8305 if (response->h.numAuthorities && (ptr = LocateAuthorities(response, end)) != mDNSNULL) 8306 { 8307 ptr = GetLargeResourceRecord(m, response, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &m->rec); 8308 if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && m->rec.r.resrec.rrtype == kDNSType_SOA) 8309 { 8310 const mDNSu32 s = HashSlot(m->rec.r.resrec.name); 8311 CacheGroup *cgSOA = CacheGroupForRecord(m, s, &m->rec.r.resrec); 8312 const rdataSOA *const soa = (const rdataSOA *)m->rec.r.resrec.rdata->u.data; 8313 mDNSu32 ttl_s = soa->min; 8314 // We use the lesser of the SOA.MIN field and the SOA record's TTL, *except* 8315 // for the SOA record for ".", where the record is reported as non-cacheable 8316 // (TTL zero) for some reason, so in this case we just take the SOA record's TTL as-is 8317 if (ttl_s > m->rec.r.resrec.rroriginalttl && m->rec.r.resrec.name->c[0]) 8318 ttl_s = m->rec.r.resrec.rroriginalttl; 8319 if (negttl < ttl_s) negttl = ttl_s; 8320 8321 // Create the SOA record as we may have to return this to the questions 8322 // that we are acting as a proxy for currently or in the future. 8323 SOARecord = CreateNewCacheEntry(m, s, cgSOA, 1, mDNSfalse, mDNSNULL); 8324 8325 // Special check for SOA queries: If we queried for a.b.c.d.com, and got no answer, 8326 // with an Authority Section SOA record for d.com, then this is a hint that the authority 8327 // is d.com, and consequently SOA records b.c.d.com and c.d.com don't exist either. 8328 // To do this we set the repeat count so the while loop below will make a series of negative cache entries for us 8329 // 8330 // For ProxyQuestions, we don't do this as we need to create additional SOA records to cache them 8331 // along with the negative cache record. For simplicity, we don't create the additional records. 8332 if (!qptr->ProxyQuestion && q.qtype == kDNSType_SOA) 8333 { 8334 int qcount = CountLabels(&q.qname); 8335 int scount = CountLabels(m->rec.r.resrec.name); 8336 if (qcount - 1 > scount) 8337 if (SameDomainName(SkipLeadingLabels(&q.qname, qcount - scount), m->rec.r.resrec.name)) 8338 repeat = qcount - 1 - scount; 8339 } 8340 } 8341 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 8342 } 8343 8344 // If we already had a negative entry in the cache, then we double our existing negative TTL. This is to avoid 8345 // the case where the record doesn't exist (e.g. particularly for things like our lb._dns-sd._udp.<domain> query), 8346 // and the server returns no SOA record (or an SOA record with a small MIN TTL) so we assume a TTL 8347 // of 60 seconds, and we end up polling the server every minute for a record that doesn't exist. 8348 // With this fix in place, when this happens, we double the effective TTL each time (up to one hour), 8349 // so that we back off our polling rate and don't keep hitting the server continually. 8350 if (neg) 8351 { 8352 if (negttl < neg->resrec.rroriginalttl * 2) 8353 negttl = neg->resrec.rroriginalttl * 2; 8354 if (negttl > 3600) 8355 negttl = 3600; 8356 } 8357 8358 negttl = GetEffectiveTTL(LLQType, negttl); // Add 25% grace period if necessary 8359 8360 // If we already had a negative cache entry just update it, else make one or more new negative cache entries. 8361 if (neg) 8362 { 8363 LogInfo("mDNSCoreReceiveNoUnicastAnswers: Renewing negative TTL from %d to %d %s", neg->resrec.rroriginalttl, negttl, CRDisplayString(m, neg)); 8364 RefreshCacheRecord(m, neg, negttl); 8365 // When we created the cache for the first time and answered the question, the question's 8366 // interval was set to MaxQuestionInterval. If the cache is about to expire and we are resending 8367 // the queries, the interval should still be at MaxQuestionInterval. If the query is being 8368 // restarted (setting it to InitialQuestionInterval) for other reasons e.g., wakeup, 8369 // we should reset its question interval here to MaxQuestionInterval. 8370 ResetQuestionState(m, qptr); 8371 if (DNSSECQuestion(qptr)) 8372 neg->CRDNSSECQuestion = 1; 8373 // Update the NSEC records again. 8374 // TBD: Need to purge and revalidate if the cached NSECS and the new set are not same. 8375 if (NSECRecords) 8376 { 8377 if (!AddNSECSForCacheRecord(m, NSECRecords, neg, rcode)) 8378 { 8379 // We might just have an SOA record for zones that are not signed and hence don't log 8380 // this as an error 8381 LogInfo("mDNSCoreReceiveNoUnicastAnswers: AddNSECSForCacheRecord failed to add NSEC for negcr %s during refresh", CRDisplayString(m, neg)); 8382 FreeNSECRecords(m, NSECRecords); 8383 neg->CRDNSSECQuestion = 0; 8384 } 8385 NSECRecords = mDNSNULL; 8386 } 8387 if (SOARecord) 8388 { 8389 if (neg->soa) 8390 ReleaseCacheRecord(m, neg->soa); 8391 neg->soa = SOARecord; 8392 SOARecord = mDNSNULL; 8393 } 8394 } 8395 else while (1) 8396 { 8397 CacheRecord *negcr; 8398 debugf("mDNSCoreReceiveNoUnicastAnswers making negative cache entry TTL %d for %##s (%s)", negttl, name->c, DNSTypeName(q.qtype)); 8399 MakeNegativeCacheRecord(m, &m->rec.r, name, hash, q.qtype, q.qclass, negttl, mDNSInterface_Any, qptr->qDNSServer); 8400 m->rec.r.responseFlags = response->h.flags; 8401 // We create SOA records above which might create new cache groups. Earlier 8402 // in the function we looked up the cache group for the name and it could have 8403 // been NULL. If we pass NULL cg to new cache entries that we create below, 8404 // it will create additional cache groups for the same name. To avoid that, 8405 // look up the cache group again to re-initialize cg again. 8406 cg = CacheGroupForName(m, slot, hash, name); 8407 if (NSECRecords && DNSSECQuestion(qptr)) 8408 { 8409 // Create the cache entry with delay and then add the NSEC records 8410 // to it and add it immediately. 8411 negcr = CreateNewCacheEntry(m, slot, cg, 1, mDNStrue, mDNSNULL); 8412 if (negcr) 8413 { 8414 negcr->CRDNSSECQuestion = 0; 8415 if (!AddNSECSForCacheRecord(m, NSECRecords, negcr, rcode)) 8416 { 8417 LogInfo("mDNSCoreReceiveNoUnicastAnswers: AddNSECSForCacheRecord failed to add NSEC for negcr %s", 8418 CRDisplayString(m, negcr)); 8419 FreeNSECRecords(m, NSECRecords); 8420 } 8421 else 8422 { 8423 negcr->CRDNSSECQuestion = 1; 8424 LogInfo("mDNSCoreReceiveNoUnicastAnswers: AddNSECSForCacheRecord added neg NSEC for %s", CRDisplayString(m, negcr)); 8425 } 8426 NSECRecords = mDNSNULL; 8427 negcr->DelayDelivery = 0; 8428 CacheRecordDeferredAdd(m, negcr); 8429 } 8430 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 8431 break; 8432 } 8433 else 8434 { 8435 // Need to add with a delay so that we can tag the SOA record 8436 negcr = CreateNewCacheEntry(m, slot, cg, 1, mDNStrue, mDNSNULL); 8437 if (negcr) 8438 { 8439 negcr->CRDNSSECQuestion = 0; 8440 if (DNSSECQuestion(qptr)) 8441 negcr->CRDNSSECQuestion = 1; 8442 negcr->DelayDelivery = 0; 8443 8444 if (SOARecord) 8445 { 8446 if (negcr->soa) 8447 ReleaseCacheRecord(m, negcr->soa); 8448 negcr->soa = SOARecord; 8449 SOARecord = mDNSNULL; 8450 } 8451 CacheRecordDeferredAdd(m, negcr); 8452 } 8453 } 8454 m->rec.r.responseFlags = zeroID; 8455 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 8456 if (!repeat) break; 8457 repeat--; 8458 name = (const domainname *)(name->c + 1 + name->c[0]); 8459 hash = DomainNameHashValue(name); 8460 slot = HashSlot(name); 8461 cg = CacheGroupForName(m, slot, hash, name); 8462 } 8463 } 8464 } 8465 } 8466 } 8467 if (NSECRecords) { LogInfo("mDNSCoreReceiveNoUnicastAnswers: NSECRecords not used"); FreeNSECRecords(m, NSECRecords); } 8468 if (SOARecord) { LogInfo("mDNSCoreReceiveNoUnicastAnswers: SOARecord not used"); ReleaseCacheRecord(m, SOARecord); } 8469 } 8470 8471 mDNSlocal void mDNSCorePrintStoredProxyRecords(mDNS *const m) 8472 { 8473 AuthRecord *rrPtr = mDNSNULL; 8474 LogSPS("Stored Proxy records :"); 8475 for (rrPtr = m->SPSRRSet; rrPtr; rrPtr = rrPtr->next) 8476 { 8477 LogSPS("%s", ARDisplayString(m, rrPtr)); 8478 } 8479 } 8480 8481 mDNSlocal mDNSBool mDNSCoreRegisteredProxyRecord(mDNS *const m, AuthRecord *rr) 8482 { 8483 AuthRecord *rrPtr = mDNSNULL; 8484 8485 for (rrPtr = m->SPSRRSet; rrPtr; rrPtr = rrPtr->next) 8486 { 8487 if (IdenticalResourceRecord(&rrPtr->resrec, &rr->resrec)) 8488 { 8489 LogSPS("mDNSCoreRegisteredProxyRecord: Ignoring packet registered with sleep proxy : %s ", ARDisplayString(m, rr)); 8490 return mDNStrue; 8491 } 8492 } 8493 mDNSCorePrintStoredProxyRecords(m); 8494 return mDNSfalse; 8495 } 8496 8497 mDNSlocal CacheRecord* mDNSCoreReceiveCacheCheck(mDNS *const m, const DNSMessage *const response, uDNS_LLQType LLQType, 8498 const mDNSu32 slot, CacheGroup *cg, DNSQuestion *unicastQuestion, CacheRecord ***cfp, CacheRecord **NSECCachePtr, 8499 mDNSInterfaceID InterfaceID) 8500 { 8501 CacheRecord *rr; 8502 CacheRecord **cflocal = *cfp; 8503 8504 for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) 8505 { 8506 mDNSBool match; 8507 // Resource record received via unicast, the resGroupID should match ? 8508 if (!InterfaceID) 8509 { 8510 mDNSu16 id1 = (rr->resrec.rDNSServer ? rr->resrec.rDNSServer->resGroupID : 0); 8511 mDNSu16 id2 = (m->rec.r.resrec.rDNSServer ? m->rec.r.resrec.rDNSServer->resGroupID : 0); 8512 match = (id1 == id2); 8513 } 8514 else 8515 match = (rr->resrec.InterfaceID == InterfaceID); 8516 // If we found this exact resource record, refresh its TTL 8517 if (match && IdenticalSameNameRecord(&m->rec.r.resrec, &rr->resrec)) 8518 { 8519 if (m->rec.r.resrec.rdlength > InlineCacheRDSize) 8520 verbosedebugf("mDNSCoreReceiveCacheCheck: Found record size %5d interface %p already in cache: %s", 8521 m->rec.r.resrec.rdlength, InterfaceID, CRDisplayString(m, &m->rec.r)); 8522 8523 if (m->rec.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask) 8524 { 8525 // If this packet record has the kDNSClass_UniqueRRSet flag set, then add it to our cache flushing list 8526 if (rr->NextInCFList == mDNSNULL && *cfp != &rr->NextInCFList && LLQType != uDNS_LLQ_Events) 8527 { 8528 *cflocal = rr; 8529 cflocal = &rr->NextInCFList; 8530 *cflocal = (CacheRecord*)1; 8531 *cfp = &rr->NextInCFList; 8532 } 8533 8534 // If this packet record is marked unique, and our previous cached copy was not, then fix it 8535 if (!(rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask)) 8536 { 8537 DNSQuestion *q; 8538 for (q = m->Questions; q; q=q->next) 8539 { 8540 if (ResourceRecordAnswersQuestion(&rr->resrec, q)) 8541 q->UniqueAnswers++; 8542 } 8543 rr->resrec.RecordType = m->rec.r.resrec.RecordType; 8544 } 8545 } 8546 8547 if (!SameRDataBody(&m->rec.r.resrec, &rr->resrec.rdata->u, SameDomainNameCS)) 8548 { 8549 // If the rdata of the packet record differs in name capitalization from the record in our cache 8550 // then mDNSPlatformMemSame will detect this. In this case, throw the old record away, so that clients get 8551 // a 'remove' event for the record with the old capitalization, and then an 'add' event for the new one. 8552 // <rdar://problem/4015377> mDNS -F returns the same domain multiple times with different casing 8553 rr->resrec.rroriginalttl = 0; 8554 rr->TimeRcvd = m->timenow; 8555 rr->UnansweredQueries = MaxUnansweredQueries; 8556 SetNextCacheCheckTimeForRecord(m, rr); 8557 LogInfo("mDNSCoreReceiveCacheCheck: Discarding due to domainname case change old: %s", CRDisplayString(m, rr)); 8558 LogInfo("mDNSCoreReceiveCacheCheck: Discarding due to domainname case change new: %s", CRDisplayString(m, &m->rec.r)); 8559 LogInfo("mDNSCoreReceiveCacheCheck: Discarding due to domainname case change in %d slot %3d in %d %d", 8560 NextCacheCheckEvent(rr) - m->timenow, slot, m->rrcache_nextcheck[slot] - m->timenow, m->NextCacheCheck - m->timenow); 8561 // DO NOT break out here -- we want to continue as if we never found it 8562 } 8563 else if (!IdenticalAnonInfo(m->rec.r.resrec.AnonInfo, rr->resrec.AnonInfo)) 8564 { 8565 // If the NSEC3 record changed, a few possibilities 8566 // 8567 // 1) the peer reinitialized e.g., after network change and still part of the 8568 // same set. 8569 // 2) the peer went to a different set but we did not see the goodbyes. If we just 8570 // update the nsec3 record, it would be incorrect. Flush the cache so that we 8571 // can deliver a RMV followed by ADD. 8572 // 3) if the peer is ourselves and we see the goodbye when moving to a different set 8573 // and so we flush the cache and create a new cache record with the new set information. 8574 // Now we move back to the original set. In this case, we can't just update the 8575 // NSEC3 record alone. We need to flush so that we can deliver an RMV followed by ADD 8576 // when we create the new cache entry. 8577 // 8578 // Note: For case (1), we could avoid flushing the cache but we can't tell the difference 8579 // from the other cases. 8580 rr->resrec.rroriginalttl = 0; 8581 rr->TimeRcvd = m->timenow; 8582 rr->UnansweredQueries = MaxUnansweredQueries; 8583 SetNextCacheCheckTimeForRecord(m, rr); 8584 LogInfo("mDNSCoreReceiveCacheCheck: AnonInfo changed for %s", CRDisplayString(m, rr)); 8585 // DO NOT break out here -- we want to continue as if we never found it. When we return 8586 // from this function, we will create a new cache entry with the new NSEC3 record 8587 } 8588 else if (m->rec.r.resrec.rroriginalttl > 0) 8589 { 8590 DNSQuestion *q; 8591 8592 m->mDNSStats.CacheRefreshed++; 8593 8594 if (rr->resrec.rroriginalttl == 0) debugf("uDNS rescuing %s", CRDisplayString(m, rr)); 8595 RefreshCacheRecord(m, rr, m->rec.r.resrec.rroriginalttl); 8596 rr->responseFlags = response->h.flags; 8597 8598 // If we may have NSEC records returned with the answer (which we don't know yet as it 8599 // has not been processed), we need to cache them along with the first cache 8600 // record in the list that answers the question so that it can be used for validation 8601 // later. The "type" check below is to make sure that we cache on the cache record 8602 // that would answer the question. It is possible that we might cache additional things 8603 // e.g., MX question might cache A records also, and we want to cache the NSEC on 8604 // the record that answers the question. 8605 if (response->h.numAnswers && unicastQuestion && unicastQuestion->qtype == rr->resrec.rrtype 8606 && !(*NSECCachePtr)) 8607 { 8608 LogInfo("mDNSCoreReceiveCacheCheck: rescuing RR %s", CRDisplayString(m, rr)); 8609 *NSECCachePtr = rr; 8610 } 8611 // We have to reset the question interval to MaxQuestionInterval so that we don't keep 8612 // polling the network once we get a valid response back. For the first time when a new 8613 // cache entry is created, AnswerCurrentQuestionWithResourceRecord does that. 8614 // Subsequently, if we reissue questions from within the mDNSResponder e.g., DNS server 8615 // configuration changed, without flushing the cache, we reset the question interval here. 8616 // Currently, we do this for for both multicast and unicast questions as long as the record 8617 // type is unique. For unicast, resource record is always unique and for multicast it is 8618 // true for records like A etc. but not for PTR. 8619 if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) 8620 { 8621 for (q = m->Questions; q; q=q->next) 8622 { 8623 if (!q->DuplicateOf && !q->LongLived && 8624 ActiveQuestion(q) && ResourceRecordAnswersQuestion(&rr->resrec, q)) 8625 { 8626 ResetQuestionState(m, q); 8627 debugf("mDNSCoreReceiveCacheCheck: Set MaxQuestionInterval for %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype)); 8628 break; // Why break here? Aren't there other questions we might want to look at?-- SC July 2010 8629 } 8630 } 8631 } 8632 break; 8633 } 8634 else 8635 { 8636 8637 // If the packet TTL is zero, that means we're deleting this record. 8638 // To give other hosts on the network a chance to protest, we push the deletion 8639 // out one second into the future. Also, we set UnansweredQueries to MaxUnansweredQueries. 8640 // Otherwise, we'll do final queries for this record at 80% and 90% of its apparent 8641 // lifetime (800ms and 900ms from now) which is a pointless waste of network bandwidth. 8642 // If record's current expiry time is more than a second from now, we set it to expire in one second. 8643 // If the record is already going to expire in less than one second anyway, we leave it alone -- 8644 // we don't want to let the goodbye packet *extend* the record's lifetime in our cache. 8645 debugf("DE for %s", CRDisplayString(m, rr)); 8646 if (RRExpireTime(rr) - m->timenow > mDNSPlatformOneSecond) 8647 { 8648 rr->resrec.rroriginalttl = 1; 8649 rr->TimeRcvd = m->timenow; 8650 rr->UnansweredQueries = MaxUnansweredQueries; 8651 SetNextCacheCheckTimeForRecord(m, rr); 8652 } 8653 break; 8654 } 8655 } 8656 } 8657 return rr; 8658 } 8659 8660 mDNSlocal void mDNSParseNSEC3Records(mDNS *const m, const DNSMessage *const response, const mDNSu8 *end, 8661 const mDNSInterfaceID InterfaceID, CacheRecord **NSEC3Records) 8662 { 8663 const mDNSu8 *ptr = response->data; 8664 CacheRecord *rr; 8665 int i; 8666 8667 if (!response->h.numAuthorities) 8668 return; 8669 ptr = LocateAuthorities(response, end); 8670 if (!ptr) 8671 { 8672 LogInfo("mDNSParseNSEC3Records: ERROR can't locate authorities"); 8673 return; 8674 } 8675 for (i = 0; i < response->h.numAuthorities && ptr && ptr < end; i++) 8676 { 8677 mDNSu32 slot; 8678 CacheGroup *cg; 8679 8680 ptr = GetLargeResourceRecord(m, response, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &m->rec); 8681 if (!ptr || m->rec.r.resrec.RecordType == kDNSRecordTypePacketNegative || m->rec.r.resrec.rrtype != kDNSType_NSEC3) 8682 { 8683 debugf("mDNSParseNSEC3Records: ptr %p, Record %s, ignoring", ptr, CRDisplayString(m, &m->rec.r)); 8684 m->rec.r.resrec.RecordType = 0; 8685 continue; 8686 } 8687 slot = HashSlot(m->rec.r.resrec.name); 8688 cg = CacheGroupForRecord(m, slot, &m->rec.r.resrec); 8689 // Create the cache entry but don't add it to the cache it. We need 8690 // to cache this along with the main cache record. 8691 rr = CreateNewCacheEntry(m, slot, cg, 0, mDNSfalse, mDNSNULL); 8692 if (rr) 8693 { 8694 debugf("mDNSParseNSEC3Records: %s", CRDisplayString(m, rr)); 8695 *NSEC3Records = rr; 8696 NSEC3Records = &rr->next; 8697 } 8698 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 8699 } 8700 } 8701 8702 mDNSlocal void mDNSCoreResetRecord(mDNS *const m) 8703 { 8704 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 8705 if (m->rec.r.resrec.AnonInfo) 8706 { 8707 FreeAnonInfo(m->rec.r.resrec.AnonInfo); 8708 m->rec.r.resrec.AnonInfo = mDNSNULL; 8709 } 8710 } 8711 8712 #define DEVICE_INFO_RECORD_LABELS 4 8713 8714 // Determine if the record is an instance of _device-info._tcp.local. 8715 mDNSlocal mDNSBool IsDeviceInfoRecord(const domainname *d) 8716 { 8717 const domainname *afterInstance; 8718 8719 if (CountLabels(d) != DEVICE_INFO_RECORD_LABELS) 8720 return mDNSfalse; 8721 8722 // skip the instance name 8723 afterInstance = SkipLeadingLabels(d, 1); 8724 if (SameDomainName(afterInstance, &LocalDeviceInfoName)) 8725 return mDNStrue; 8726 8727 return mDNSfalse; 8728 } 8729 8730 // Note: mDNSCoreReceiveResponse calls mDNS_Deregister_internal which can call a user callback, which may change 8731 // the record list and/or question list. 8732 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this. 8733 // InterfaceID non-NULL tells us the interface this multicast response was received on 8734 // InterfaceID NULL tells us this was a unicast response 8735 // dstaddr NULL tells us we received this over an outgoing TCP connection we made 8736 mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, 8737 const DNSMessage *const response, const mDNSu8 *end, 8738 const mDNSAddr *srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, mDNSIPPort dstport, 8739 const mDNSInterfaceID InterfaceID) 8740 { 8741 int i; 8742 mDNSBool myself; 8743 mDNSBool ResponseMCast = dstaddr && mDNSAddrIsDNSMulticast(dstaddr); 8744 mDNSBool ResponseSrcLocal = !srcaddr || mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr, &myself); 8745 DNSQuestion *llqMatch = mDNSNULL; 8746 DNSQuestion *unicastQuestion = mDNSNULL; 8747 uDNS_LLQType LLQType = uDNS_recvLLQResponse(m, response, end, srcaddr, srcport, &llqMatch); 8748 8749 // "(CacheRecord*)1" is a special (non-zero) end-of-list marker 8750 // We use this non-zero marker so that records in our CacheFlushRecords list will always have NextInCFList 8751 // set non-zero, and that tells GetCacheEntity() that they're not, at this moment, eligible for recycling. 8752 CacheRecord *CacheFlushRecords = (CacheRecord*)1; 8753 CacheRecord **cfp = &CacheFlushRecords; 8754 CacheRecord *NSECRecords = mDNSNULL; 8755 CacheRecord *NSECCachePtr = mDNSNULL; 8756 CacheRecord **nsecp = &NSECRecords; 8757 CacheRecord *McastNSEC3Records = mDNSNULL; 8758 mDNSBool nseclist; 8759 mDNSu8 rcode = '\0'; 8760 mDNSBool rrsigsCreated = mDNSfalse; 8761 mDNSBool DNSSECQuestion = mDNSfalse; 8762 mDNSBool recordAccepted = mDNSfalse; 8763 NetworkInterfaceInfo *llintf = FirstIPv4LLInterfaceForID(m, InterfaceID); 8764 8765 // All records in a DNS response packet are treated as equally valid statements of truth. If we want 8766 // to guard against spoof responses, then the only credible protection against that is cryptographic 8767 // security, e.g. DNSSEC., not worring about which section in the spoof packet contained the record 8768 int firstauthority = response->h.numAnswers; 8769 int firstadditional = firstauthority + response->h.numAuthorities; 8770 int totalrecords = firstadditional + response->h.numAdditionals; 8771 const mDNSu8 *ptr = response->data; 8772 DNSServer *uDNSServer = mDNSNULL; 8773 8774 debugf("Received Response from %#-15a addressed to %#-15a on %p with " 8775 "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s %d bytes LLQType %d", 8776 srcaddr, dstaddr, InterfaceID, 8777 response->h.numQuestions, response->h.numQuestions == 1 ? ", " : "s,", 8778 response->h.numAnswers, response->h.numAnswers == 1 ? ", " : "s,", 8779 response->h.numAuthorities, response->h.numAuthorities == 1 ? "y, " : "ies,", 8780 response->h.numAdditionals, response->h.numAdditionals == 1 ? " " : "s", end - response->data, LLQType); 8781 8782 // According to RFC 2181 <http://www.ietf.org/rfc/rfc2181.txt> 8783 // When a DNS client receives a reply with TC 8784 // set, it should ignore that response, and query again, using a 8785 // mechanism, such as a TCP connection, that will permit larger replies. 8786 // It feels wrong to be throwing away data after the network went to all the trouble of delivering it to us, but 8787 // delivering some records of the RRSet first and then the remainder a couple of milliseconds later was causing 8788 // failures in our Microsoft Active Directory client, which expects to get the entire set of answers at once. 8789 // <rdar://problem/6690034> Can't bind to Active Directory 8790 // In addition, if the client immediately canceled its query after getting the initial partial response, then we'll 8791 // abort our TCP connection, and not complete the operation, and end up with an incomplete RRSet in our cache. 8792 // Next time there's a query for this RRSet we'll see answers in our cache, and assume we have the whole RRSet already, 8793 // and not even do the TCP query. 8794 // Accordingly, if we get a uDNS reply with kDNSFlag0_TC set, we bail out and wait for the TCP response containing the entire RRSet. 8795 if (!InterfaceID && (response->h.flags.b[0] & kDNSFlag0_TC)) return; 8796 8797 if (LLQType == uDNS_LLQ_Ignore) return; 8798 8799 // 1. We ignore questions (if any) in mDNS response packets 8800 // 2. If this is an LLQ response, we handle it much the same 8801 // 3. If we get a uDNS UDP response with the TC (truncated) bit set, then we can't treat this 8802 // answer as being the authoritative complete RRSet, and respond by deleting all other 8803 // matching cache records that don't appear in this packet. 8804 // Otherwise, this is a authoritative uDNS answer, so arrange for any stale records to be purged 8805 if (ResponseMCast || LLQType == uDNS_LLQ_Events || (response->h.flags.b[0] & kDNSFlag0_TC)) 8806 ptr = LocateAnswers(response, end); 8807 // Otherwise, for one-shot queries, any answers in our cache that are not also contained 8808 // in this response packet are immediately deemed to be invalid. 8809 else 8810 { 8811 mDNSBool failure, returnEarly; 8812 rcode = (mDNSu8)(response->h.flags.b[1] & kDNSFlag1_RC_Mask); 8813 failure = !(rcode == kDNSFlag1_RC_NoErr || rcode == kDNSFlag1_RC_NXDomain || rcode == kDNSFlag1_RC_NotAuth); 8814 returnEarly = mDNSfalse; 8815 // We could possibly combine this with the similar loop at the end of this function -- 8816 // instead of tagging cache records here and then rescuing them if we find them in the answer section, 8817 // we could instead use the "m->PktNum" mechanism to tag each cache record with the packet number in 8818 // which it was received (or refreshed), and then at the end if we find any cache records which 8819 // answer questions in this packet's question section, but which aren't tagged with this packet's 8820 // packet number, then we deduce they are old and delete them 8821 for (i = 0; i < response->h.numQuestions && ptr && ptr < end; i++) 8822 { 8823 DNSQuestion q, *qptr = mDNSNULL; 8824 ptr = getQuestion(response, ptr, end, InterfaceID, &q); 8825 if (ptr && (qptr = ExpectingUnicastResponseForQuestion(m, dstport, response->h.id, &q, !dstaddr))) 8826 { 8827 if (!failure) 8828 { 8829 CacheRecord *rr; 8830 // Remember the unicast question that we found, which we use to make caching 8831 // decisions later on in this function 8832 const mDNSu32 slot = HashSlot(&q.qname); 8833 CacheGroup *cg = CacheGroupForName(m, slot, q.qnamehash, &q.qname); 8834 if (!mDNSOpaque16IsZero(response->h.id)) 8835 { 8836 unicastQuestion = qptr; 8837 if (qptr->qDNSServer && DNSSECQuestion(qptr)) 8838 { 8839 LogInfo("mDNSCoreReceiveResponse: Setting aware for %##s (%s) on %#a", qptr->qname.c, 8840 DNSTypeName(qptr->qtype), &qptr->qDNSServer->addr); 8841 qptr->qDNSServer->DNSSECAware = mDNStrue; 8842 qptr->qDNSServer->req_DO = mDNStrue; 8843 } 8844 if (qptr->ValidatingResponse) 8845 DNSSECQuestion = mDNStrue; 8846 } 8847 for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) 8848 if (SameNameRecordAnswersQuestion(&rr->resrec, qptr)) 8849 { 8850 debugf("uDNS marking %p %##s (%s) %p %s", q.InterfaceID, q.qname.c, DNSTypeName(q.qtype), 8851 rr->resrec.InterfaceID, CRDisplayString(m, rr)); 8852 // Don't want to disturb rroriginalttl here, because code below might need it for the exponential backoff doubling algorithm 8853 rr->TimeRcvd = m->timenow - TicksTTL(rr) - 1; 8854 rr->UnansweredQueries = MaxUnansweredQueries; 8855 rr->CRDNSSECQuestion = 0; 8856 if (unicastQuestion && DNSSECQuestion(unicastQuestion)) 8857 { 8858 LogInfo("mDNSCoreReceiveResponse: CRDNSSECQuestion set for record %s, question %##s (%s)", CRDisplayString(m, rr), 8859 unicastQuestion->qname.c, DNSTypeName(unicastQuestion->qtype)); 8860 rr->CRDNSSECQuestion = 1; 8861 } 8862 } 8863 } 8864 else 8865 { 8866 if (qptr) 8867 { 8868 // If we recv any error from the DNSServer for a DNSSEC Query and if we know that the server 8869 // is not DNSSEC aware, stop doing DNSSEC for that DNSServer. Note that by setting the 8870 // req_DO to false here, the next retransmission for this question will turn off validation 8871 // and hence retransmit without the EDNS0/DOK option. 8872 if (DNSSECOptionalQuestion(qptr) && qptr->qDNSServer && !qptr->qDNSServer->DNSSECAware) 8873 { 8874 LogInfo("mDNSCoreReceiveResponse: Server %p responded with code %d to DNSSEC Query %##s (%s), clear DO flag", 8875 qptr->qDNSServer, rcode, q.qname.c, DNSTypeName(q.qtype)); 8876 qptr->qDNSServer->req_DO = mDNSfalse; 8877 } 8878 // For Unicast DNS Queries, penalize the DNSServer 8879 else 8880 { 8881 LogInfo("mDNSCoreReceiveResponse: Server %p responded with code %d to query %##s (%s)", 8882 qptr->qDNSServer, rcode, q.qname.c, DNSTypeName(q.qtype)); 8883 PenalizeDNSServer(m, qptr, response->h.flags); 8884 } 8885 } 8886 returnEarly = mDNStrue; 8887 } 8888 } 8889 } 8890 if (returnEarly) 8891 { 8892 LogInfo("Ignoring %2d Answer%s %2d Authorit%s %2d Additional%s", 8893 response->h.numAnswers, response->h.numAnswers == 1 ? ", " : "s,", 8894 response->h.numAuthorities, response->h.numAuthorities == 1 ? "y, " : "ies,", 8895 response->h.numAdditionals, response->h.numAdditionals == 1 ? "" : "s"); 8896 // not goto exit because we won't have any CacheFlushRecords and we do not want to 8897 // generate negative cache entries (we want to query the next server) 8898 return; 8899 } 8900 if (unicastQuestion && DNSSECQuestion(unicastQuestion)) 8901 { 8902 BumpDNSSECStats(m, kStatsActionSet, kStatsTypeMsgSize, (end - response->data)); 8903 } 8904 } 8905 8906 // Parse the NSEC3 records from the Authority section before we process 8907 // the Answer section so that we can cache them along with the proper 8908 // cache records we create. 8909 if (mDNSOpaque16IsZero(response->h.id)) 8910 mDNSParseNSEC3Records(m, response, end, InterfaceID, &McastNSEC3Records); 8911 8912 for (i = 0; i < totalrecords && ptr && ptr < end; i++) 8913 { 8914 // All responses sent via LL multicast are acceptable for caching 8915 // All responses received over our outbound TCP connections are acceptable for caching 8916 mDNSBool AcceptableResponse = ResponseMCast || !dstaddr || LLQType; 8917 // (Note that just because we are willing to cache something, that doesn't necessarily make it a trustworthy answer 8918 // to any specific question -- any code reading records from the cache needs to make that determination for itself.) 8919 8920 const mDNSu8 RecordType = 8921 (i < firstauthority ) ? (mDNSu8)kDNSRecordTypePacketAns : 8922 (i < firstadditional) ? (mDNSu8)kDNSRecordTypePacketAuth : (mDNSu8)kDNSRecordTypePacketAdd; 8923 ptr = GetLargeResourceRecord(m, response, ptr, end, InterfaceID, RecordType, &m->rec); 8924 if (!ptr) goto exit; // Break out of the loop and clean up our CacheFlushRecords list before exiting 8925 8926 if (m->rec.r.resrec.RecordType == kDNSRecordTypePacketNegative) 8927 { 8928 mDNSCoreResetRecord(m); 8929 continue; 8930 } 8931 8932 // We have already parsed the NSEC3 records and cached them approrpriately for 8933 // multicast responses. 8934 if (mDNSOpaque16IsZero(response->h.id) && m->rec.r.resrec.rrtype == kDNSType_NSEC3) 8935 { 8936 mDNSCoreResetRecord(m); 8937 continue; 8938 } 8939 // Don't want to cache OPT or TSIG pseudo-RRs 8940 if (m->rec.r.resrec.rrtype == kDNSType_TSIG) 8941 { 8942 mDNSCoreResetRecord(m); 8943 continue; 8944 } 8945 if (m->rec.r.resrec.rrtype == kDNSType_OPT) 8946 { 8947 const rdataOPT *opt; 8948 const rdataOPT *const e = (const rdataOPT *)&m->rec.r.resrec.rdata->u.data[m->rec.r.resrec.rdlength]; 8949 // Find owner sub-option(s). We verify that the MAC is non-zero, otherwise we could inadvertently 8950 // delete all our own AuthRecords (which are identified by having zero MAC tags on them). 8951 for (opt = &m->rec.r.resrec.rdata->u.opt[0]; opt < e; opt++) 8952 if (opt->opt == kDNSOpt_Owner && opt->u.owner.vers == 0 && opt->u.owner.HMAC.l[0]) 8953 { 8954 ClearProxyRecords(m, &opt->u.owner, m->DuplicateRecords); 8955 ClearProxyRecords(m, &opt->u.owner, m->ResourceRecords); 8956 } 8957 mDNSCoreResetRecord(m); 8958 continue; 8959 } 8960 // if a CNAME record points to itself, then don't add it to the cache 8961 if ((m->rec.r.resrec.rrtype == kDNSType_CNAME) && SameDomainName(m->rec.r.resrec.name, &m->rec.r.resrec.rdata->u.name)) 8962 { 8963 LogInfo("mDNSCoreReceiveResponse: CNAME loop domain name %##s", m->rec.r.resrec.name->c); 8964 mDNSCoreResetRecord(m); 8965 continue; 8966 } 8967 8968 // When we receive uDNS LLQ responses, we assume a long cache lifetime -- 8969 // In the case of active LLQs, we'll get remove events when the records actually do go away 8970 // In the case of polling LLQs, we assume the record remains valid until the next poll 8971 if (!mDNSOpaque16IsZero(response->h.id)) 8972 m->rec.r.resrec.rroriginalttl = GetEffectiveTTL(LLQType, m->rec.r.resrec.rroriginalttl); 8973 8974 // If response was not sent via LL multicast, 8975 // then see if it answers a recent query of ours, which would also make it acceptable for caching. 8976 if (!ResponseMCast) 8977 { 8978 if (LLQType) 8979 { 8980 // For Long Lived queries that are both sent over UDP and Private TCP, LLQType is set. 8981 // Even though it is AcceptableResponse, we need a matching DNSServer pointer for the 8982 // queries to get ADD/RMV events. To lookup the question, we can't use 8983 // ExpectingUnicastResponseForRecord as the port numbers don't match. uDNS_recvLLQRespose 8984 // has already matched the question using the 64 bit Id in the packet and we use that here. 8985 8986 if (llqMatch != mDNSNULL) m->rec.r.resrec.rDNSServer = uDNSServer = llqMatch->qDNSServer; 8987 8988 // If this is a DNSSEC question that is also LongLived, don't accept records from the 8989 // Additional/Authority section blindly. We need to go through IsAcceptableResponse below 8990 // so that NSEC/NSEC3 record are cached in the nseclist if we accept them. This can happen 8991 // for both negative responses and wildcard expanded positive responses as both of come 8992 // back with NSEC/NSEC3s. 8993 if (unicastQuestion && DNSSECQuestion(unicastQuestion)) 8994 AcceptableResponse = mDNSfalse; 8995 } 8996 else if (!AcceptableResponse || !dstaddr) 8997 { 8998 // For responses that come over TCP (Responses that can't fit within UDP) or TLS (Private queries 8999 // that are not long lived e.g., AAAA lookup in a Private domain), it is indicated by !dstaddr. 9000 // Even though it is AcceptableResponse, we still need a DNSServer pointer for the resource records that 9001 // we create. 9002 9003 if (!mDNSOpaque16IsZero(response->h.id)) 9004 { 9005 DNSQuestion *q = ExpectingUnicastResponseForRecord(m, srcaddr, ResponseSrcLocal, dstport, response->h.id, &m->rec.r, !dstaddr); 9006 9007 // Initialize the DNS server on the resource record which will now filter what questions we answer with 9008 // this record. 9009 // 9010 // We could potentially lookup the DNS server based on the source address, but that may not work always 9011 // and that's why ExpectingUnicastResponseForRecord does not try to verify whether the response came 9012 // from the DNS server that queried. We follow the same logic here. If we can find a matching quetion based 9013 // on the "id" and "source port", then this response answers the question and assume the response 9014 // came from the same DNS server that we sent the query to. 9015 9016 if (q != mDNSNULL) 9017 { 9018 AcceptableResponse = mDNStrue; 9019 if (!InterfaceID) 9020 { 9021 debugf("mDNSCoreReceiveResponse: InterfaceID %p %##s (%s)", q->InterfaceID, q->qname.c, DNSTypeName(q->qtype)); 9022 m->rec.r.resrec.rDNSServer = uDNSServer = q->qDNSServer; 9023 } 9024 else 9025 LogInfo("mDNSCoreReceiveResponse: InterfaceID %p %##s (%s)", q->InterfaceID, q->qname.c, DNSTypeName(q->qtype)); 9026 } 9027 else 9028 { 9029 // If we can't find a matching question, we need to see whether we have seen records earlier that matched 9030 // the question. The code below does that. So, make this record unacceptable for now 9031 if (!InterfaceID) 9032 { 9033 debugf("mDNSCoreReceiveResponse: Can't find question for record name %##s", m->rec.r.resrec.name->c); 9034 AcceptableResponse = mDNSfalse; 9035 } 9036 } 9037 } 9038 else if (ExpectingMulticastResponseForRecord(m, &m->rec.r, srcaddr, recordAccepted, &McastNSEC3Records)) 9039 { 9040 recordAccepted = mDNStrue; 9041 AcceptableResponse = mDNStrue; 9042 LogInfo("mDNSCoreReceiveResponse: Accepting record in response to QU question %s, InterfaceID %p", CRDisplayString(m, &m->rec.r), 9043 InterfaceID); 9044 } 9045 else if (IsDeviceInfoRecord(m->rec.r.resrec.name)) 9046 { 9047 recordAccepted = mDNStrue; 9048 AcceptableResponse = mDNStrue; 9049 LogInfo("mDNSCoreReceiveResponse: Accepting _device-info record %s, InterfaceID %p", 9050 CRDisplayString(m, &m->rec.r), InterfaceID); 9051 } 9052 } 9053 } 9054 else if (llintf && llintf->IgnoreIPv4LL && m->rec.r.resrec.rrtype == kDNSType_A) 9055 { 9056 CacheRecord *const rr = &m->rec.r; 9057 RDataBody2 *const rdb = (RDataBody2 *)rr->smallrdatastorage.data; 9058 9059 // If we are supposed to ignore link-local addresses on this interface, drop 9060 // all "A" records that have link-local address in them. 9061 if (mDNSv4AddressIsLinkLocal(&rdb->ipv4)) 9062 { 9063 LogInfo("mDNSResponder: Dropping LinkLocal packet %s", CRDisplayString(m, &m->rec.r)); 9064 mDNSCoreResetRecord(m); 9065 continue; 9066 } 9067 } 9068 9069 // 1. Check that this packet resource record does not conflict with any of ours 9070 if (mDNSOpaque16IsZero(response->h.id) && m->rec.r.resrec.rrtype != kDNSType_NSEC) 9071 { 9072 if (m->CurrentRecord) 9073 LogMsg("mDNSCoreReceiveResponse ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord)); 9074 m->CurrentRecord = m->ResourceRecords; 9075 while (m->CurrentRecord) 9076 { 9077 AuthRecord *rr = m->CurrentRecord; 9078 m->CurrentRecord = rr->next; 9079 // We accept all multicast responses, and unicast responses resulting from queries we issued 9080 // For other unicast responses, this code accepts them only for responses with an 9081 // (apparently) local source address that pertain to a record of our own that's in probing state 9082 if (!AcceptableResponse && !(ResponseSrcLocal && rr->resrec.RecordType == kDNSRecordTypeUnique)) continue; 9083 9084 if (PacketRRMatchesSignature(&m->rec.r, rr)) // If interface, name, type (if shared record) and class match... 9085 { 9086 // ... check to see if type and rdata are identical 9087 if (IdenticalSameNameRecord(&m->rec.r.resrec, &rr->resrec)) 9088 { 9089 // If the RR in the packet is identical to ours, just check they're not trying to lower the TTL on us 9090 if (m->rec.r.resrec.rroriginalttl >= rr->resrec.rroriginalttl/2 || m->SleepState) 9091 { 9092 // If we were planning to send on this -- and only this -- interface, then we don't need to any more 9093 if (rr->ImmedAnswer == InterfaceID) { rr->ImmedAnswer = mDNSNULL; rr->ImmedUnicast = mDNSfalse; } 9094 } 9095 else 9096 { 9097 if (rr->ImmedAnswer == mDNSNULL) { rr->ImmedAnswer = InterfaceID; m->NextScheduledResponse = m->timenow; } 9098 else if (rr->ImmedAnswer != InterfaceID) { rr->ImmedAnswer = mDNSInterfaceMark; m->NextScheduledResponse = m->timenow; } 9099 } 9100 } 9101 // else, the packet RR has different type or different rdata -- check to see if this is a conflict 9102 else if (m->rec.r.resrec.rroriginalttl > 0 && PacketRRConflict(m, rr, &m->rec.r)) 9103 { 9104 LogInfo("mDNSCoreReceiveResponse: Pkt Record: %08lX %s", m->rec.r.resrec.rdatahash, CRDisplayString(m, &m->rec.r)); 9105 LogInfo("mDNSCoreReceiveResponse: Our Record: %08lX %s", rr->resrec.rdatahash, ARDisplayString(m, rr)); 9106 9107 // If this record is marked DependentOn another record for conflict detection purposes, 9108 // then *that* record has to be bumped back to probing state to resolve the conflict 9109 if (rr->DependentOn) 9110 { 9111 while (rr->DependentOn) rr = rr->DependentOn; 9112 LogInfo("mDNSCoreReceiveResponse: Dep Record: %08lX %s", rr->resrec.rdatahash, ARDisplayString(m, rr)); 9113 } 9114 9115 // If we've just whacked this record's ProbeCount, don't need to do it again 9116 if (rr->ProbeCount > DefaultProbeCountForTypeUnique) 9117 LogInfo("mDNSCoreReceiveResponse: Already reset to Probing: %s", ARDisplayString(m, rr)); 9118 else if (rr->ProbeCount == DefaultProbeCountForTypeUnique) 9119 LogMsg("mDNSCoreReceiveResponse: Ignoring response received before we even began probing: %s", ARDisplayString(m, rr)); 9120 else 9121 { 9122 LogMsg("mDNSCoreReceiveResponse: Received from %#a:%d %s", srcaddr, mDNSVal16(srcport), CRDisplayString(m, &m->rec.r)); 9123 // If we'd previously verified this record, put it back to probing state and try again 9124 if (rr->resrec.RecordType == kDNSRecordTypeVerified) 9125 { 9126 LogMsg("mDNSCoreReceiveResponse: Resetting to Probing: %s", ARDisplayString(m, rr)); 9127 rr->resrec.RecordType = kDNSRecordTypeUnique; 9128 // We set ProbeCount to one more than the usual value so we know we've already touched this record. 9129 // This is because our single probe for "example-name.local" could yield a response with (say) two A records and 9130 // three AAAA records in it, and we don't want to call RecordProbeFailure() five times and count that as five conflicts. 9131 // This special value is recognised and reset to DefaultProbeCountForTypeUnique in SendQueries(). 9132 rr->ProbeCount = DefaultProbeCountForTypeUnique + 1; 9133 rr->AnnounceCount = InitialAnnounceCount; 9134 InitializeLastAPTime(m, rr); 9135 RecordProbeFailure(m, rr); // Repeated late conflicts also cause us to back off to the slower probing rate 9136 } 9137 // If we're probing for this record, we just failed 9138 else if (rr->resrec.RecordType == kDNSRecordTypeUnique) 9139 { 9140 // Before we call deregister, check if this is a packet we registered with the sleep proxy. 9141 if (!mDNSCoreRegisteredProxyRecord(m, rr)) 9142 { 9143 LogMsg("mDNSCoreReceiveResponse: ProbeCount %d; will deregister %s", rr->ProbeCount, ARDisplayString(m, rr)); 9144 9145 m->mDNSStats.NameConflicts++; 9146 mDNS_Deregister_internal(m, rr, mDNS_Dereg_conflict); 9147 } 9148 } 9149 // We assumed this record must be unique, but we were wrong. (e.g. There are two mDNSResponders on the 9150 // same machine giving different answers for the reverse mapping record, or there are two machines on the 9151 // network using the same IP address.) This is simply a misconfiguration, and there's nothing we can do 9152 // to fix it -- e.g. it's not our job to be trying to change the machine's IP address. We just discard our 9153 // record to avoid continued conflicts (as we do for a conflict on our Unique records) and get on with life. 9154 else if (rr->resrec.RecordType == kDNSRecordTypeKnownUnique) 9155 { 9156 LogMsg("mDNSCoreReceiveResponse: Unexpected conflict discarding %s", ARDisplayString(m, rr)); 9157 m->mDNSStats.KnownUniqueNameConflicts++; 9158 mDNS_Deregister_internal(m, rr, mDNS_Dereg_conflict); 9159 } 9160 else 9161 LogMsg("mDNSCoreReceiveResponse: Unexpected record type %X %s", rr->resrec.RecordType, ARDisplayString(m, rr)); 9162 } 9163 } 9164 // Else, matching signature, different type or rdata, but not a considered a conflict. 9165 // If the packet record has the cache-flush bit set, then we check to see if we 9166 // have any record(s) of the same type that we should re-assert to rescue them 9167 // (see note about "multi-homing and bridged networks" at the end of this function). 9168 else if (m->rec.r.resrec.rrtype == rr->resrec.rrtype) 9169 if ((m->rec.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask) && m->timenow - rr->LastMCTime > mDNSPlatformOneSecond/2) 9170 { rr->ImmedAnswer = mDNSInterfaceMark; m->NextScheduledResponse = m->timenow; } 9171 } 9172 } 9173 } 9174 9175 nseclist = mDNSfalse; 9176 if (!AcceptableResponse) 9177 { 9178 AcceptableResponse = IsResponseAcceptable(m, CacheFlushRecords, unicastQuestion, &nseclist); 9179 if (AcceptableResponse) m->rec.r.resrec.rDNSServer = uDNSServer; 9180 } 9181 9182 // 2. See if we want to add this packet resource record to our cache 9183 // We only try to cache answers if we have a cache to put them in 9184 // Also, we ignore any apparent attempts at cache poisoning unicast to us that do not answer any outstanding active query 9185 if (!AcceptableResponse) LogInfo("mDNSCoreReceiveResponse ignoring %s", CRDisplayString(m, &m->rec.r)); 9186 if (m->rrcache_size && AcceptableResponse) 9187 { 9188 const mDNSu32 slot = HashSlot(m->rec.r.resrec.name); 9189 CacheGroup *cg = CacheGroupForRecord(m, slot, &m->rec.r.resrec); 9190 CacheRecord *rr = mDNSNULL; 9191 9192 if (McastNSEC3Records) 9193 InitializeAnonInfoForCR(m, &McastNSEC3Records, &m->rec.r); 9194 9195 // 2a. Check if this packet resource record is already in our cache. 9196 // 9197 // If this record should go in the nseclist, don't look in the cache for updating it. 9198 // They are supposed to be cached under the "nsec" field of the cache record for 9199 // validation. Just create the cache record. 9200 if (!nseclist) 9201 { 9202 rr = mDNSCoreReceiveCacheCheck(m, response, LLQType, slot, cg, unicastQuestion, &cfp, &NSECCachePtr, InterfaceID); 9203 } 9204 9205 // If mDNSOppCaching is set (which affects only multicast), enable opportunistic caching in which case we cache 9206 // everything that was received over multicast. Otherwise, we are selective about the caching. 9207 // 9208 // Cache everything that is from ourselves (that's how we answer any questions looking for them). Otherwise call 9209 // ExpectingMulticastResponseForRecord which decides whether to cache this record or not. 9210 // 9211 if (!m->mDNSOppCaching && !rr && !myself && mDNSOpaque16IsZero(response->h.id)) 9212 { 9213 if (!ExpectingMulticastResponseForRecord(m, &m->rec.r, srcaddr, recordAccepted, &McastNSEC3Records)) 9214 { 9215 //LogMsg("mDNSCoreReceiveResponse: discarding %s", CRDisplayString(m, &m->rec.r)); 9216 mDNSCoreResetRecord(m); 9217 continue; 9218 } 9219 else 9220 { 9221 recordAccepted = mDNStrue; 9222 } 9223 } 9224 9225 9226 // If packet resource record not in our cache, add it now 9227 // (unless it is just a deletion of a record we never had, in which case we don't care) 9228 if (!rr && m->rec.r.resrec.rroriginalttl > 0) 9229 { 9230 const mDNSBool AddToCFList = (m->rec.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask) && (LLQType != uDNS_LLQ_Events); 9231 mDNSs32 delay; 9232 9233 if (AddToCFList) 9234 delay = NonZeroTime(m->timenow + mDNSPlatformOneSecond); 9235 else 9236 delay = CheckForSoonToExpireRecords(m, m->rec.r.resrec.name, m->rec.r.resrec.namehash, slot, mDNSNULL); 9237 9238 // If unique, assume we may have to delay delivery of this 'add' event. 9239 // Below, where we walk the CacheFlushRecords list, we either call CacheRecordDeferredAdd() 9240 // to immediately to generate answer callbacks, or we call ScheduleNextCacheCheckTime() 9241 // to schedule an mDNS_Execute task at the appropriate time. 9242 rr = CreateNewCacheEntry(m, slot, cg, delay, !nseclist, srcaddr); 9243 if (rr) 9244 { 9245 rr->responseFlags = response->h.flags; 9246 // If we are not creating signatures, then we need to inform DNSSEC so that 9247 // it does not wait forever. Don't do this if we got NSEC records 9248 // as it indicates that this name does not exist. 9249 if (rr->resrec.rrtype == kDNSType_RRSIG && !nseclist) 9250 { 9251 rrsigsCreated = mDNStrue; 9252 } 9253 // Remember whether we created a cache record in response to a DNSSEC question. 9254 // This helps DNSSEC code not to reissue the question to fetch the DNSSEC records. 9255 rr->CRDNSSECQuestion = 0; 9256 if (unicastQuestion && DNSSECQuestion(unicastQuestion)) 9257 { 9258 LogInfo("mDNSCoreReceiveResponse: CRDNSSECQuestion set for new record %s, question %##s (%s)", CRDisplayString(m, rr), 9259 unicastQuestion->qname.c, DNSTypeName(unicastQuestion->qtype)); 9260 rr->CRDNSSECQuestion = 1; 9261 } 9262 // NSEC/NSEC3 records and its signatures are cached with the negative cache entry 9263 // which we should be creating below. It is also needed in the wildcard 9264 // expanded answer case and in that case it is cached along with the answer. 9265 if (nseclist) 9266 { 9267 rr->TimeRcvd = m->timenow; 9268 *nsecp = rr; 9269 nsecp = &rr->next; 9270 } 9271 else if (AddToCFList) 9272 { 9273 *cfp = rr; 9274 cfp = &rr->NextInCFList; 9275 *cfp = (CacheRecord*)1; 9276 } 9277 else if (rr->DelayDelivery) 9278 { 9279 ScheduleNextCacheCheckTime(m, slot, rr->DelayDelivery); 9280 } 9281 } 9282 } 9283 else 9284 { 9285 if (rr && rr->resrec.AnonInfo && m->rec.r.resrec.AnonInfo) 9286 { 9287 CopyAnonInfoForCR(m, rr, &m->rec.r); 9288 } 9289 } 9290 } 9291 mDNSCoreResetRecord(m); 9292 } 9293 9294 exit: 9295 mDNSCoreResetRecord(m); 9296 9297 // If we've just received one or more records with their cache flush bits set, 9298 // then scan that cache slot to see if there are any old stale records we need to flush 9299 while (CacheFlushRecords != (CacheRecord*)1) 9300 { 9301 CacheRecord *r1 = CacheFlushRecords, *r2; 9302 const mDNSu32 slot = HashSlot(r1->resrec.name); 9303 const CacheGroup *cg = CacheGroupForRecord(m, slot, &r1->resrec); 9304 CacheFlushRecords = CacheFlushRecords->NextInCFList; 9305 r1->NextInCFList = mDNSNULL; 9306 9307 // Look for records in the cache with the same signature as this new one with the cache flush 9308 // bit set, and either (a) if they're fresh, just make sure the whole RRSet has the same TTL 9309 // (as required by DNS semantics) or (b) if they're old, mark them for deletion in one second. 9310 // We make these TTL adjustments *only* for records that still have *more* than one second 9311 // remaining to live. Otherwise, a record that we tagged for deletion half a second ago 9312 // (and now has half a second remaining) could inadvertently get its life extended, by either 9313 // (a) if we got an explicit goodbye packet half a second ago, the record would be considered 9314 // "fresh" and would be incorrectly resurrected back to the same TTL as the rest of the RRSet, 9315 // or (b) otherwise, the record would not be fully resurrected, but would be reset to expire 9316 // in one second, thereby inadvertently delaying its actual expiration, instead of hastening it. 9317 // If this were to happen repeatedly, the record's expiration could be deferred indefinitely. 9318 // To avoid this, we need to ensure that the cache flushing operation will only act to 9319 // *decrease* a record's remaining lifetime, never *increase* it. 9320 for (r2 = cg ? cg->members : mDNSNULL; r2; r2=r2->next) 9321 { 9322 mDNSu16 id1; 9323 mDNSu16 id2; 9324 if (!r1->resrec.InterfaceID) 9325 { 9326 id1 = (r1->resrec.rDNSServer ? r1->resrec.rDNSServer->resGroupID : 0); 9327 id2 = (r2->resrec.rDNSServer ? r2->resrec.rDNSServer->resGroupID : 0); 9328 } 9329 else 9330 { 9331 id1 = id2 = 0; 9332 } 9333 // When we receive new RRSIGs e.g., for DNSKEY record, we should not flush the old 9334 // RRSIGS e.g., for TXT record. To do so, we need to look at the typeCovered field of 9335 // the new RRSIG that we received. Process only if the typeCovered matches. 9336 if ((r1->resrec.rrtype == r2->resrec.rrtype) && (r1->resrec.rrtype == kDNSType_RRSIG)) 9337 { 9338 rdataRRSig *rrsig1 = (rdataRRSig *)(((RDataBody2 *)(r1->resrec.rdata->u.data))->data); 9339 rdataRRSig *rrsig2 = (rdataRRSig *)(((RDataBody2 *)(r2->resrec.rdata->u.data))->data); 9340 if (swap16(rrsig1->typeCovered) != swap16(rrsig2->typeCovered)) 9341 { 9342 debugf("mDNSCoreReceiveResponse: Received RRSIG typeCovered %s, found %s, not processing", 9343 DNSTypeName(swap16(rrsig1->typeCovered)), DNSTypeName(swap16(rrsig2->typeCovered))); 9344 continue; 9345 } 9346 } 9347 9348 // For Unicast (null InterfaceID) the resolver IDs should also match 9349 if ((r1->resrec.InterfaceID == r2->resrec.InterfaceID) && 9350 (r1->resrec.InterfaceID || (id1 == id2)) && 9351 r1->resrec.rrtype == r2->resrec.rrtype && 9352 r1->resrec.rrclass == r2->resrec.rrclass) 9353 { 9354 // If record is recent, just ensure the whole RRSet has the same TTL (as required by DNS semantics) 9355 // else, if record is old, mark it to be flushed 9356 if (m->timenow - r2->TimeRcvd < mDNSPlatformOneSecond && RRExpireTime(r2) - m->timenow > mDNSPlatformOneSecond) 9357 { 9358 // If we find mismatched TTLs in an RRSet, correct them. 9359 // We only do this for records with a TTL of 2 or higher. It's possible to have a 9360 // goodbye announcement with the cache flush bit set (or a case-change on record rdata, 9361 // which we treat as a goodbye followed by an addition) and in that case it would be 9362 // inappropriate to synchronize all the other records to a TTL of 0 (or 1). 9363 // We suppress the message for the specific case of correcting from 240 to 60 for type TXT, 9364 // because certain early Bonjour devices are known to have this specific mismatch, and 9365 // there's no point filling syslog with messages about something we already know about. 9366 // We also don't log this for uDNS responses, since a caching name server is obliged 9367 // to give us an aged TTL to correct for how long it has held the record, 9368 // so our received TTLs are expected to vary in that case 9369 if (r2->resrec.rroriginalttl != r1->resrec.rroriginalttl && r1->resrec.rroriginalttl > 1) 9370 { 9371 if (!(r2->resrec.rroriginalttl == 240 && r1->resrec.rroriginalttl == 60 && r2->resrec.rrtype == kDNSType_TXT) && 9372 mDNSOpaque16IsZero(response->h.id)) 9373 LogInfo("Correcting TTL from %4d to %4d for %s", 9374 r2->resrec.rroriginalttl, r1->resrec.rroriginalttl, CRDisplayString(m, r2)); 9375 r2->resrec.rroriginalttl = r1->resrec.rroriginalttl; 9376 } 9377 r2->TimeRcvd = m->timenow; 9378 } 9379 else // else, if record is old, mark it to be flushed 9380 { 9381 verbosedebugf("Cache flush new %p age %d expire in %d %s", r1, m->timenow - r1->TimeRcvd, RRExpireTime(r1) - m->timenow, CRDisplayString(m, r1)); 9382 verbosedebugf("Cache flush old %p age %d expire in %d %s", r2, m->timenow - r2->TimeRcvd, RRExpireTime(r2) - m->timenow, CRDisplayString(m, r2)); 9383 // We set stale records to expire in one second. 9384 // This gives the owner a chance to rescue it if necessary. 9385 // This is important in the case of multi-homing and bridged networks: 9386 // Suppose host X is on Ethernet. X then connects to an AirPort base station, which happens to be 9387 // bridged onto the same Ethernet. When X announces its AirPort IP address with the cache-flush bit 9388 // set, the AirPort packet will be bridged onto the Ethernet, and all other hosts on the Ethernet 9389 // will promptly delete their cached copies of the (still valid) Ethernet IP address record. 9390 // By delaying the deletion by one second, we give X a change to notice that this bridging has 9391 // happened, and re-announce its Ethernet IP address to rescue it from deletion from all our caches. 9392 9393 // We set UnansweredQueries to MaxUnansweredQueries to avoid expensive and unnecessary 9394 // final expiration queries for this record. 9395 9396 // If a record is deleted twice, first with an explicit DE record, then a second time by virtue of the cache 9397 // flush bit on the new record replacing it, then we allow the record to be deleted immediately, without the usual 9398 // one-second grace period. This improves responsiveness for mDNS_Update(), as used for things like iChat status updates. 9399 // <rdar://problem/5636422> Updating TXT records is too slow 9400 // We check for "rroriginalttl == 1" because we want to include records tagged by the "packet TTL is zero" check above, 9401 // which sets rroriginalttl to 1, but not records tagged by the rdata case-change check, which sets rroriginalttl to 0. 9402 if (r2->TimeRcvd == m->timenow && r2->resrec.rroriginalttl == 1 && r2->UnansweredQueries == MaxUnansweredQueries) 9403 { 9404 LogInfo("Cache flush for DE record %s", CRDisplayString(m, r2)); 9405 r2->resrec.rroriginalttl = 0; 9406 } 9407 else if (RRExpireTime(r2) - m->timenow > mDNSPlatformOneSecond) 9408 { 9409 // We only set a record to expire in one second if it currently has *more* than a second to live 9410 // If it's already due to expire in a second or less, we just leave it alone 9411 r2->resrec.rroriginalttl = 1; 9412 r2->UnansweredQueries = MaxUnansweredQueries; 9413 r2->TimeRcvd = m->timenow - 1; 9414 // We use (m->timenow - 1) instead of m->timenow, because we use that to identify records 9415 // that we marked for deletion via an explicit DE record 9416 } 9417 } 9418 SetNextCacheCheckTimeForRecord(m, r2); 9419 } 9420 } 9421 9422 if (r1->DelayDelivery) // If we were planning to delay delivery of this record, see if we still need to 9423 { 9424 // If we had a unicast question for this response with at least one positive answer and we 9425 // have NSECRecords, it is most likely a wildcard expanded answer. Cache the NSEC and its 9426 // signatures along with the cache record which will be used for validation later. If 9427 // we rescued a few records earlier in this function, then NSECCachePtr would be set. In that 9428 // use that instead. 9429 if (response->h.numAnswers && unicastQuestion && NSECRecords) 9430 { 9431 if (!NSECCachePtr) 9432 { 9433 LogInfo("mDNSCoreReceiveResponse: Updating NSECCachePtr to %s", CRDisplayString(m, r1)); 9434 NSECCachePtr = r1; 9435 } 9436 // Note: We need to do this before we call CacheRecordDeferredAdd as this 9437 // might start the verification process which needs these NSEC records 9438 if (!AddNSECSForCacheRecord(m, NSECRecords, NSECCachePtr, rcode)) 9439 { 9440 LogInfo("mDNSCoreReceiveResponse: AddNSECSForCacheRecord failed to add NSEC for %s", CRDisplayString(m, NSECCachePtr)); 9441 FreeNSECRecords(m, NSECRecords); 9442 } 9443 NSECRecords = mDNSNULL; 9444 NSECCachePtr = mDNSNULL; 9445 } 9446 r1->DelayDelivery = CheckForSoonToExpireRecords(m, r1->resrec.name, r1->resrec.namehash, slot, mDNSNULL); 9447 // If no longer delaying, deliver answer now, else schedule delivery for the appropriate time 9448 if (!r1->DelayDelivery) CacheRecordDeferredAdd(m, r1); 9449 else ScheduleNextCacheCheckTime(m, slot, r1->DelayDelivery); 9450 } 9451 } 9452 9453 // If we have not consumed the NSEC records yet e.g., just refreshing the cache, 9454 // update them now for future validations. 9455 if (NSECRecords && NSECCachePtr) 9456 { 9457 LogInfo("mDNSCoreReceieveResponse: Updating NSEC records in %s", CRDisplayString(m, NSECCachePtr)); 9458 if (!AddNSECSForCacheRecord(m, NSECRecords, NSECCachePtr, rcode)) 9459 { 9460 LogInfo("mDNSCoreReceiveResponse: AddNSECSForCacheRecord failed to add NSEC for %s", CRDisplayString(m, NSECCachePtr)); 9461 FreeNSECRecords(m, NSECRecords); 9462 } 9463 NSECRecords = mDNSNULL; 9464 NSECCachePtr = mDNSNULL; 9465 } 9466 9467 // If there is at least one answer and we did not create RRSIGs and there was a 9468 // ValidatingResponse question waiting for this response, give a hint that no RRSIGs 9469 // were created. We don't need to give a hint: 9470 // 9471 // - if we have no answers, the mDNSCoreReceiveNoUnicastAnswers below should 9472 // generate a negative response 9473 // 9474 // - if we have NSECRecords, it means we might have a potential proof for 9475 // non-existence of name that we are looking for 9476 // 9477 if (response->h.numAnswers && !rrsigsCreated && DNSSECQuestion && !NSECRecords) 9478 mDNSCoreReceiveNoDNSSECAnswers(m, response, end, dstaddr, dstport, InterfaceID); 9479 9480 // See if we need to generate negative cache entries for unanswered unicast questions 9481 mDNSCoreReceiveNoUnicastAnswers(m, response, end, dstaddr, dstport, InterfaceID, LLQType, rcode, NSECRecords); 9482 9483 if (McastNSEC3Records) 9484 { 9485 debugf("mDNSCoreReceiveResponse: McastNSEC3Records not used"); 9486 FreeNSECRecords(m, McastNSEC3Records); 9487 } 9488 } 9489 9490 // ScheduleWakeup causes all proxy records with WakeUp.HMAC matching mDNSEthAddr 'e' to be deregistered, causing 9491 // multiple wakeup magic packets to be sent if appropriate, and all records to be ultimately freed after a few seconds. 9492 // ScheduleWakeup is called on mDNS record conflicts, ARP conflicts, NDP conflicts, or reception of trigger traffic 9493 // that warrants waking the sleeping host. 9494 // ScheduleWakeup must be called with the lock held (ScheduleWakeupForList uses mDNS_Deregister_internal) 9495 9496 mDNSlocal void ScheduleWakeupForList(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *e, AuthRecord *const thelist) 9497 { 9498 // We need to use the m->CurrentRecord mechanism here when dealing with DuplicateRecords list as 9499 // mDNS_Deregister_internal deregisters duplicate records immediately as they are not used 9500 // to send wakeups or goodbyes. See the comment in that function for more details. To keep it 9501 // simple, we use the same mechanism for both lists. 9502 if (!e->l[0]) 9503 { 9504 LogMsg("ScheduleWakeupForList ERROR: Target HMAC is zero"); 9505 return; 9506 } 9507 m->CurrentRecord = thelist; 9508 while (m->CurrentRecord) 9509 { 9510 AuthRecord *const rr = m->CurrentRecord; 9511 if (rr->resrec.InterfaceID == InterfaceID && rr->resrec.RecordType != kDNSRecordTypeDeregistering && mDNSSameEthAddress(&rr->WakeUp.HMAC, e)) 9512 { 9513 LogInfo("ScheduleWakeupForList: Scheduling wakeup packets for %s", ARDisplayString(m, rr)); 9514 mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal); 9515 } 9516 if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now 9517 m->CurrentRecord = rr->next; 9518 } 9519 } 9520 9521 mDNSlocal void ScheduleWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *e) 9522 { 9523 if (!e->l[0]) { LogMsg("ScheduleWakeup ERROR: Target HMAC is zero"); return; } 9524 ScheduleWakeupForList(m, InterfaceID, e, m->DuplicateRecords); 9525 ScheduleWakeupForList(m, InterfaceID, e, m->ResourceRecords); 9526 } 9527 9528 mDNSlocal void SPSRecordCallback(mDNS *const m, AuthRecord *const ar, mStatus result) 9529 { 9530 if (result && result != mStatus_MemFree) 9531 LogInfo("SPS Callback %d %s", result, ARDisplayString(m, ar)); 9532 9533 if (result == mStatus_NameConflict) 9534 { 9535 mDNS_Lock(m); 9536 LogMsg("%-7s Conflicting mDNS -- waking %.6a %s", InterfaceNameForID(m, ar->resrec.InterfaceID), &ar->WakeUp.HMAC, ARDisplayString(m, ar)); 9537 if (ar->WakeUp.HMAC.l[0]) 9538 { 9539 SendWakeup(m, ar->resrec.InterfaceID, &ar->WakeUp.IMAC, &ar->WakeUp.password); // Send one wakeup magic packet 9540 ScheduleWakeup(m, ar->resrec.InterfaceID, &ar->WakeUp.HMAC); // Schedule all other records with the same owner to be woken 9541 } 9542 mDNS_Unlock(m); 9543 } 9544 9545 if (result == mStatus_NameConflict || result == mStatus_MemFree) 9546 { 9547 m->ProxyRecords--; 9548 mDNSPlatformMemFree(ar); 9549 mDNS_UpdateAllowSleep(m); 9550 } 9551 } 9552 9553 mDNSlocal mDNSu8 *GetValueForMACAddr(mDNSu8 *ptr, mDNSu8 *limit, mDNSEthAddr *eth) 9554 { 9555 int i; 9556 mDNSs8 hval = 0; 9557 int colons = 0; 9558 mDNSu8 val = 0; 9559 9560 for (i = 0; ptr < limit && *ptr != ' ' && i < 17; i++, ptr++) 9561 { 9562 hval = HexVal(*ptr); 9563 if (hval != -1) 9564 { 9565 val <<= 4; 9566 val |= hval; 9567 } 9568 else if (*ptr == ':') 9569 { 9570 eth->b[colons] = val; 9571 colons++; 9572 val = 0; 9573 } 9574 } 9575 if (colons != 5) 9576 { 9577 LogMsg("GetValueForMACAddr: Address malformed colons %d", colons); 9578 return mDNSNULL; 9579 } 9580 eth->b[colons] = val; 9581 return ptr; 9582 } 9583 9584 mDNSlocal mDNSu8 *GetValueForIPv6Addr(mDNSu8 *ptr, mDNSu8 *limit, mDNSv6Addr *v6) 9585 { 9586 int hval; 9587 int value; 9588 int numBytes; 9589 int digitsProcessed; 9590 int zeroFillStart; 9591 int numColons; 9592 mDNSu8 v6addr[16]; 9593 9594 // RFC 3513: Section 2.2 specifies IPv6 presentation format. The following parsing 9595 // handles both (1) and (2) and does not handle embedded IPv4 addresses. 9596 // 9597 // First forms a address in "v6addr", then expands to fill the zeroes in and returns 9598 // the result in "v6" 9599 9600 numColons = numBytes = value = digitsProcessed = zeroFillStart = 0; 9601 while (ptr < limit && *ptr != ' ') 9602 { 9603 hval = HexVal(*ptr); 9604 if (hval != -1) 9605 { 9606 value <<= 4; 9607 value |= hval; 9608 digitsProcessed = 1; 9609 } 9610 else if (*ptr == ':') 9611 { 9612 if (!digitsProcessed) 9613 { 9614 // If we have already seen a "::", we should not see one more. Handle the special 9615 // case of "::" 9616 if (numColons) 9617 { 9618 // if we never filled any bytes and the next character is space (we have reached the end) 9619 // we are done 9620 if (!numBytes && (ptr + 1) < limit && *(ptr + 1) == ' ') 9621 { 9622 mDNSPlatformMemZero(v6->b, 16); 9623 return ptr + 1; 9624 } 9625 LogMsg("GetValueForIPv6Addr: zeroFillStart non-zero %d", zeroFillStart); 9626 return mDNSNULL; 9627 } 9628 9629 // We processed "::". We need to fill zeroes later. For now, mark the 9630 // point where we will start filling zeroes from. 9631 zeroFillStart = numBytes; 9632 numColons++; 9633 } 9634 else if ((ptr + 1) < limit && *(ptr + 1) == ' ') 9635 { 9636 // We have a trailing ":" i.e., no more characters after ":" 9637 LogMsg("GetValueForIPv6Addr: Trailing colon"); 9638 return mDNSNULL; 9639 } 9640 else 9641 { 9642 // For a fully expanded IPv6 address, we fill the 14th and 15th byte outside of this while 9643 // loop below as there is no ":" at the end. Hence, the last two bytes that can possibly 9644 // filled here is 12 and 13. 9645 if (numBytes > 13) { LogMsg("GetValueForIPv6Addr:1: numBytes is %d", numBytes); return mDNSNULL; } 9646 9647 v6addr[numBytes++] = (mDNSu8) ((value >> 8) & 0xFF); 9648 v6addr[numBytes++] = (mDNSu8) (value & 0xFF); 9649 digitsProcessed = value = 0; 9650 9651 // Make sure that we did not fill the 13th and 14th byte above 9652 if (numBytes > 14) { LogMsg("GetValueForIPv6Addr:2: numBytes is %d", numBytes); return mDNSNULL; } 9653 } 9654 } 9655 ptr++; 9656 } 9657 9658 // We should be processing the last set of bytes following the last ":" here 9659 if (!digitsProcessed) 9660 { 9661 LogMsg("GetValueForIPv6Addr: no trailing bytes after colon, numBytes is %d", numBytes); 9662 return mDNSNULL; 9663 } 9664 9665 if (numBytes > 14) { LogMsg("GetValueForIPv6Addr:3: numBytes is %d", numBytes); return mDNSNULL; } 9666 v6addr[numBytes++] = (mDNSu8) ((value >> 8) & 0xFF); 9667 v6addr[numBytes++] = (mDNSu8) (value & 0xFF); 9668 9669 if (zeroFillStart) 9670 { 9671 int i, j, n; 9672 for (i = 0; i < zeroFillStart; i++) 9673 v6->b[i] = v6addr[i]; 9674 for (j = i, n = 0; n < 16 - numBytes; j++, n++) 9675 v6->b[j] = 0; 9676 for (; j < 16; i++, j++) 9677 v6->b[j] = v6addr[i]; 9678 } 9679 else if (numBytes == 16) 9680 mDNSPlatformMemCopy(v6->b, v6addr, 16); 9681 else 9682 { 9683 LogMsg("GetValueForIPv6addr: Not enough bytes for IPv6 address, numBytes is %d", numBytes); 9684 return mDNSNULL; 9685 } 9686 return ptr; 9687 } 9688 9689 mDNSlocal mDNSu8 *GetValueForIPv4Addr(mDNSu8 *ptr, mDNSu8 *limit, mDNSv4Addr *v4) 9690 { 9691 mDNSu32 val; 9692 int dots = 0; 9693 val = 0; 9694 9695 for ( ; ptr < limit && *ptr != ' '; ptr++) 9696 { 9697 if (*ptr >= '0' && *ptr <= '9') 9698 val = val * 10 + *ptr - '0'; 9699 else if (*ptr == '.') 9700 { 9701 v4->b[dots++] = val; 9702 val = 0; 9703 } 9704 else 9705 { 9706 // We have a zero at the end and if we reached that, then we are done. 9707 if (*ptr == 0 && ptr == limit - 1 && dots == 3) 9708 { 9709 v4->b[dots] = val; 9710 return ptr + 1; 9711 } 9712 else { LogMsg("GetValueForIPv4Addr: something wrong ptr(%p) %c, limit %p, dots %d", ptr, *ptr, limit, dots); return mDNSNULL; } 9713 } 9714 } 9715 if (dots != 3) { LogMsg("GetValueForIPv4Addr: Address malformed dots %d", dots); return mDNSNULL; } 9716 v4->b[dots] = val; 9717 return ptr; 9718 } 9719 9720 mDNSlocal mDNSu8 *GetValueForKeepalive(mDNSu8 *ptr, mDNSu8 *limit, mDNSu32 *value) 9721 { 9722 mDNSu32 val; 9723 9724 val = 0; 9725 for ( ; ptr < limit && *ptr != ' '; ptr++) 9726 { 9727 if (*ptr < '0' || *ptr > '9') 9728 { 9729 // We have a zero at the end and if we reached that, then we are done. 9730 if (*ptr == 0 && ptr == limit - 1) 9731 { 9732 *value = val; 9733 return ptr + 1; 9734 } 9735 else { LogMsg("GetValueForKeepalive: *ptr %d, ptr %p, limit %p, ptr +1 %d", *ptr, ptr, limit, *(ptr + 1)); return mDNSNULL; } 9736 } 9737 val = val * 10 + *ptr - '0'; 9738 } 9739 *value = val; 9740 return ptr; 9741 } 9742 9743 mDNSlocal void mDNS_ExtractKeepaliveInfo(AuthRecord *ar, mDNSu32 *timeout, mDNSAddr *laddr, mDNSAddr *raddr, mDNSEthAddr *eth, mDNSu32 *seq, 9744 mDNSu32 *ack, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu16 *win) 9745 { 9746 if (ar->resrec.rrtype != kDNSType_NULL) 9747 return; 9748 9749 if (mDNS_KeepaliveRecord(&ar->resrec)) 9750 { 9751 int len = ar->resrec.rdlength; 9752 mDNSu8 *ptr = &ar->resrec.rdata->u.txt.c[1]; 9753 mDNSu8 *limit = ptr + len - 1; // Exclude the first byte that is the length 9754 mDNSu32 value = 0; 9755 9756 while (ptr < limit) 9757 { 9758 mDNSu8 param = *ptr; 9759 ptr += 2; // Skip the letter and the "=" 9760 if (param == 'h') 9761 { 9762 laddr->type = mDNSAddrType_IPv4; 9763 ptr = GetValueForIPv4Addr(ptr, limit, &laddr->ip.v4); 9764 } 9765 else if (param == 'd') 9766 { 9767 raddr->type = mDNSAddrType_IPv4; 9768 ptr = GetValueForIPv4Addr(ptr, limit, &raddr->ip.v4); 9769 } 9770 if (param == 'H') 9771 { 9772 laddr->type = mDNSAddrType_IPv6; 9773 ptr = GetValueForIPv6Addr(ptr, limit, &laddr->ip.v6); 9774 } 9775 else if (param == 'D') 9776 { 9777 raddr->type = mDNSAddrType_IPv6; 9778 ptr = GetValueForIPv6Addr(ptr, limit, &raddr->ip.v6); 9779 } 9780 else if (param == 'm') 9781 { 9782 ptr = GetValueForMACAddr(ptr, limit, eth); 9783 } 9784 else 9785 { 9786 ptr = GetValueForKeepalive(ptr, limit, &value); 9787 } 9788 if (!ptr) { LogMsg("mDNS_ExtractKeepaliveInfo: Cannot parse\n"); return; } 9789 9790 // Extract everything in network order so that it is easy for sending a keepalive and also 9791 // for matching incoming TCP packets 9792 switch (param) 9793 { 9794 case 't': 9795 *timeout = value; 9796 //if (*timeout < 120) *timeout = 120; 9797 break; 9798 case 'h': 9799 case 'H': 9800 case 'd': 9801 case 'D': 9802 case 'm': 9803 case 'i': 9804 case 'c': 9805 break; 9806 case 'l': 9807 lport->NotAnInteger = swap16((mDNSu16)value); 9808 break; 9809 case 'r': 9810 rport->NotAnInteger = swap16((mDNSu16)value); 9811 break; 9812 case 's': 9813 *seq = swap32(value); 9814 break; 9815 case 'a': 9816 *ack = swap32(value); 9817 break; 9818 case 'w': 9819 *win = swap16((mDNSu16)value); 9820 break; 9821 default: 9822 LogMsg("mDNS_ExtractKeepaliveInfo: unknown value %c\n", param); 9823 ptr = limit; 9824 break; 9825 } 9826 ptr++; // skip the space 9827 } 9828 } 9829 } 9830 9831 // Matches the proxied auth records to the incoming TCP packet and returns the match and its sequence and ack in "rseq" and "rack" so that 9832 // the clients need not retrieve this information from the auth record again. 9833 mDNSlocal AuthRecord* mDNS_MatchKeepaliveInfo(mDNS *const m, const mDNSAddr* pladdr, const mDNSAddr* praddr, const mDNSIPPort plport, 9834 const mDNSIPPort prport, mDNSu32 *rseq, mDNSu32 *rack) 9835 { 9836 AuthRecord *ar; 9837 mDNSAddr laddr, raddr; 9838 mDNSEthAddr eth; 9839 mDNSIPPort lport, rport; 9840 mDNSu32 timeout, seq, ack; 9841 mDNSu16 win; 9842 9843 for (ar = m->ResourceRecords; ar; ar=ar->next) 9844 { 9845 timeout = seq = ack = 0; 9846 win = 0; 9847 laddr = raddr = zeroAddr; 9848 lport = rport = zeroIPPort; 9849 9850 if (!ar->WakeUp.HMAC.l[0]) continue; 9851 9852 mDNS_ExtractKeepaliveInfo(ar, &timeout, &laddr, &raddr, ð, &seq, &ack, &lport, &rport, &win); 9853 9854 // Did we parse correctly ? 9855 if (!timeout || mDNSAddressIsZero(&laddr) || mDNSAddressIsZero(&raddr) || !seq || !ack || mDNSIPPortIsZero(lport) || mDNSIPPortIsZero(rport) || !win) 9856 { 9857 debugf("mDNS_MatchKeepaliveInfo: not a valid record %s for keepalive", ARDisplayString(m, ar)); 9858 continue; 9859 } 9860 9861 debugf("mDNS_MatchKeepaliveInfo: laddr %#a pladdr %#a, raddr %#a praddr %#a, lport %d plport %d, rport %d prport %d", 9862 &laddr, pladdr, &raddr, praddr, mDNSVal16(lport), mDNSVal16(plport), mDNSVal16(rport), mDNSVal16(prport)); 9863 9864 // Does it match the incoming TCP packet ? 9865 if (mDNSSameAddress(&laddr, pladdr) && mDNSSameAddress(&raddr, praddr) && mDNSSameIPPort(lport, plport) && mDNSSameIPPort(rport, prport)) 9866 { 9867 // returning in network order 9868 *rseq = seq; 9869 *rack = ack; 9870 return ar; 9871 } 9872 } 9873 return mDNSNULL; 9874 } 9875 9876 mDNSlocal void mDNS_SendKeepalives(mDNS *const m) 9877 { 9878 AuthRecord *ar; 9879 9880 for (ar = m->ResourceRecords; ar; ar=ar->next) 9881 { 9882 mDNSu32 timeout, seq, ack; 9883 mDNSu16 win; 9884 mDNSAddr laddr, raddr; 9885 mDNSEthAddr eth; 9886 mDNSIPPort lport, rport; 9887 9888 timeout = seq = ack = 0; 9889 win = 0; 9890 9891 laddr = raddr = zeroAddr; 9892 lport = rport = zeroIPPort; 9893 9894 if (!ar->WakeUp.HMAC.l[0]) continue; 9895 9896 mDNS_ExtractKeepaliveInfo(ar, &timeout, &laddr, &raddr, ð, &seq, &ack, &lport, &rport, &win); 9897 9898 if (!timeout || mDNSAddressIsZero(&laddr) || mDNSAddressIsZero(&raddr) || !seq || !ack || mDNSIPPortIsZero(lport) || mDNSIPPortIsZero(rport) || !win) 9899 { 9900 debugf("mDNS_SendKeepalives: not a valid record %s for keepalive", ARDisplayString(m, ar)); 9901 continue; 9902 } 9903 LogMsg("mDNS_SendKeepalives: laddr %#a raddr %#a lport %d rport %d", &laddr, &raddr, mDNSVal16(lport), mDNSVal16(rport)); 9904 9905 // When we receive a proxy update, we set KATimeExpire to zero so that we always send a keepalive 9906 // immediately (to detect any potential problems). After that we always set it to a non-zero value. 9907 if (!ar->KATimeExpire || (m->timenow - ar->KATimeExpire >= 0)) 9908 { 9909 mDNSPlatformSendKeepalive(&laddr, &raddr, &lport, &rport, seq, ack, win); 9910 ar->KATimeExpire = NonZeroTime(m->timenow + timeout * mDNSPlatformOneSecond); 9911 } 9912 if (m->NextScheduledKA - ar->KATimeExpire > 0) 9913 m->NextScheduledKA = ar->KATimeExpire; 9914 } 9915 } 9916 9917 mDNSlocal void mDNS_SendKeepaliveACK(mDNS *const m, AuthRecord *ar) 9918 { 9919 if (ar != mDNSNULL) 9920 { 9921 LogInfo("mDNS_SendKeepalivesACK: AuthRecord is NULL"); 9922 return; 9923 } 9924 mDNSu32 timeout, seq, ack; 9925 mDNSu16 win; 9926 mDNSAddr laddr, raddr; 9927 mDNSEthAddr eth; 9928 mDNSIPPort lport, rport; 9929 9930 timeout = seq = ack = 0; 9931 win = 0; 9932 9933 laddr = raddr = zeroAddr; 9934 lport = rport = zeroIPPort; 9935 9936 mDNS_ExtractKeepaliveInfo(ar, &timeout, &laddr, &raddr, ð, &seq, &ack, &lport, &rport, &win); 9937 9938 if (!timeout || mDNSAddressIsZero(&laddr) || mDNSAddressIsZero(&raddr) || !seq || !ack || mDNSIPPortIsZero(lport) || mDNSIPPortIsZero(rport) || !win) 9939 { 9940 LogInfo("mDNS_SendKeepaliveACK: not a valid record %s for keepalive", ARDisplayString(m, ar)); 9941 return; 9942 } 9943 LogMsg("mDNS_SendKeepaliveACK: laddr %#a raddr %#a lport %d rport %d", &laddr, &raddr, mDNSVal16(lport), mDNSVal16(rport)); 9944 mDNSPlatformSendKeepalive(&laddr, &raddr, &lport, &rport, seq, ack, win); 9945 } 9946 9947 mDNSlocal void mDNSCoreReceiveUpdate(mDNS *const m, 9948 const DNSMessage *const msg, const mDNSu8 *end, 9949 const mDNSAddr *srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, mDNSIPPort dstport, 9950 const mDNSInterfaceID InterfaceID) 9951 { 9952 int i; 9953 AuthRecord opt; 9954 mDNSu8 *p = m->omsg.data; 9955 OwnerOptData owner = zeroOwner; // Need to zero this, so we'll know if this Update packet was missing its Owner option 9956 mDNSu32 updatelease = 0; 9957 const mDNSu8 *ptr; 9958 9959 LogSPS("Received Update from %#-15a:%-5d to %#-15a:%-5d on 0x%p with " 9960 "%2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s %d bytes", 9961 srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), InterfaceID, 9962 msg->h.numQuestions, msg->h.numQuestions == 1 ? ", " : "s,", 9963 msg->h.numAnswers, msg->h.numAnswers == 1 ? ", " : "s,", 9964 msg->h.numAuthorities, msg->h.numAuthorities == 1 ? "y, " : "ies,", 9965 msg->h.numAdditionals, msg->h.numAdditionals == 1 ? " " : "s", end - msg->data); 9966 9967 if (!InterfaceID || !m->SPSSocket || !mDNSSameIPPort(dstport, m->SPSSocket->port)) return; 9968 9969 if (mDNS_PacketLoggingEnabled) 9970 DumpPacket(m, mStatus_NoError, mDNSfalse, "UDP", srcaddr, srcport, dstaddr, dstport, msg, end); 9971 9972 ptr = LocateOptRR(msg, end, DNSOpt_LeaseData_Space + DNSOpt_OwnerData_ID_Space); 9973 if (ptr) 9974 { 9975 ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec); 9976 if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && m->rec.r.resrec.rrtype == kDNSType_OPT) 9977 { 9978 const rdataOPT *o; 9979 const rdataOPT *const e = (const rdataOPT *)&m->rec.r.resrec.rdata->u.data[m->rec.r.resrec.rdlength]; 9980 for (o = &m->rec.r.resrec.rdata->u.opt[0]; o < e; o++) 9981 { 9982 if (o->opt == kDNSOpt_Lease) updatelease = o->u.updatelease; 9983 else if (o->opt == kDNSOpt_Owner && o->u.owner.vers == 0) owner = o->u.owner; 9984 } 9985 } 9986 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 9987 } 9988 9989 InitializeDNSMessage(&m->omsg.h, msg->h.id, UpdateRespFlags); 9990 9991 if (!updatelease || !owner.HMAC.l[0]) 9992 { 9993 static int msgs = 0; 9994 if (msgs < 100) 9995 { 9996 msgs++; 9997 LogMsg("Refusing sleep proxy registration from %#a:%d:%s%s", srcaddr, mDNSVal16(srcport), 9998 !updatelease ? " No lease" : "", !owner.HMAC.l[0] ? " No owner" : ""); 9999 } 10000 m->omsg.h.flags.b[1] |= kDNSFlag1_RC_FormErr; 10001 } 10002 else if (m->ProxyRecords + msg->h.mDNS_numUpdates > MAX_PROXY_RECORDS) 10003 { 10004 static int msgs = 0; 10005 if (msgs < 100) 10006 { 10007 msgs++; 10008 LogMsg("Refusing sleep proxy registration from %#a:%d: Too many records %d + %d = %d > %d", srcaddr, mDNSVal16(srcport), 10009 m->ProxyRecords, msg->h.mDNS_numUpdates, m->ProxyRecords + msg->h.mDNS_numUpdates, MAX_PROXY_RECORDS); 10010 } 10011 m->omsg.h.flags.b[1] |= kDNSFlag1_RC_Refused; 10012 } 10013 else 10014 { 10015 LogSPS("Received Update for H-MAC %.6a I-MAC %.6a Password %.6a seq %d", &owner.HMAC, &owner.IMAC, &owner.password, owner.seq); 10016 10017 if (updatelease > 24 * 60 * 60) 10018 updatelease = 24 * 60 * 60; 10019 10020 if (updatelease > 0x40000000UL / mDNSPlatformOneSecond) 10021 updatelease = 0x40000000UL / mDNSPlatformOneSecond; 10022 10023 ptr = LocateAuthorities(msg, end); 10024 10025 // Clear any stale TCP keepalive records that may exist 10026 ClearKeepaliveProxyRecords(m, &owner, m->DuplicateRecords, InterfaceID); 10027 ClearKeepaliveProxyRecords(m, &owner, m->ResourceRecords, InterfaceID); 10028 10029 for (i = 0; i < msg->h.mDNS_numUpdates && ptr && ptr < end; i++) 10030 { 10031 ptr = GetLargeResourceRecord(m, msg, ptr, end, InterfaceID, kDNSRecordTypePacketAuth, &m->rec); 10032 if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative) 10033 { 10034 mDNSu16 RDLengthMem = GetRDLengthMem(&m->rec.r.resrec); 10035 AuthRecord *ar = mDNSPlatformMemAllocate(sizeof(AuthRecord) - sizeof(RDataBody) + RDLengthMem); 10036 if (!ar) 10037 { 10038 m->omsg.h.flags.b[1] |= kDNSFlag1_RC_Refused; 10039 break; 10040 } 10041 else 10042 { 10043 mDNSu8 RecordType = m->rec.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask ? kDNSRecordTypeUnique : kDNSRecordTypeShared; 10044 m->rec.r.resrec.rrclass &= ~kDNSClass_UniqueRRSet; 10045 // All stale keepalive records have been flushed prior to this loop. 10046 if (!mDNS_KeepaliveRecord(&m->rec.r.resrec)) 10047 { 10048 ClearIdenticalProxyRecords(m, &owner, m->DuplicateRecords); // Make sure we don't have any old stale duplicates of this record 10049 ClearIdenticalProxyRecords(m, &owner, m->ResourceRecords); 10050 } 10051 mDNS_SetupResourceRecord(ar, mDNSNULL, InterfaceID, m->rec.r.resrec.rrtype, m->rec.r.resrec.rroriginalttl, RecordType, AuthRecordAny, SPSRecordCallback, ar); 10052 AssignDomainName(&ar->namestorage, m->rec.r.resrec.name); 10053 ar->resrec.rdlength = GetRDLength(&m->rec.r.resrec, mDNSfalse); 10054 ar->resrec.rdata->MaxRDLength = RDLengthMem; 10055 mDNSPlatformMemCopy(ar->resrec.rdata->u.data, m->rec.r.resrec.rdata->u.data, RDLengthMem); 10056 ar->ForceMCast = mDNStrue; 10057 ar->WakeUp = owner; 10058 if (m->rec.r.resrec.rrtype == kDNSType_PTR) 10059 { 10060 mDNSs32 t = ReverseMapDomainType(m->rec.r.resrec.name); 10061 if (t == mDNSAddrType_IPv4) GetIPv4FromName(&ar->AddressProxy, m->rec.r.resrec.name); 10062 else if (t == mDNSAddrType_IPv6) GetIPv6FromName(&ar->AddressProxy, m->rec.r.resrec.name); 10063 debugf("mDNSCoreReceiveUpdate: PTR %d %d %#a %s", t, ar->AddressProxy.type, &ar->AddressProxy, ARDisplayString(m, ar)); 10064 if (ar->AddressProxy.type) SetSPSProxyListChanged(InterfaceID); 10065 } 10066 ar->TimeRcvd = m->timenow; 10067 ar->TimeExpire = m->timenow + updatelease * mDNSPlatformOneSecond; 10068 if (m->NextScheduledSPS - ar->TimeExpire > 0) 10069 m->NextScheduledSPS = ar->TimeExpire; 10070 ar->KATimeExpire = 0; 10071 mDNS_Register_internal(m, ar); 10072 10073 m->ProxyRecords++; 10074 mDNS_UpdateAllowSleep(m); 10075 LogSPS("SPS Registered %4d %X %s", m->ProxyRecords, RecordType, ARDisplayString(m,ar)); 10076 } 10077 } 10078 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 10079 } 10080 10081 if (m->omsg.h.flags.b[1] & kDNSFlag1_RC_Mask) 10082 { 10083 LogMsg("Refusing sleep proxy registration from %#a:%d: Out of memory", srcaddr, mDNSVal16(srcport)); 10084 ClearProxyRecords(m, &owner, m->DuplicateRecords); 10085 ClearProxyRecords(m, &owner, m->ResourceRecords); 10086 } 10087 else 10088 { 10089 mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL); 10090 opt.resrec.rrclass = NormalMaxDNSMessageData; 10091 opt.resrec.rdlength = sizeof(rdataOPT); // One option in this OPT record 10092 opt.resrec.rdestimate = sizeof(rdataOPT); 10093 opt.resrec.rdata->u.opt[0].opt = kDNSOpt_Lease; 10094 opt.resrec.rdata->u.opt[0].u.updatelease = updatelease; 10095 p = PutResourceRecordTTLWithLimit(&m->omsg, p, &m->omsg.h.numAdditionals, &opt.resrec, opt.resrec.rroriginalttl, m->omsg.data + AbsoluteMaxDNSMessageData); 10096 } 10097 } 10098 10099 if (p) mDNSSendDNSMessage(m, &m->omsg, p, InterfaceID, m->SPSSocket, srcaddr, srcport, mDNSNULL, mDNSNULL, mDNSfalse); 10100 mDNS_SendKeepalives(m); 10101 } 10102 10103 mDNSlocal void mDNSCoreReceiveUpdateR(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *end, const mDNSAddr *srcaddr, const mDNSInterfaceID InterfaceID) 10104 { 10105 if (InterfaceID) 10106 { 10107 mDNSu32 updatelease = 60 * 60; // If SPS fails to indicate lease time, assume one hour 10108 const mDNSu8 *ptr = LocateOptRR(msg, end, DNSOpt_LeaseData_Space); 10109 if (ptr) 10110 { 10111 ptr = GetLargeResourceRecord(m, msg, ptr, end, 0, kDNSRecordTypePacketAdd, &m->rec); 10112 if (ptr && m->rec.r.resrec.RecordType != kDNSRecordTypePacketNegative && m->rec.r.resrec.rrtype == kDNSType_OPT) 10113 { 10114 const rdataOPT *o; 10115 const rdataOPT *const e = (const rdataOPT *)&m->rec.r.resrec.rdata->u.data[m->rec.r.resrec.rdlength]; 10116 for (o = &m->rec.r.resrec.rdata->u.opt[0]; o < e; o++) 10117 if (o->opt == kDNSOpt_Lease) 10118 { 10119 updatelease = o->u.updatelease; 10120 LogSPS("Sleep Proxy granted lease time %4d seconds, updateid %d, InterfaceID %p", updatelease, mDNSVal16(msg->h.id), InterfaceID); 10121 } 10122 } 10123 m->rec.r.resrec.RecordType = 0; // Clear RecordType to show we're not still using it 10124 } 10125 10126 if (m->CurrentRecord) 10127 LogMsg("mDNSCoreReceiveUpdateR ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord)); 10128 m->CurrentRecord = m->ResourceRecords; 10129 while (m->CurrentRecord) 10130 { 10131 AuthRecord *const rr = m->CurrentRecord; 10132 if (rr->resrec.InterfaceID == InterfaceID || (!rr->resrec.InterfaceID && (rr->ForceMCast || IsLocalDomain(rr->resrec.name)))) 10133 if (mDNSSameOpaque16(rr->updateid, msg->h.id)) 10134 { 10135 // We successfully completed this record's registration on this "InterfaceID". Clear that bit. 10136 // Clear the updateid when we are done sending on all interfaces. 10137 mDNSu32 scopeid = mDNSPlatformInterfaceIndexfromInterfaceID(m, InterfaceID, mDNStrue); 10138 if (scopeid < (sizeof(rr->updateIntID) * mDNSNBBY)) 10139 bit_clr_opaque64(rr->updateIntID, scopeid); 10140 if (mDNSOpaque64IsZero(&rr->updateIntID)) 10141 rr->updateid = zeroID; 10142 rr->expire = NonZeroTime(m->timenow + updatelease * mDNSPlatformOneSecond); 10143 LogSPS("Sleep Proxy %s record %5d 0x%x 0x%x (%d) %s", rr->WakeUp.HMAC.l[0] ? "transferred" : "registered", updatelease, rr->updateIntID.l[1], rr->updateIntID.l[0], mDNSVal16(rr->updateid), ARDisplayString(m,rr)); 10144 if (rr->WakeUp.HMAC.l[0]) 10145 { 10146 rr->WakeUp.HMAC = zeroEthAddr; // Clear HMAC so that mDNS_Deregister_internal doesn't waste packets trying to wake this host 10147 rr->RequireGoodbye = mDNSfalse; // and we don't want to send goodbye for it 10148 mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal); 10149 } 10150 } 10151 // Mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal, because 10152 // new records could have been added to the end of the list as a result of that call. 10153 if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now 10154 m->CurrentRecord = rr->next; 10155 } 10156 10157 // Update the dynamic store with the IP Address and MAC address of the sleep proxy 10158 char *ifname = InterfaceNameForID(m, InterfaceID); 10159 mDNSAddr spsaddr; 10160 mDNSPlatformMemCopy(&spsaddr, srcaddr, sizeof (mDNSAddr)); 10161 mDNSPlatformStoreSPSMACAddr(&spsaddr, ifname); 10162 } 10163 // If we were waiting to go to sleep, then this SPS registration or wide-area record deletion 10164 // may have been the thing we were waiting for, so schedule another check to see if we can sleep now. 10165 if (m->SleepLimit) m->NextScheduledSPRetry = m->timenow; 10166 } 10167 10168 mDNSexport void MakeNegativeCacheRecord(mDNS *const m, CacheRecord *const cr, 10169 const domainname *const name, const mDNSu32 namehash, const mDNSu16 rrtype, const mDNSu16 rrclass, mDNSu32 ttl_seconds, mDNSInterfaceID InterfaceID, DNSServer *dnsserver) 10170 { 10171 if (cr == &m->rec.r && m->rec.r.resrec.RecordType) 10172 { 10173 LogMsg("MakeNegativeCacheRecord: m->rec appears to be already in use for %s", CRDisplayString(m, &m->rec.r)); 10174 #if ForceAlerts 10175 *(long*)0 = 0; 10176 #endif 10177 } 10178 10179 // Create empty resource record 10180 cr->resrec.RecordType = kDNSRecordTypePacketNegative; 10181 cr->resrec.InterfaceID = InterfaceID; 10182 cr->resrec.rDNSServer = dnsserver; 10183 cr->resrec.name = name; // Will be updated to point to cg->name when we call CreateNewCacheEntry 10184 cr->resrec.rrtype = rrtype; 10185 cr->resrec.rrclass = rrclass; 10186 cr->resrec.rroriginalttl = ttl_seconds; 10187 cr->resrec.rdlength = 0; 10188 cr->resrec.rdestimate = 0; 10189 cr->resrec.namehash = namehash; 10190 cr->resrec.rdatahash = 0; 10191 cr->resrec.rdata = (RData*)&cr->smallrdatastorage; 10192 cr->resrec.rdata->MaxRDLength = 0; 10193 10194 cr->NextInKAList = mDNSNULL; 10195 cr->TimeRcvd = m->timenow; 10196 cr->DelayDelivery = 0; 10197 cr->NextRequiredQuery = m->timenow; 10198 cr->LastUsed = m->timenow; 10199 cr->CRActiveQuestion = mDNSNULL; 10200 cr->UnansweredQueries = 0; 10201 cr->LastUnansweredTime = 0; 10202 #if ENABLE_MULTI_PACKET_QUERY_SNOOPING 10203 cr->MPUnansweredQ = 0; 10204 cr->MPLastUnansweredQT = 0; 10205 cr->MPUnansweredKA = 0; 10206 cr->MPExpectingKA = mDNSfalse; 10207 #endif 10208 cr->NextInCFList = mDNSNULL; 10209 cr->nsec = mDNSNULL; 10210 cr->soa = mDNSNULL; 10211 cr->CRDNSSECQuestion = 0; 10212 // Initialize to the basic one and the caller can set it to more 10213 // specific based on the response if any 10214 cr->responseFlags = ResponseFlags; 10215 } 10216 10217 mDNSexport void mDNSCoreReceive(mDNS *const m, void *const pkt, const mDNSu8 *const end, 10218 const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, 10219 const mDNSInterfaceID InterfaceID) 10220 { 10221 mDNSInterfaceID ifid = InterfaceID; 10222 DNSMessage *msg = (DNSMessage *)pkt; 10223 const mDNSu8 StdQ = kDNSFlag0_QR_Query | kDNSFlag0_OP_StdQuery; 10224 const mDNSu8 StdR = kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery; 10225 const mDNSu8 UpdQ = kDNSFlag0_QR_Query | kDNSFlag0_OP_Update; 10226 const mDNSu8 UpdR = kDNSFlag0_QR_Response | kDNSFlag0_OP_Update; 10227 mDNSu8 QR_OP; 10228 mDNSu8 *ptr = mDNSNULL; 10229 mDNSBool TLS = (dstaddr == (mDNSAddr *)1); // For debug logs: dstaddr = 0 means TCP; dstaddr = 1 means TLS 10230 if (TLS) dstaddr = mDNSNULL; 10231 10232 #ifndef UNICAST_DISABLED 10233 if (mDNSSameAddress(srcaddr, &m->Router)) 10234 { 10235 #ifdef _LEGACY_NAT_TRAVERSAL_ 10236 if (mDNSSameIPPort(srcport, SSDPPort) || (m->SSDPSocket && mDNSSameIPPort(dstport, m->SSDPSocket->port))) 10237 { 10238 mDNS_Lock(m); 10239 LNT_ConfigureRouterInfo(m, InterfaceID, pkt, (mDNSu16)(end - (mDNSu8 *)pkt)); 10240 mDNS_Unlock(m); 10241 return; 10242 } 10243 #endif 10244 if (mDNSSameIPPort(srcport, NATPMPPort)) 10245 { 10246 mDNS_Lock(m); 10247 uDNS_ReceiveNATPacket(m, InterfaceID, pkt, (mDNSu16)(end - (mDNSu8 *)pkt)); 10248 mDNS_Unlock(m); 10249 return; 10250 } 10251 } 10252 #ifdef _LEGACY_NAT_TRAVERSAL_ 10253 else if (m->SSDPSocket && mDNSSameIPPort(dstport, m->SSDPSocket->port)) { debugf("Ignoring SSDP response from %#a:%d", srcaddr, mDNSVal16(srcport)); return; } 10254 #endif 10255 10256 #endif 10257 if ((unsigned)(end - (mDNSu8 *)pkt) < sizeof(DNSMessageHeader)) 10258 { 10259 LogMsg("DNS Message from %#a:%d to %#a:%d length %d too short", srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), end - (mDNSu8 *)pkt); 10260 return; 10261 } 10262 QR_OP = (mDNSu8)(msg->h.flags.b[0] & kDNSFlag0_QROP_Mask); 10263 // Read the integer parts which are in IETF byte-order (MSB first, LSB second) 10264 ptr = (mDNSu8 *)&msg->h.numQuestions; 10265 msg->h.numQuestions = (mDNSu16)((mDNSu16)ptr[0] << 8 | ptr[1]); 10266 msg->h.numAnswers = (mDNSu16)((mDNSu16)ptr[2] << 8 | ptr[3]); 10267 msg->h.numAuthorities = (mDNSu16)((mDNSu16)ptr[4] << 8 | ptr[5]); 10268 msg->h.numAdditionals = (mDNSu16)((mDNSu16)ptr[6] << 8 | ptr[7]); 10269 10270 if (!m) { LogMsg("mDNSCoreReceive ERROR m is NULL"); return; } 10271 10272 // We use zero addresses and all-ones addresses at various places in the code to indicate special values like "no address" 10273 // If we accept and try to process a packet with zero or all-ones source address, that could really mess things up 10274 if (srcaddr && !mDNSAddressIsValid(srcaddr)) { debugf("mDNSCoreReceive ignoring packet from %#a", srcaddr); return; } 10275 10276 mDNS_Lock(m); 10277 m->PktNum++; 10278 if (mDNSOpaque16IsZero(msg->h.id)) 10279 { 10280 m->MPktNum++; 10281 #if APPLE_OSX_mDNSResponder 10282 // Track the number of multicast packets received from a source outside our subnet. 10283 // Check the destination address to avoid accounting for spurious packets that 10284 // comes in with message id zero. 10285 if (!mDNS_AddressIsLocalSubnet(m, InterfaceID, srcaddr, mDNSNULL) && 10286 mDNSAddressIsAllDNSLinkGroup(dstaddr)) 10287 { 10288 m->RemoteSubnet++; 10289 } 10290 #endif // #if APPLE_OSX_mDNSResponder 10291 } 10292 10293 #ifndef UNICAST_DISABLED 10294 if (!dstaddr || (!mDNSAddressIsAllDNSLinkGroup(dstaddr) && (QR_OP == StdR || QR_OP == UpdR))) 10295 if (!mDNSOpaque16IsZero(msg->h.id)) // uDNS_ReceiveMsg only needs to get real uDNS responses, not "QU" mDNS responses 10296 { 10297 ifid = mDNSInterface_Any; 10298 if (mDNS_PacketLoggingEnabled) 10299 DumpPacket(m, mStatus_NoError, mDNSfalse, TLS ? "TLS" : !dstaddr ? "TCP" : "UDP", srcaddr, srcport, dstaddr, dstport, msg, end); 10300 uDNS_ReceiveMsg(m, msg, end, srcaddr, srcport); 10301 // Note: mDNSCore also needs to get access to received unicast responses 10302 } 10303 #endif 10304 if (QR_OP == StdQ) mDNSCoreReceiveQuery (m, msg, end, srcaddr, srcport, dstaddr, dstport, ifid); 10305 else if (QR_OP == StdR) mDNSCoreReceiveResponse(m, msg, end, srcaddr, srcport, dstaddr, dstport, ifid); 10306 else if (QR_OP == UpdQ) mDNSCoreReceiveUpdate (m, msg, end, srcaddr, srcport, dstaddr, dstport, InterfaceID); 10307 else if (QR_OP == UpdR) mDNSCoreReceiveUpdateR (m, msg, end, srcaddr, InterfaceID); 10308 else 10309 { 10310 LogMsg("Unknown DNS packet type %02X%02X from %#-15a:%-5d to %#-15a:%-5d length %d on %p (ignored)", 10311 msg->h.flags.b[0], msg->h.flags.b[1], srcaddr, mDNSVal16(srcport), dstaddr, mDNSVal16(dstport), end - (mDNSu8 *)pkt, InterfaceID); 10312 if (mDNS_LoggingEnabled) 10313 { 10314 int i = 0; 10315 while (i<end - (mDNSu8 *)pkt) 10316 { 10317 char buffer[128]; 10318 char *p = buffer + mDNS_snprintf(buffer, sizeof(buffer), "%04X", i); 10319 do if (i<end - (mDNSu8 *)pkt) p += mDNS_snprintf(p, sizeof(buffer), " %02X", ((mDNSu8 *)pkt)[i]);while (++i & 15); 10320 LogInfo("%s", buffer); 10321 } 10322 } 10323 } 10324 // Packet reception often causes a change to the task list: 10325 // 1. Inbound queries can cause us to need to send responses 10326 // 2. Conflicing response packets received from other hosts can cause us to need to send defensive responses 10327 // 3. Other hosts announcing deletion of shared records can cause us to need to re-assert those records 10328 // 4. Response packets that answer questions may cause our client to issue new questions 10329 mDNS_Unlock(m); 10330 } 10331 10332 // *************************************************************************** 10333 #if COMPILER_LIKES_PRAGMA_MARK 10334 #pragma mark - 10335 #pragma mark - Searcher Functions 10336 #endif 10337 10338 // Targets are considered the same if both queries are untargeted, or 10339 // if both are targeted to the same address+port 10340 // (If Target address is zero, TargetPort is undefined) 10341 #define SameQTarget(A,B) (((A)->Target.type == mDNSAddrType_None && (B)->Target.type == mDNSAddrType_None) || \ 10342 (mDNSSameAddress(& (A)->Target, & (B)->Target) && mDNSSameIPPort((A)->TargetPort, (B)->TargetPort))) 10343 10344 // Note: We explicitly disallow making a public query be a duplicate of a private one. This is to avoid the 10345 // circular deadlock where a client does a query for something like "dns-sd -Q _dns-query-tls._tcp.company.com SRV" 10346 // and we have a key for company.com, so we try to locate the private query server for company.com, which necessarily entails 10347 // doing a standard DNS query for the _dns-query-tls._tcp SRV record for company.com. If we make the latter (public) query 10348 // a duplicate of the former (private) query, then it will block forever waiting for an answer that will never come. 10349 // 10350 // We keep SuppressUnusable questions separate so that we can return a quick response to them and not get blocked behind 10351 // the queries that are not marked SuppressUnusable. But if the query is not suppressed, they are treated the same as 10352 // non-SuppressUnusable questions. This should be fine as the goal of SuppressUnusable is to return quickly only if it 10353 // is suppressed. If it is not suppressed, we do try all the DNS servers for valid answers like any other question. 10354 // The main reason for this design is that cache entries point to a *single* question and that question is responsible 10355 // for keeping the cache fresh as long as it is active. Having multiple active question for a single cache entry 10356 // breaks this design principle. 10357 // 10358 10359 // If IsLLQ(Q) is true, it means the question is both: 10360 // (a) long-lived and 10361 // (b) being performed by a unicast DNS long-lived query (either full LLQ, or polling) 10362 // for multicast questions, we don't want to treat LongLived as anything special 10363 #define IsLLQ(Q) ((Q)->LongLived && !mDNSOpaque16IsZero((Q)->TargetQID)) 10364 #define IsAWDLIncluded(Q) (((Q)->flags & kDNSServiceFlagsIncludeAWDL) != 0) 10365 10366 mDNSlocal DNSQuestion *FindDuplicateQuestion(const mDNS *const m, const DNSQuestion *const question) 10367 { 10368 DNSQuestion *q; 10369 // Note: A question can only be marked as a duplicate of one that occurs *earlier* in the list. 10370 // This prevents circular references, where two questions are each marked as a duplicate of the other. 10371 // Accordingly, we break out of the loop when we get to 'question', because there's no point searching 10372 // further in the list. 10373 for (q = m->Questions; q && q != question; q=q->next) // Scan our list for another question 10374 if (q->InterfaceID == question->InterfaceID && // with the same InterfaceID, 10375 SameQTarget(q, question) && // and same unicast/multicast target settings 10376 q->qtype == question->qtype && // type, 10377 q->qclass == question->qclass && // class, 10378 IsLLQ(q) == IsLLQ(question) && // and long-lived status matches 10379 (!q->AuthInfo || question->AuthInfo) && // to avoid deadlock, don't make public query dup of a private one 10380 (q->AnonInfo == question->AnonInfo) && // Anonymous query not a dup of normal query 10381 (q->SuppressQuery == question->SuppressQuery) && // Questions that are suppressed/not suppressed 10382 (q->ValidationRequired == question->ValidationRequired) && // Questions that require DNSSEC validation 10383 (q->ValidatingResponse == question->ValidatingResponse) && // Questions that are validating responses using DNSSEC 10384 (q->DisallowPID == question->DisallowPID) && // Disallowing a PID should not affect a PID that is allowed 10385 (q->BrowseThreshold == question->BrowseThreshold) && // browse thresholds must match 10386 q->qnamehash == question->qnamehash && 10387 (IsAWDLIncluded(q) == IsAWDLIncluded(question)) && // Inclusion of AWDL interface must match 10388 SameDomainName(&q->qname, &question->qname)) // and name 10389 return(q); 10390 return(mDNSNULL); 10391 } 10392 10393 // This is called after a question is deleted, in case other identical questions were being suppressed as duplicates 10394 mDNSlocal void UpdateQuestionDuplicates(mDNS *const m, DNSQuestion *const question) 10395 { 10396 DNSQuestion *q; 10397 DNSQuestion *first = mDNSNULL; 10398 10399 // This is referring to some other question as duplicate. No other question can refer to this 10400 // question as a duplicate. 10401 if (question->DuplicateOf) 10402 { 10403 LogInfo("UpdateQuestionDuplicates: question %p %##s (%s) duplicate of %p %##s (%s)", 10404 question, question->qname.c, DNSTypeName(question->qtype), 10405 question->DuplicateOf, question->DuplicateOf->qname.c, DNSTypeName(question->DuplicateOf->qtype)); 10406 return; 10407 } 10408 10409 for (q = m->Questions; q; q=q->next) // Scan our list of questions 10410 if (q->DuplicateOf == question) // To see if any questions were referencing this as their duplicate 10411 { 10412 q->DuplicateOf = first; 10413 if (!first) 10414 { 10415 first = q; 10416 // If q used to be a duplicate, but now is not, 10417 // then inherit the state from the question that's going away 10418 q->LastQTime = question->LastQTime; 10419 q->ThisQInterval = question->ThisQInterval; 10420 q->ExpectUnicastResp = question->ExpectUnicastResp; 10421 q->LastAnswerPktNum = question->LastAnswerPktNum; 10422 q->RecentAnswerPkts = question->RecentAnswerPkts; 10423 q->RequestUnicast = question->RequestUnicast; 10424 q->LastQTxTime = question->LastQTxTime; 10425 q->CNAMEReferrals = question->CNAMEReferrals; 10426 q->nta = question->nta; 10427 q->servAddr = question->servAddr; 10428 q->servPort = question->servPort; 10429 q->qDNSServer = question->qDNSServer; 10430 q->validDNSServers = question->validDNSServers; 10431 q->unansweredQueries = question->unansweredQueries; 10432 q->noServerResponse = question->noServerResponse; 10433 q->triedAllServersOnce = question->triedAllServersOnce; 10434 10435 q->TargetQID = question->TargetQID; 10436 if (q->LocalSocket) 10437 { 10438 mDNSPlatformUDPClose(q->LocalSocket); 10439 } 10440 10441 q->LocalSocket = question->LocalSocket; 10442 10443 q->state = question->state; 10444 // q->tcp = question->tcp; 10445 q->ReqLease = question->ReqLease; 10446 q->expire = question->expire; 10447 q->ntries = question->ntries; 10448 q->id = question->id; 10449 10450 question->LocalSocket = mDNSNULL; 10451 question->nta = mDNSNULL; // If we've got a GetZoneData in progress, transfer it to the newly active question 10452 // question->tcp = mDNSNULL; 10453 10454 if (q->LocalSocket) 10455 debugf("UpdateQuestionDuplicates transferred LocalSocket pointer for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 10456 10457 if (q->nta) 10458 { 10459 LogInfo("UpdateQuestionDuplicates transferred nta pointer for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 10460 q->nta->ZoneDataContext = q; 10461 } 10462 10463 // Need to work out how to safely transfer this state too -- appropriate context pointers need to be updated or the code will crash 10464 if (question->tcp) LogInfo("UpdateQuestionDuplicates did not transfer tcp pointer"); 10465 10466 if (question->state == LLQ_Established) 10467 { 10468 LogInfo("UpdateQuestionDuplicates transferred LLQ state for %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 10469 question->state = 0; // Must zero question->state, or mDNS_StopQuery_internal will clean up and cancel our LLQ from the server 10470 } 10471 10472 SetNextQueryTime(m,q); 10473 } 10474 } 10475 } 10476 10477 mDNSexport McastResolver *mDNS_AddMcastResolver(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, mDNSu32 timeout) 10478 { 10479 McastResolver **p = &m->McastResolvers; 10480 McastResolver *tmp = mDNSNULL; 10481 10482 if (!d) d = (const domainname *)""; 10483 10484 LogInfo("mDNS_AddMcastResolver: Adding %##s, InterfaceID %p, timeout %u", d->c, interface, timeout); 10485 10486 mDNS_CheckLock(m); 10487 10488 while (*p) // Check if we already have this {interface, domain} tuple registered 10489 { 10490 if ((*p)->interface == interface && SameDomainName(&(*p)->domain, d)) 10491 { 10492 if (!((*p)->flags & DNSServer_FlagDelete)) LogMsg("Note: Mcast Resolver domain %##s (%p) registered more than once", d->c, interface); 10493 (*p)->flags &= ~DNSServer_FlagDelete; 10494 tmp = *p; 10495 *p = tmp->next; 10496 tmp->next = mDNSNULL; 10497 } 10498 else 10499 p=&(*p)->next; 10500 } 10501 10502 if (tmp) *p = tmp; // move to end of list, to ensure ordering from platform layer 10503 else 10504 { 10505 // allocate, add to list 10506 *p = mDNSPlatformMemAllocate(sizeof(**p)); 10507 if (!*p) LogMsg("mDNS_AddMcastResolver: ERROR!! - malloc"); 10508 else 10509 { 10510 (*p)->interface = interface; 10511 (*p)->flags = DNSServer_FlagNew; 10512 (*p)->timeout = timeout; 10513 AssignDomainName(&(*p)->domain, d); 10514 (*p)->next = mDNSNULL; 10515 } 10516 } 10517 return(*p); 10518 } 10519 10520 mDNSinline mDNSs32 PenaltyTimeForServer(mDNS *m, DNSServer *server) 10521 { 10522 mDNSs32 ptime = 0; 10523 if (server->penaltyTime != 0) 10524 { 10525 ptime = server->penaltyTime - m->timenow; 10526 if (ptime < 0) 10527 { 10528 // This should always be a positive value between 0 and DNSSERVER_PENALTY_TIME 10529 // If it does not get reset in ResetDNSServerPenalties for some reason, we do it 10530 // here 10531 LogMsg("PenaltyTimeForServer: PenaltyTime negative %d, (server penaltyTime %d, timenow %d) resetting the penalty", 10532 ptime, server->penaltyTime, m->timenow); 10533 server->penaltyTime = 0; 10534 ptime = 0; 10535 } 10536 } 10537 return ptime; 10538 } 10539 10540 //Checks to see whether the newname is a better match for the name, given the best one we have 10541 //seen so far (given in bestcount). 10542 //Returns -1 if the newname is not a better match 10543 //Returns 0 if the newname is the same as the old match 10544 //Returns 1 if the newname is a better match 10545 mDNSlocal int BetterMatchForName(const domainname *name, int namecount, const domainname *newname, int newcount, 10546 int bestcount) 10547 { 10548 // If the name contains fewer labels than the new server's domain or the new name 10549 // contains fewer labels than the current best, then it can't possibly be a better match 10550 if (namecount < newcount || newcount < bestcount) return -1; 10551 10552 // If there is no match, return -1 and the caller will skip this newname for 10553 // selection 10554 // 10555 // If we find a match and the number of labels is the same as bestcount, then 10556 // we return 0 so that the caller can do additional logic to pick one of 10557 // the best based on some other factors e.g., penaltyTime 10558 // 10559 // If we find a match and the number of labels is more than bestcount, then we 10560 // return 1 so that the caller can pick this over the old one. 10561 // 10562 // Note: newcount can either be equal or greater than bestcount beause of the 10563 // check above. 10564 10565 if (SameDomainName(SkipLeadingLabels(name, namecount - newcount), newname)) 10566 return bestcount == newcount ? 0 : 1; 10567 else 10568 return -1; 10569 } 10570 10571 // Normally, we have McastResolvers for .local, in-addr.arpa and ip6.arpa. But there 10572 // can be queries that can forced to multicast (ForceMCast) even though they don't end in these 10573 // names. In that case, we give a default timeout of 5 seconds 10574 #define DEFAULT_MCAST_TIMEOUT 5 10575 mDNSlocal mDNSu32 GetTimeoutForMcastQuestion(mDNS *m, DNSQuestion *question) 10576 { 10577 McastResolver *curmatch = mDNSNULL; 10578 int bestmatchlen = -1, namecount = CountLabels(&question->qname); 10579 McastResolver *curr; 10580 int bettermatch, currcount; 10581 for (curr = m->McastResolvers; curr; curr = curr->next) 10582 { 10583 currcount = CountLabels(&curr->domain); 10584 bettermatch = BetterMatchForName(&question->qname, namecount, &curr->domain, currcount, bestmatchlen); 10585 // Take the first best match. If there are multiple equally good matches (bettermatch = 0), we take 10586 // the timeout value from the first one 10587 if (bettermatch == 1) 10588 { 10589 curmatch = curr; 10590 bestmatchlen = currcount; 10591 } 10592 } 10593 LogInfo("GetTimeoutForMcastQuestion: question %##s curmatch %p, Timeout %d", question->qname.c, curmatch, 10594 curmatch ? curmatch->timeout : DEFAULT_MCAST_TIMEOUT); 10595 return ( curmatch ? curmatch->timeout : DEFAULT_MCAST_TIMEOUT); 10596 } 10597 10598 // Returns true if it is a Domain Enumeration Query 10599 mDNSexport mDNSBool DomainEnumQuery(const domainname *qname) 10600 { 10601 const mDNSu8 *mDNS_DEQLabels[] = { (const mDNSu8 *)"\001b", (const mDNSu8 *)"\002db", (const mDNSu8 *)"\002lb", 10602 (const mDNSu8 *)"\001r", (const mDNSu8 *)"\002dr", (const mDNSu8 *)mDNSNULL, }; 10603 const domainname *d = qname; 10604 const mDNSu8 *label; 10605 int i = 0; 10606 10607 // We need at least 3 labels (DEQ prefix) + one more label to make a meaningful DE query 10608 if (CountLabels(qname) < 4) { debugf("DomainEnumQuery: question %##s, not enough labels", qname->c); return mDNSfalse; } 10609 10610 label = (const mDNSu8 *)d; 10611 while (mDNS_DEQLabels[i] != (const mDNSu8 *)mDNSNULL) 10612 { 10613 if (SameDomainLabel(mDNS_DEQLabels[i], label)) {debugf("DomainEnumQuery: DEQ %##s, label1 match", qname->c); break;} 10614 i++; 10615 } 10616 if (mDNS_DEQLabels[i] == (const mDNSu8 *)mDNSNULL) 10617 { 10618 debugf("DomainEnumQuery: Not a DEQ %##s, label1 mismatch", qname->c); 10619 return mDNSfalse; 10620 } 10621 debugf("DomainEnumQuery: DEQ %##s, label1 match", qname->c); 10622 10623 // CountLabels already verified the number of labels 10624 d = (const domainname *)(d->c + 1 + d->c[0]); // Second Label 10625 label = (const mDNSu8 *)d; 10626 if (!SameDomainLabel(label, (const mDNSu8 *)"\007_dns-sd")) 10627 { 10628 debugf("DomainEnumQuery: Not a DEQ %##s, label2 mismatch", qname->c); 10629 return(mDNSfalse); 10630 } 10631 debugf("DomainEnumQuery: DEQ %##s, label2 match", qname->c); 10632 10633 d = (const domainname *)(d->c + 1 + d->c[0]); // Third Label 10634 label = (const mDNSu8 *)d; 10635 if (!SameDomainLabel(label, (const mDNSu8 *)"\004_udp")) 10636 { 10637 debugf("DomainEnumQuery: Not a DEQ %##s, label3 mismatch", qname->c); 10638 return(mDNSfalse); 10639 } 10640 debugf("DomainEnumQuery: DEQ %##s, label3 match", qname->c); 10641 10642 debugf("DomainEnumQuery: Question %##s is a Domain Enumeration query", qname->c); 10643 10644 return mDNStrue; 10645 } 10646 10647 // Note: InterfaceID is the InterfaceID of the question 10648 mDNSlocal mDNSBool DNSServerMatch(DNSServer *d, mDNSInterfaceID InterfaceID, mDNSs32 ServiceID) 10649 { 10650 // 1) Unscoped questions (NULL InterfaceID) should consider *only* unscoped DNSServers ( DNSServer 10651 // with "scoped" set to kScopeNone) 10652 // 10653 // 2) Scoped questions (non-NULL InterfaceID) should consider *only* scoped DNSServers (DNSServer 10654 // with "scoped" set to kScopeInterfaceId) and their InterfaceIDs should match. 10655 // 10656 // 3) Scoped questions (non-zero ServiceID) should consider *only* scoped DNSServers (DNSServer 10657 // with "scoped" set to kScopeServiceID) and their ServiceIDs should match. 10658 // 10659 // The first condition in the "if" statement checks to see if both the question and the DNSServer are 10660 // unscoped. The question is unscoped only if InterfaceID is zero and ServiceID is -1. 10661 // 10662 // If the first condition fails, following are the possible cases (the notes below are using 10663 // InterfaceID for discussion and the same holds good for ServiceID): 10664 // 10665 // - DNSServer is not scoped, InterfaceID is not NULL - we should skip the current DNSServer entry 10666 // as scoped questions should not pick non-scoped DNSServer entry (Refer to (2) above). 10667 // 10668 // - DNSServer is scoped, InterfaceID is NULL - we should skip the current DNSServer entry as 10669 // unscoped question should not match scoped DNSServer (Refer to (1) above). The InterfaceID check 10670 // would fail in this case. 10671 // 10672 // - DNSServer is scoped and InterfaceID is not NULL - the InterfaceID of the question and the DNSServer 10673 // should match (Refer to (2) above). 10674 // 10675 // Note: mDNSInterface_Unicast is used only by .local unicast questions and are treated as unscoped. 10676 // If a question is scoped both to InterfaceID and ServiceID, the question will be scoped to InterfaceID. 10677 10678 if (((d->scoped == kScopeNone) && ((!InterfaceID && ServiceID == -1) || InterfaceID == mDNSInterface_Unicast)) || 10679 ((d->scoped == kScopeInterfaceID) && d->interface == InterfaceID) || 10680 ((d->scoped == kScopeServiceID) && d->serviceID == ServiceID)) 10681 { 10682 return mDNStrue; 10683 } 10684 return mDNSfalse; 10685 } 10686 10687 // Sets all the Valid DNS servers for a question 10688 mDNSexport mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question) 10689 { 10690 int bestmatchlen = -1, namecount = CountLabels(&question->qname); 10691 DNSServer *curr; 10692 int bettermatch, currcount; 10693 int index = 0; 10694 mDNSu32 timeout = 0; 10695 mDNSBool DEQuery; 10696 10697 question->validDNSServers = zeroOpaque64; 10698 DEQuery = DomainEnumQuery(&question->qname); 10699 for (curr = m->DNSServers; curr; curr = curr->next) 10700 { 10701 debugf("SetValidDNSServers: Parsing DNS server Address %#a (Domain %##s), Scope: %d", &curr->addr, curr->domain.c, curr->scoped); 10702 // skip servers that will soon be deleted 10703 if (curr->flags & DNSServer_FlagDelete) 10704 { 10705 debugf("SetValidDNSServers: Delete set for index %d, DNS server %#a (Domain %##s), scoped %d", index, &curr->addr, curr->domain.c, curr->scoped); 10706 continue; 10707 } 10708 10709 // This happens normally when you unplug the interface where we reset the interfaceID to mDNSInterface_Any for all 10710 // the DNS servers whose scope match the interfaceID. Few seconds later, we also receive the updated DNS configuration. 10711 // But any questions that has mDNSInterface_Any scope that are started/restarted before we receive the update 10712 // (e.g., CheckSuppressUnusableQuestions is called when interfaces are deregistered with the core) should not 10713 // match the scoped entries by mistake. 10714 // 10715 // Note: DNS configuration change will help pick the new dns servers but currently it does not affect the timeout 10716 10717 if (curr->scoped && curr->interface == mDNSInterface_Any) 10718 { 10719 debugf("SetValidDNSServers: Scoped DNS server %#a (Domain %##s) with Interface Any", &curr->addr, curr->domain.c); 10720 continue; 10721 } 10722 10723 currcount = CountLabels(&curr->domain); 10724 if ((!DEQuery || !curr->cellIntf) && DNSServerMatch(curr, question->InterfaceID, question->ServiceID)) 10725 { 10726 bettermatch = BetterMatchForName(&question->qname, namecount, &curr->domain, currcount, bestmatchlen); 10727 10728 // If we found a better match (bettermatch == 1) then clear all the bits 10729 // corresponding to the old DNSServers that we have may set before and start fresh. 10730 // If we find an equal match, then include that DNSServer also by setting the corresponding 10731 // bit 10732 if ((bettermatch == 1) || (bettermatch == 0)) 10733 { 10734 bestmatchlen = currcount; 10735 if (bettermatch) 10736 { 10737 debugf("SetValidDNSServers: Resetting all the bits"); 10738 question->validDNSServers = zeroOpaque64; 10739 timeout = 0; 10740 } 10741 debugf("SetValidDNSServers: question %##s Setting the bit for DNS server Address %#a (Domain %##s), Scoped:%d index %d," 10742 " Timeout %d, interface %p", question->qname.c, &curr->addr, curr->domain.c, curr->scoped, index, curr->timeout, 10743 curr->interface); 10744 timeout += curr->timeout; 10745 if (DEQuery) 10746 debugf("DomainEnumQuery: Question %##s, DNSServer %#a, cell %d", question->qname.c, &curr->addr, curr->cellIntf); 10747 bit_set_opaque64(question->validDNSServers, index); 10748 } 10749 } 10750 index++; 10751 } 10752 question->noServerResponse = 0; 10753 10754 debugf("SetValidDNSServers: ValidDNSServer bits 0x%x%x for question %p %##s (%s)", 10755 question->validDNSServers.l[1], question->validDNSServers.l[0], question, question->qname.c, DNSTypeName(question->qtype)); 10756 // If there are no matching resolvers, then use the default timeout value. 10757 // For ProxyQuestion, shorten the timeout so that dig does not timeout on us in case of no response. 10758 return ((question->ProxyQuestion || question->ValidatingResponse) ? DEFAULT_UDNSSEC_TIMEOUT : timeout ? timeout : DEFAULT_UDNS_TIMEOUT); 10759 } 10760 10761 // Get the Best server that matches a name. If you find penalized servers, look for the one 10762 // that will come out of the penalty box soon 10763 mDNSlocal DNSServer *GetBestServer(mDNS *m, const domainname *name, mDNSInterfaceID InterfaceID, mDNSs32 ServiceID, mDNSOpaque64 validBits, 10764 int *selected, mDNSBool nameMatch) 10765 { 10766 DNSServer *curmatch = mDNSNULL; 10767 int bestmatchlen = -1, namecount = name ? CountLabels(name) : 0; 10768 DNSServer *curr; 10769 mDNSs32 bestPenaltyTime, currPenaltyTime; 10770 int bettermatch, currcount; 10771 int index = 0; 10772 int currindex = -1; 10773 10774 debugf("GetBestServer: ValidDNSServer bits 0x%x%x", validBits.l[1], validBits.l[0]); 10775 bestPenaltyTime = DNSSERVER_PENALTY_TIME + 1; 10776 for (curr = m->DNSServers; curr; curr = curr->next) 10777 { 10778 // skip servers that will soon be deleted 10779 if (curr->flags & DNSServer_FlagDelete) 10780 { 10781 debugf("GetBestServer: Delete set for index %d, DNS server %#a (Domain %##s), scoped %d", index, &curr->addr, curr->domain.c, curr->scoped); 10782 continue; 10783 } 10784 10785 // Check if this is a valid DNSServer 10786 if (!bit_get_opaque64(validBits, index)) 10787 { 10788 debugf("GetBestServer: continuing for index %d", index); 10789 index++; 10790 continue; 10791 } 10792 10793 currcount = CountLabels(&curr->domain); 10794 currPenaltyTime = PenaltyTimeForServer(m, curr); 10795 10796 debugf("GetBestServer: Address %#a (Domain %##s), PenaltyTime(abs) %d, PenaltyTime(rel) %d", 10797 &curr->addr, curr->domain.c, curr->penaltyTime, currPenaltyTime); 10798 10799 // If there are multiple best servers for a given question, we will pick the first one 10800 // if none of them are penalized. If some of them are penalized in that list, we pick 10801 // the least penalized one. BetterMatchForName walks through all best matches and 10802 // "currPenaltyTime < bestPenaltyTime" check lets us either pick the first best server 10803 // in the list when there are no penalized servers and least one among them 10804 // when there are some penalized servers. 10805 10806 if (DNSServerMatch(curr, InterfaceID, ServiceID)) 10807 { 10808 10809 // If we know that all the names are already equally good matches, then skip calling BetterMatchForName. 10810 // This happens when we initially walk all the DNS servers and set the validity bit on the question. 10811 // Actually we just need PenaltyTime match, but for the sake of readability we just skip the expensive 10812 // part and still do some redundant steps e.g., InterfaceID match 10813 10814 if (nameMatch) 10815 bettermatch = BetterMatchForName(name, namecount, &curr->domain, currcount, bestmatchlen); 10816 else 10817 bettermatch = 0; 10818 10819 // If we found a better match (bettermatch == 1) then we don't need to 10820 // compare penalty times. But if we found an equal match, then we compare 10821 // the penalty times to pick a better match 10822 10823 if ((bettermatch == 1) || ((bettermatch == 0) && currPenaltyTime < bestPenaltyTime)) 10824 { 10825 currindex = index; 10826 curmatch = curr; 10827 bestmatchlen = currcount; 10828 bestPenaltyTime = currPenaltyTime; 10829 } 10830 } 10831 index++; 10832 } 10833 if (selected) *selected = currindex; 10834 return curmatch; 10835 } 10836 10837 // Look up a DNS Server, matching by name and InterfaceID 10838 mDNSlocal DNSServer *GetServerForName(mDNS *m, const domainname *name, mDNSInterfaceID InterfaceID, mDNSs32 ServiceID) 10839 { 10840 DNSServer *curmatch = mDNSNULL; 10841 char *ifname = mDNSNULL; // for logging purposes only 10842 mDNSOpaque64 allValid; 10843 10844 if ((InterfaceID == mDNSInterface_Unicast) || (InterfaceID == mDNSInterface_LocalOnly)) 10845 InterfaceID = mDNSNULL; 10846 10847 if (InterfaceID) ifname = InterfaceNameForID(m, InterfaceID); 10848 10849 // By passing in all ones, we make sure that every DNS server is considered 10850 allValid.l[0] = allValid.l[1] = 0xFFFFFFFF; 10851 10852 curmatch = GetBestServer(m, name, InterfaceID, ServiceID, allValid, mDNSNULL, mDNStrue); 10853 10854 if (curmatch != mDNSNULL) 10855 LogInfo("GetServerForName: DNS server %#a:%d (Penalty Time Left %d) (Scope %s:%p) found for name %##s", &curmatch->addr, 10856 mDNSVal16(curmatch->port), (curmatch->penaltyTime ? (curmatch->penaltyTime - m->timenow) : 0), ifname ? ifname : "None", 10857 InterfaceID, name); 10858 else 10859 LogInfo("GetServerForName: no DNS server (Scope %s:%p) found for name %##s", ifname ? ifname : "None", InterfaceID, name); 10860 10861 return(curmatch); 10862 } 10863 10864 // Look up a DNS Server for a question within its valid DNSServer bits 10865 mDNSexport DNSServer *GetServerForQuestion(mDNS *m, DNSQuestion *question) 10866 { 10867 DNSServer *curmatch = mDNSNULL; 10868 char *ifname = mDNSNULL; // for logging purposes only 10869 mDNSInterfaceID InterfaceID = question->InterfaceID; 10870 const domainname *name = &question->qname; 10871 int currindex; 10872 10873 if ((InterfaceID == mDNSInterface_Unicast) || (InterfaceID == mDNSInterface_LocalOnly)) 10874 InterfaceID = mDNSNULL; 10875 10876 if (InterfaceID) 10877 ifname = InterfaceNameForID(m, InterfaceID); 10878 10879 if (!mDNSOpaque64IsZero(&question->validDNSServers)) 10880 { 10881 curmatch = GetBestServer(m, name, InterfaceID, question->ServiceID, question->validDNSServers, &currindex, mDNSfalse); 10882 if (currindex != -1) 10883 bit_clr_opaque64(question->validDNSServers, currindex); 10884 } 10885 10886 if (curmatch != mDNSNULL) 10887 { 10888 LogInfo("GetServerForQuestion: %p DNS server (%p) %#a:%d (Penalty Time Left %d) (Scope %s:%p:%d) found for name %##s (%s)", 10889 question, curmatch, &curmatch->addr, mDNSVal16(curmatch->port), 10890 (curmatch->penaltyTime ? (curmatch->penaltyTime - m->timenow) : 0), ifname ? ifname : "None", 10891 InterfaceID, question->ServiceID, name, DNSTypeName(question->qtype)); 10892 } 10893 else 10894 { 10895 LogInfo("GetServerForQuestion: %p no DNS server (Scope %s:%p:%d) found for name %##s (%s)", 10896 question, ifname ? ifname : "None", InterfaceID, question->ServiceID, name, DNSTypeName(question->qtype)); 10897 } 10898 10899 return(curmatch); 10900 } 10901 10902 10903 #define ValidQuestionTarget(Q) (((Q)->Target.type == mDNSAddrType_IPv4 || (Q)->Target.type == mDNSAddrType_IPv6) && \ 10904 (mDNSSameIPPort((Q)->TargetPort, UnicastDNSPort) || mDNSSameIPPort((Q)->TargetPort, MulticastDNSPort))) 10905 10906 // Called in normal client context (lock not held) 10907 mDNSlocal void LLQNATCallback(mDNS *m, NATTraversalInfo *n) 10908 { 10909 DNSQuestion *q; 10910 mDNS_Lock(m); 10911 LogInfo("LLQNATCallback external address:port %.4a:%u, NAT result %d", &n->ExternalAddress, mDNSVal16(n->ExternalPort), n->Result); 10912 n->clientContext = mDNSNULL; // we received at least one callback since starting this NAT-T 10913 for (q = m->Questions; q; q=q->next) 10914 if (ActiveQuestion(q) && !mDNSOpaque16IsZero(q->TargetQID) && q->LongLived) 10915 startLLQHandshake(m, q); // If ExternalPort is zero, will do StartLLQPolling instead 10916 #if APPLE_OSX_mDNSResponder 10917 UpdateAutoTunnelDomainStatuses(m); 10918 #endif 10919 mDNS_Unlock(m); 10920 } 10921 10922 mDNSlocal mDNSBool IsPrivateDomain(mDNS *const m, DNSQuestion *q) 10923 { 10924 DomainAuthInfo *AuthInfo; 10925 // Skip Private domains as we have special addresses to get the hosts in the Private domain 10926 AuthInfo = GetAuthInfoForName_internal(m, &q->qname); 10927 if (AuthInfo && !AuthInfo->deltime && AuthInfo->AutoTunnel) 10928 { 10929 debugf("IsPrivateDomain: %##s true", q->qname.c); 10930 return mDNStrue; 10931 } 10932 else 10933 { 10934 debugf("IsPrivateDomain: %##s false", q->qname.c); 10935 return mDNSfalse; 10936 } 10937 } 10938 10939 // This function takes the DNSServer as a separate argument because sometimes the 10940 // caller has not yet assigned the DNSServer, but wants to evaluate the SuppressQuery 10941 // status before switching to it. 10942 mDNSlocal mDNSBool ShouldSuppressUnicastQuery(mDNS *const m, DNSQuestion *q, DNSServer *d) 10943 { 10944 // Some callers don't check for the qtype 10945 if (q->qtype != kDNSType_A && q->qtype != kDNSType_AAAA) 10946 { 10947 LogInfo("ShouldSuppressUnicastQuery: Query not suppressed for %##s, qtype %s, not A/AAAA type", q->qname.c, DNSTypeName(q->qtype)); 10948 return mDNSfalse; 10949 } 10950 10951 // Private domains are exempted irrespective of what the DNSServer says 10952 if (IsPrivateDomain(m, q)) 10953 { 10954 LogInfo("ShouldSuppressUnicastQuery: Query not suppressed for %##s, qtype %s, Private Domain", q->qname.c, DNSTypeName(q->qtype)); 10955 return mDNSfalse; 10956 } 10957 10958 if (!d) 10959 { 10960 LogInfo("ShouldSuppressUnicastQuery: Query suppressed for %##s, qtype %s, as the DNS server is NULL", q->qname.c, DNSTypeName(q->qtype)); 10961 return mDNStrue; 10962 } 10963 10964 // Check if the DNS Configuration allows A/AAAA queries to be sent 10965 if ((q->qtype == kDNSType_A) && (d->req_A)) 10966 { 10967 LogInfo("ShouldSuppressUnicastQuery: Query not suppressed for %##s, qtype %s, DNSServer %##s %#a:%d allows A queries", q->qname.c, 10968 DNSTypeName(q->qtype), d->domain.c, &d->addr, mDNSVal16(d->port)); 10969 return mDNSfalse; 10970 } 10971 if ((q->qtype == kDNSType_AAAA) && (d->req_AAAA)) 10972 { 10973 LogInfo("ShouldSuppressUnicastQuery: Query not suppressed for %##s, qtype %s, DNSServer %##s %#a:%d allows AAAA queries", q->qname.c, 10974 DNSTypeName(q->qtype), d->domain.c, &d->addr, mDNSVal16(d->port)); 10975 return mDNSfalse; 10976 } 10977 10978 LogInfo("ShouldSuppressUnicastQuery: Query suppressed for %##s, qtype %s, since DNS Configuration does not allow (req_A is %s and req_AAAA is %s)", 10979 q->qname.c, DNSTypeName(q->qtype), d->req_A ? "true" : "false", d->req_AAAA ? "true" : "false"); 10980 10981 return mDNStrue; 10982 } 10983 10984 mDNSlocal mDNSBool ShouldSuppressDotLocalQuery(mDNS *const m, DNSQuestion *q) 10985 { 10986 NetworkInterfaceInfo *intf; 10987 AuthRecord *rr; 10988 mDNSBool ret; 10989 10990 // Check to see if there is at least one interface other than loopback and don't suppress 10991 // .local questions if you find one. If we have at least one interface, it means that 10992 // we can send unicast queries for the .local name and we don't want to suppress 10993 // multicast in that case as upper layers don't know how to handle if we return a 10994 // negative response for multicast followed by a positive response for unicast. 10995 // 10996 // Note: we used to check for multicast capable interfaces instead of just any interface 10997 // present. That did not work in the case where we have a valid interface for unicast 10998 // but not multicast capable e.g., cellular, as we ended up delivering a negative response 10999 // first and the upper layer did not wait for the positive response that came later. 11000 for (intf = m->HostInterfaces; intf; intf = intf->next) 11001 { 11002 if (intf->InterfaceActive && !intf->Loopback) 11003 { 11004 LogInfo("ShouldSuppressDotLocalQuery: Found interface %s, not suppressing", intf->ifname); 11005 return mDNSfalse; 11006 } 11007 } 11008 11009 // 1. If we find a LocalOnly or P2P record answering this question, then don't suppress it. 11010 // Set m->CurrentQuestion as it is required by AnswerQuestionWithLORecord. 11011 m->CurrentQuestion = q; 11012 ret = AnswerQuestionWithLORecord(m, q, mDNStrue); 11013 m->CurrentQuestion = mDNSNULL; 11014 11015 if (ret) 11016 { 11017 LogInfo("ShouldSuppressDotLocalQuery: Found LocalOnly record for %##s (%s), not suppressing", q->qname.c, 11018 DNSTypeName(q->qtype)); 11019 return mDNSfalse; 11020 } 11021 11022 // 2. If we find a local AuthRecord answering this question, then don't suppress it. 11023 for (rr = m->ResourceRecords; rr; rr = rr->next) 11024 { 11025 if (ResourceRecordAnswersQuestion(&rr->resrec, q)) 11026 { 11027 LogInfo("ShouldSuppressDotLocalQuery: Found resource record %s for %##s (%s) not suppressing", ARDisplayString(m, rr), 11028 q->qname.c, DNSTypeName(q->qtype)); 11029 return mDNSfalse; 11030 } 11031 } 11032 return mDNStrue; 11033 } 11034 11035 mDNSlocal mDNSBool ShouldSuppressQuery(mDNS *const m, DNSQuestion *q) 11036 { 11037 if (q->qtype != kDNSType_A && q->qtype != kDNSType_AAAA) 11038 { 11039 LogInfo("ShouldSuppressQuery: Query not suppressed for %##s, qtype %s, not A/AAAA type", q->qname.c, DNSTypeName(q->qtype)); 11040 return mDNSfalse; 11041 } 11042 11043 // We still want the ability to be able to listen to the local services and hence 11044 // don't fail .local query if we have local records that can potentially answer 11045 // the question. 11046 if (q->InterfaceID != mDNSInterface_Unicast && IsLocalDomain(&q->qname)) 11047 { 11048 if (!ShouldSuppressDotLocalQuery(m, q)) 11049 { 11050 LogInfo("ShouldSuppressQuery: Query not suppressed for %##s, qtype %s, Local question", q->qname.c, DNSTypeName(q->qtype)); 11051 return mDNSfalse; 11052 } 11053 else 11054 { 11055 LogInfo("ShouldSuppressQuery: Query suppressed for %##s, qtype %s, Local question", q->qname.c, DNSTypeName(q->qtype)); 11056 return mDNStrue; 11057 } 11058 } 11059 11060 return (ShouldSuppressUnicastQuery(m, q, q->qDNSServer)); 11061 } 11062 11063 mDNSlocal void CacheRecordRmvEventsForCurrentQuestion(mDNS *const m, DNSQuestion *q) 11064 { 11065 CacheRecord *rr; 11066 mDNSu32 slot; 11067 CacheGroup *cg; 11068 11069 slot = HashSlot(&q->qname); 11070 cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); 11071 for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) 11072 { 11073 // Don't deliver RMV events for negative records 11074 if (rr->resrec.RecordType == kDNSRecordTypePacketNegative) 11075 { 11076 LogInfo("CacheRecordRmvEventsForCurrentQuestion: CacheRecord %s Suppressing RMV events for question %p %##s (%s), CRActiveQuestion %p, CurrentAnswers %d", 11077 CRDisplayString(m, rr), q, q->qname.c, DNSTypeName(q->qtype), rr->CRActiveQuestion, q->CurrentAnswers); 11078 continue; 11079 } 11080 11081 if (SameNameRecordAnswersQuestion(&rr->resrec, q)) 11082 { 11083 LogInfo("CacheRecordRmvEventsForCurrentQuestion: Calling AnswerCurrentQuestionWithResourceRecord (RMV) for question %##s using resource record %s LocalAnswers %d", 11084 q->qname.c, CRDisplayString(m, rr), q->LOAddressAnswers); 11085 11086 q->CurrentAnswers--; 11087 if (rr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers--; 11088 if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers--; 11089 11090 if (rr->CRActiveQuestion == q) 11091 { 11092 DNSQuestion *qptr; 11093 // If this was the active question for this cache entry, it was the one that was 11094 // responsible for keeping the cache entry fresh when the cache entry was reaching 11095 // its expiry. We need to handover the responsibility to someone else. Otherwise, 11096 // when the cache entry is about to expire, we won't find an active question 11097 // (pointed by CRActiveQuestion) to refresh the cache. 11098 for (qptr = m->Questions; qptr; qptr=qptr->next) 11099 if (qptr != q && ActiveQuestion(qptr) && ResourceRecordAnswersQuestion(&rr->resrec, qptr)) 11100 break; 11101 11102 if (qptr) 11103 LogInfo("CacheRecordRmvEventsForCurrentQuestion: Updating CRActiveQuestion to %p for cache record %s, " 11104 "Original question CurrentAnswers %d, new question CurrentAnswers %d, SuppressUnusable %d, SuppressQuery %d", 11105 qptr, CRDisplayString(m,rr), q->CurrentAnswers, qptr->CurrentAnswers, qptr->SuppressUnusable, qptr->SuppressQuery); 11106 11107 rr->CRActiveQuestion = qptr; // Question used to be active; new value may or may not be null 11108 if (!qptr) m->rrcache_active--; // If no longer active, decrement rrcache_active count 11109 } 11110 AnswerCurrentQuestionWithResourceRecord(m, rr, QC_rmv); 11111 if (m->CurrentQuestion != q) break; // If callback deleted q, then we're finished here 11112 } 11113 } 11114 } 11115 11116 mDNSlocal mDNSBool IsQuestionNew(mDNS *const m, DNSQuestion *question) 11117 { 11118 DNSQuestion *q; 11119 for (q = m->NewQuestions; q; q = q->next) 11120 if (q == question) return mDNStrue; 11121 return mDNSfalse; 11122 } 11123 11124 mDNSlocal mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q) 11125 { 11126 AuthRecord *rr; 11127 mDNSu32 slot; 11128 AuthGroup *ag; 11129 11130 if (m->CurrentQuestion) 11131 LogMsg("LocalRecordRmvEventsForQuestion: ERROR m->CurrentQuestion already set: %##s (%s)", 11132 m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype)); 11133 11134 if (IsQuestionNew(m, q)) 11135 { 11136 LogInfo("LocalRecordRmvEventsForQuestion: New Question %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 11137 return mDNStrue; 11138 } 11139 m->CurrentQuestion = q; 11140 slot = AuthHashSlot(&q->qname); 11141 ag = AuthGroupForName(&m->rrauth, slot, q->qnamehash, &q->qname); 11142 if (ag) 11143 { 11144 for (rr = ag->members; rr; rr=rr->next) 11145 // Filter the /etc/hosts records - LocalOnly, Unique, A/AAAA/CNAME 11146 if (UniqueLocalOnlyRecord(rr) && LocalOnlyRecordAnswersQuestion(rr, q)) 11147 { 11148 LogInfo("LocalRecordRmvEventsForQuestion: Delivering possible Rmv events with record %s", 11149 ARDisplayString(m, rr)); 11150 if (q->CurrentAnswers <= 0 || q->LOAddressAnswers <= 0) 11151 { 11152 LogMsg("LocalRecordRmvEventsForQuestion: ERROR!! CurrentAnswers or LOAddressAnswers is zero %p %##s" 11153 " (%s) CurrentAnswers %d, LOAddressAnswers %d", q, q->qname.c, DNSTypeName(q->qtype), 11154 q->CurrentAnswers, q->LOAddressAnswers); 11155 continue; 11156 } 11157 AnswerLocalQuestionWithLocalAuthRecord(m, rr, QC_rmv); // MUST NOT dereference q again 11158 if (m->CurrentQuestion != q) { m->CurrentQuestion = mDNSNULL; return mDNSfalse; } 11159 } 11160 } 11161 m->CurrentQuestion = mDNSNULL; 11162 return mDNStrue; 11163 } 11164 11165 // Returns false if the question got deleted while delivering the RMV events 11166 // The caller should handle the case 11167 mDNSlocal mDNSBool CacheRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q) 11168 { 11169 if (m->CurrentQuestion) 11170 LogMsg("CacheRecordRmvEventsForQuestion: ERROR m->CurrentQuestion already set: %##s (%s)", 11171 m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype)); 11172 11173 // If it is a new question, we have not delivered any ADD events yet. So, don't deliver RMV events. 11174 // If this question was answered using local auth records, then you can't deliver RMVs using cache 11175 if (!IsQuestionNew(m, q) && !q->LOAddressAnswers) 11176 { 11177 m->CurrentQuestion = q; 11178 CacheRecordRmvEventsForCurrentQuestion(m, q); 11179 if (m->CurrentQuestion != q) { m->CurrentQuestion = mDNSNULL; return mDNSfalse; } 11180 m->CurrentQuestion = mDNSNULL; 11181 } 11182 else { LogInfo("CacheRecordRmvEventsForQuestion: Question %p %##s (%s) is a new question", q, q->qname.c, DNSTypeName(q->qtype)); } 11183 return mDNStrue; 11184 } 11185 11186 mDNSlocal void SuppressStatusChanged(mDNS *const m, DNSQuestion *q, DNSQuestion **restart) 11187 { 11188 // NOTE: CacheRecordRmvEventsForQuestion will not generate RMV events for queries that have non-zero 11189 // LOAddressAnswers. Hence it is important that we call CacheRecordRmvEventsForQuestion before 11190 // LocalRecordRmvEventsForQuestion (which decrements LOAddressAnswers) 11191 if (q->SuppressQuery) 11192 { 11193 q->SuppressQuery = mDNSfalse; 11194 if (!CacheRecordRmvEventsForQuestion(m, q)) 11195 { 11196 LogInfo("SuppressStatusChanged: Question deleted while delivering RMV events from cache"); 11197 return; 11198 } 11199 q->SuppressQuery = mDNStrue; 11200 } 11201 11202 // SuppressUnusable does not affect questions that are answered from the local records (/etc/hosts) 11203 // and SuppressQuery status does not mean anything for these questions. As we are going to stop the 11204 // question below, we need to deliver the RMV events so that the ADDs that will be delivered during 11205 // the restart will not be a duplicate ADD 11206 if (!LocalRecordRmvEventsForQuestion(m, q)) 11207 { 11208 LogInfo("SuppressStatusChanged: Question deleted while delivering RMV events from Local AuthRecords"); 11209 return; 11210 } 11211 11212 // There are two cases here. 11213 // 11214 // 1. Previously it was suppressed and now it is not suppressed, restart the question so 11215 // that it will start as a new question. Note that we can't just call ActivateUnicastQuery 11216 // because when we get the response, if we had entries in the cache already, it will not answer 11217 // this question if the cache entry did not change. Hence, we need to restart 11218 // the query so that it can be answered from the cache. 11219 // 11220 // 2. Previously it was not suppressed and now it is suppressed. We need to restart the questions 11221 // so that we redo the duplicate checks in mDNS_StartQuery_internal. A SuppressUnusable question 11222 // is a duplicate of non-SuppressUnusable question if it is not suppressed (SuppressQuery is false). 11223 // A SuppressUnusable question is not a duplicate of non-SuppressUnusable question if it is suppressed 11224 // (SuppressQuery is true). The reason for this is that when a question is suppressed, we want an 11225 // immediate response and not want to be blocked behind a question that is querying DNS servers. When 11226 // the question is not suppressed, we don't want two active questions sending packets on the wire. 11227 // This affects both efficiency and also the current design where there is only one active question 11228 // pointed to from a cache entry. 11229 // 11230 // We restart queries in a two step process by first calling stop and build a temporary list which we 11231 // will restart at the end. The main reason for the two step process is to handle duplicate questions. 11232 // If there are duplicate questions, calling stop inherits the values from another question on the list (which 11233 // will soon become the real question) including q->ThisQInterval which might be zero if it was 11234 // suppressed before. At the end when we have restarted all questions, none of them is active as each 11235 // inherits from one another and we need to reactivate one of the questions here which is a little hacky. 11236 // 11237 // It is much cleaner and less error prone to build a list of questions and restart at the end. 11238 11239 LogInfo("SuppressStatusChanged: Stop question %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype)); 11240 mDNS_StopQuery_internal(m, q); 11241 q->next = *restart; 11242 *restart = q; 11243 } 11244 11245 // The caller should hold the lock 11246 mDNSexport void CheckSuppressUnusableQuestions(mDNS *const m) 11247 { 11248 DNSQuestion *q; 11249 DNSQuestion *restart = mDNSNULL; 11250 11251 // We look through all questions including new questions. During network change events, 11252 // we potentially restart questions here in this function that ends up as new questions, 11253 // which may be suppressed at this instance. Before it is handled we get another network 11254 // event that changes the status e.g., address becomes available. If we did not process 11255 // new questions, we would never change its SuppressQuery status. 11256 // 11257 // CurrentQuestion is used by RmvEventsForQuestion below. While delivering RMV events, the 11258 // application callback can potentially stop the current question (detected by CurrentQuestion) or 11259 // *any* other question which could be the next one that we may process here. RestartQuestion 11260 // points to the "next" question which will be automatically advanced in mDNS_StopQuery_internal 11261 // if the "next" question is stopped while the CurrentQuestion is stopped 11262 if (m->RestartQuestion) 11263 LogMsg("CheckSuppressUnusableQuestions: ERROR!! m->RestartQuestion already set: %##s (%s)", 11264 m->RestartQuestion->qname.c, DNSTypeName(m->RestartQuestion->qtype)); 11265 m->RestartQuestion = m->Questions; 11266 while (m->RestartQuestion) 11267 { 11268 q = m->RestartQuestion; 11269 m->RestartQuestion = q->next; 11270 if (q->SuppressUnusable) 11271 { 11272 mDNSBool old = q->SuppressQuery; 11273 q->SuppressQuery = ShouldSuppressQuery(m, q); 11274 if (q->SuppressQuery != old) 11275 { 11276 // Previously it was not suppressed, Generate RMV events for the ADDs that we might have delivered before 11277 // followed by a negative cache response. Temporarily turn off suppression so that 11278 // AnswerCurrentQuestionWithResourceRecord can answer the question 11279 SuppressStatusChanged(m, q, &restart); 11280 } 11281 } 11282 } 11283 while (restart) 11284 { 11285 q = restart; 11286 restart = restart->next; 11287 q->next = mDNSNULL; 11288 LogInfo("CheckSuppressUnusableQuestions: Start question %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype)); 11289 mDNS_StartQuery_internal(m, q); 11290 } 11291 } 11292 11293 mDNSlocal void RestartUnicastQuestions(mDNS *const m) 11294 { 11295 DNSQuestion *q; 11296 DNSQuestion *restart = mDNSNULL; 11297 11298 if (m->RestartQuestion) 11299 LogMsg("RestartUnicastQuestions: ERROR!! m->RestartQuestion already set: %##s (%s)", 11300 m->RestartQuestion->qname.c, DNSTypeName(m->RestartQuestion->qtype)); 11301 m->RestartQuestion = m->Questions; 11302 while (m->RestartQuestion) 11303 { 11304 q = m->RestartQuestion; 11305 m->RestartQuestion = q->next; 11306 if (q->Restart) 11307 { 11308 if (mDNSOpaque16IsZero(q->TargetQID)) 11309 LogMsg("RestartUnicastQuestions: ERROR!! Restart set for multicast question %##s (%s)", q->qname.c, DNSTypeName(q->qtype)); 11310 11311 q->Restart = 0; 11312 SuppressStatusChanged(m, q, &restart); 11313 } 11314 } 11315 while (restart) 11316 { 11317 q = restart; 11318 restart = restart->next; 11319 q->next = mDNSNULL; 11320 LogInfo("RestartUnicastQuestions: Start question %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype)); 11321 mDNS_StartQuery_internal(m, q); 11322 } 11323 } 11324 11325 11326 // ValidateParameters() is called by mDNS_StartQuery_internal() to check the client parameters of 11327 // DNS Question that are already set by the client before calling mDNS_StartQuery() 11328 mDNSlocal mStatus ValidateParameters(mDNS *const m, DNSQuestion *const question) 11329 { 11330 11331 if (question->Target.type && !ValidQuestionTarget(question)) 11332 { 11333 LogMsg("ValidateParameters: Warning! Target.type = %ld port = %u (Client forgot to initialize before calling mDNS_StartQuery? for question %##s)", 11334 question->Target.type, mDNSVal16(question->TargetPort), question->qname.c); 11335 question->Target.type = mDNSAddrType_None; 11336 } 11337 11338 // If no question->Target specified, clear TargetPort 11339 if (!question->Target.type) 11340 question->TargetPort = zeroIPPort; 11341 11342 if (!ValidateDomainName(&question->qname)) 11343 { 11344 LogMsg("ValidateParameters: Attempt to start query with invalid qname %##s (%s)", question->qname.c, DNSTypeName(question->qtype)); 11345 return(mStatus_Invalid); 11346 } 11347 11348 // If this question is referencing a specific interface, verify it exists 11349 if (question->InterfaceID && question->InterfaceID != mDNSInterface_LocalOnly && question->InterfaceID != mDNSInterface_Unicast && question->InterfaceID != mDNSInterface_P2P) 11350 { 11351 NetworkInterfaceInfo *intf = FirstInterfaceForID(m, question->InterfaceID); 11352 if (!intf) 11353 LogInfo("ValidateParameters: Note: InterfaceID %d for question %##s (%s) not currently found in active interface list", 11354 (uint32_t)question->InterfaceID, question->qname.c, DNSTypeName(question->qtype)); 11355 } 11356 11357 return(mStatus_NoError); 11358 } 11359 11360 // InitDNSConfig() is called by InitCommonState() to initialize the DNS configuration of the Question. 11361 // These are a subset of the internal uDNS fields. Must be done before ShouldSuppressQuery() & mDNS_PurgeForQuestion() 11362 mDNSlocal void InitDNSConfig(mDNS *const m, DNSQuestion *const question) 11363 { 11364 // First reset all DNS Configuration 11365 question->qDNSServer = mDNSNULL; 11366 question->validDNSServers = zeroOpaque64; 11367 question->triedAllServersOnce = 0; 11368 question->noServerResponse = 0; 11369 question->StopTime = 0; 11370 11371 // Need not initialize the DNS Configuration for Local Only OR P2P Questions 11372 if (question->InterfaceID == mDNSInterface_LocalOnly || question->InterfaceID == mDNSInterface_P2P) 11373 return; 11374 // Proceed to initialize DNS Configuration (some are set in SetValidDNSServers()) 11375 if (!mDNSOpaque16IsZero(question->TargetQID)) 11376 { 11377 mDNSu32 timeout = SetValidDNSServers(m, question); 11378 mDNSIPPort zp = zeroIPPort; 11379 // We set the timeout whenever mDNS_StartQuery_internal is called. This means if we have 11380 // a networking change/search domain change that calls this function again we keep 11381 // reinitializing the timeout value which means it may never timeout. If this becomes 11382 // a common case in the future, we can easily fix this by adding extra state that 11383 // indicates that we have already set the StopTime. 11384 // 11385 // Note that we set the timeout for all questions. If this turns out to be a duplicate, 11386 // it gets a full timeout value even if the original question times out earlier. 11387 if (question->TimeoutQuestion) 11388 { 11389 question->StopTime = NonZeroTime(m->timenow + timeout * mDNSPlatformOneSecond); 11390 LogInfo("InitDNSConfig: Setting StopTime on question %p %##s (%s)", question, question->qname.c, DNSTypeName(question->qtype)); 11391 } 11392 11393 question->qDNSServer = GetServerForQuestion(m, question); 11394 LogInfo("InitDNSConfig: question %p %##s (%s) Timeout %d, DNS Server %#a:%d", 11395 question, question->qname.c, DNSTypeName(question->qtype), timeout, 11396 question->qDNSServer ? &question->qDNSServer->addr : mDNSNULL, 11397 mDNSVal16(question->qDNSServer ? question->qDNSServer->port : zp)); 11398 } 11399 else 11400 { 11401 if (question->TimeoutQuestion) 11402 question->StopTime = NonZeroTime(m->timenow + GetTimeoutForMcastQuestion(m, question) * mDNSPlatformOneSecond); 11403 } 11404 // Set StopTime here since it is a part of DNS Configuration 11405 if (question->StopTime) 11406 SetNextQueryStopTime(m, question); 11407 // SetNextQueryTime() need not be initialized for LocalOnly OR P2P Questions since those questions 11408 // will never be transmitted on the wire. Hence we call SetNextQueryTime() here. 11409 SetNextQueryTime(m,question); 11410 } 11411 11412 // InitCommonState() is called by mDNS_StartQuery_internal() to initialize the common(uDNS/mDNS) internal 11413 // state fields of the DNS Question. These are independent of the Client layer. 11414 mDNSlocal mDNSBool InitCommonState(mDNS *const m, DNSQuestion *const question) 11415 { 11416 mDNSBool purge; 11417 int i; 11418 11419 // Note: In the case where we already have the answer to this question in our cache, that may be all the client 11420 // wanted, and they may immediately cancel their question. In this case, sending an actual query on the wire would 11421 // be a waste. For that reason, we schedule our first query to go out in half a second (InitialQuestionInterval). 11422 // If AnswerNewQuestion() finds that we have *no* relevant answers currently in our cache, then it will accelerate 11423 // that to go out immediately. 11424 question->next = mDNSNULL; 11425 // ThisQInterval should be initialized before any memory allocations occur. If malloc 11426 // debugging is turned on within mDNSResponder (see mDNSDebug.h for details) it validates 11427 // the question list to check if ThisQInterval is negative which means the question has been 11428 // stopped and can't be on the list. The question is already on the list and ThisQInterval 11429 // can be negative if the caller just stopped it and starting it again. Hence, it always has to 11430 // be initialized. CheckForSoonToExpireRecords below prints the cache records when logging is 11431 // turned ON which can allocate memory e.g., base64 encoding, in the case of DNSSEC. 11432 question->ThisQInterval = InitialQuestionInterval; // MUST be > zero for an active question 11433 question->qnamehash = DomainNameHashValue(&question->qname); 11434 question->DelayAnswering = CheckForSoonToExpireRecords(m, &question->qname, question->qnamehash, HashSlot(&question->qname), &purge); 11435 question->LastQTime = m->timenow; 11436 question->ExpectUnicastResp = 0; 11437 question->LastAnswerPktNum = m->PktNum; 11438 question->RecentAnswerPkts = 0; 11439 question->CurrentAnswers = 0; 11440 11441 #if APPLE_OSX_mDNSResponder 11442 11443 // Initial browse threshold used by Finder. 11444 #define mDNSFinderBrowseThreshold 20 11445 11446 // Set the threshold at which we move to a passive browse state, 11447 // not actively sending queries. 11448 if (question->flags & kDNSServiceFlagsThresholdOne) 11449 question->BrowseThreshold = 1; 11450 else if (question->flags & kDNSServiceFlagsThresholdFinder) 11451 question->BrowseThreshold = mDNSFinderBrowseThreshold; 11452 else 11453 question->BrowseThreshold = 0; 11454 11455 #else // APPLE_OSX_mDNSResponder 11456 question->BrowseThreshold = 0; 11457 #endif // APPLE_OSX_mDNSResponder 11458 question->CachedAnswerNeedsUpdate = mDNSfalse; 11459 11460 question->LargeAnswers = 0; 11461 question->UniqueAnswers = 0; 11462 question->LOAddressAnswers = 0; 11463 question->FlappingInterface1 = mDNSNULL; 11464 question->FlappingInterface2 = mDNSNULL; 11465 11466 // if kDNSServiceFlagsServiceIndex flag is SET by the client, then do NOT call mDNSPlatformGetServiceID() 11467 // since we would already have the question->ServiceID in that case. 11468 if (!(question->flags & kDNSServiceFlagsServiceIndex)) 11469 question->ServiceID = mDNSPlatformGetServiceID(m, question); 11470 else 11471 LogInfo("InitCommonState: Query for %##s (%s), PID[%d], ServiceID %d is already set by client", question->qname.c, 11472 DNSTypeName(question->qtype), question->pid, question->ServiceID); 11473 11474 InitDNSConfig(m, question); 11475 11476 question->AuthInfo = GetAuthInfoForQuestion(m, question); 11477 question->SuppressQuery = 0; 11478 if (question->SuppressUnusable) 11479 question->SuppressQuery = ShouldSuppressQuery(m, question); 11480 11481 // If ServiceID is 0 or the policy disallows making DNS requests, 11482 // set DisallowPID 11483 question->DisallowPID = (question->ServiceID == 0 || (mDNSPlatformAllowPID(m, question) == 0)); 11484 if (question->DisallowPID) 11485 LogInfo("InitCommonState: Query suppressed for %##s (%s), PID %d/ServiceID %d not allowed", question->qname.c, 11486 DNSTypeName(question->qtype), question->pid, question->ServiceID); 11487 11488 question->NextInDQList = mDNSNULL; 11489 question->SendQNow = mDNSNULL; 11490 question->SendOnAll = mDNSfalse; 11491 11492 #if mDNS_REQUEST_UNICAST_RESPONSE 11493 question->RequestUnicast = SET_QU_IN_FIRST_FOUR_QUERIES; 11494 #else // mDNS_REQUEST_UNICAST_RESPONSE 11495 question->RequestUnicast = SET_QU_IN_FIRST_QUERY; 11496 #endif // mDNS_REQUEST_UNICAST_RESPONSE 11497 11498 #if APPLE_OSX_mDNSResponder 11499 // Request unicast response for first 4 queries to increase 11500 // reliability in an environment with high multicast packet loss. 11501 // Must set to one more than the number of unicast queries you want, since SendQueries() 11502 // decrements it before calling BuildQuestion() which acts on it. 11503 if (question->flags & kDNSServiceFlagsUnicastResponse) 11504 { 11505 question->RequestUnicast = SET_QU_IN_FIRST_FOUR_QUERIES; 11506 LogInfo("InitCommonState: setting RequestUnicast = %d for %##s (%s)", question->RequestUnicast, question->qname.c, 11507 DNSTypeName(question->qtype)); 11508 } 11509 else if (question->flags & kDNSServiceFlagsThresholdFinder) 11510 { 11511 // always send one request with QU bit set when kDNSServiceFlagsThresholdFinder is set 11512 #if mDNS_REQUEST_UNICAST_RESPONSE 11513 question->RequestUnicast = SET_QU_IN_FIRST_FOUR_QUERIES; 11514 #else // mDNS_REQUEST_UNICAST_RESPONSE 11515 question->RequestUnicast = SET_QU_IN_FIRST_QUERY; 11516 #endif // mDNS_REQUEST_UNICAST_RESPONSE 11517 11518 LogInfo("InitCommonState: kDNSServiceFlagsThresholdFinder set, setting RequestUnicast = %d for %##s (%s)", 11519 question->RequestUnicast, question->qname.c, DNSTypeName(question->qtype)); 11520 } 11521 #endif // APPLE_OSX_mDNSResponder 11522 11523 question->LastQTxTime = m->timenow; 11524 question->CNAMEReferrals = 0; 11525 11526 question->WakeOnResolveCount = 0; 11527 if (question->WakeOnResolve) 11528 { 11529 question->WakeOnResolveCount = InitialWakeOnResolveCount; 11530 purge = mDNStrue; 11531 } 11532 11533 for (i=0; i<DupSuppressInfoSize; i++) 11534 question->DupSuppress[i].InterfaceID = mDNSNULL; 11535 11536 question->Restart = 0; 11537 11538 debugf("InitCommonState: Question %##s (%s) Interface %p Now %d Send in %d Answer in %d (%p) %s (%p)", 11539 question->qname.c, DNSTypeName(question->qtype), question->InterfaceID, m->timenow, 11540 NextQSendTime(question) - m->timenow, 11541 question->DelayAnswering ? question->DelayAnswering - m->timenow : 0, 11542 question, question->DuplicateOf ? "duplicate of" : "not duplicate", question->DuplicateOf); 11543 11544 if (question->DelayAnswering) 11545 LogInfo("InitCommonState: Delaying answering for %d ticks while cache stabilizes for %##s (%s)", 11546 question->DelayAnswering - m->timenow, question->qname.c, DNSTypeName(question->qtype)); 11547 11548 return(purge); 11549 } 11550 11551 // Excludes the DNS Config fields which are already handled by InitDNSConfig() 11552 mDNSlocal void InitWABState(DNSQuestion *const question) 11553 { 11554 // We'll create our question->LocalSocket on demand, if needed. 11555 // We won't need one for duplicate questions, or from questions answered immediately out of the cache. 11556 // We also don't need one for LLQs because (when we're using NAT) we want them all to share a single 11557 // NAT mapping for receiving inbound add/remove events. 11558 question->LocalSocket = mDNSNULL; 11559 question->unansweredQueries = 0; 11560 question->nta = mDNSNULL; 11561 question->servAddr = zeroAddr; 11562 question->servPort = zeroIPPort; 11563 question->tcp = mDNSNULL; 11564 question->NoAnswer = NoAnswer_Normal; 11565 } 11566 11567 mDNSlocal void InitLLQNATState(mDNS *const m) 11568 { 11569 // If we don't have our NAT mapping active, start it now 11570 if (!m->LLQNAT.clientCallback) 11571 { 11572 m->LLQNAT.Protocol = NATOp_MapUDP; 11573 m->LLQNAT.IntPort = m->UnicastPort4; 11574 m->LLQNAT.RequestedPort = m->UnicastPort4; 11575 m->LLQNAT.clientCallback = LLQNATCallback; 11576 m->LLQNAT.clientContext = (void*)1; // Means LLQ NAT Traversal just started 11577 mDNS_StartNATOperation_internal(m, &m->LLQNAT); 11578 } 11579 } 11580 11581 mDNSlocal void InitLLQState(DNSQuestion *const question) 11582 { 11583 question->state = LLQ_InitialRequest; 11584 question->ReqLease = 0; 11585 question->expire = 0; 11586 question->ntries = 0; 11587 question->id = zeroOpaque64; 11588 } 11589 11590 // InitDNSSECProxyState() is called by mDNS_StartQuery_internal() to initialize 11591 // DNSSEC & DNS Proxy fields of the DNS Question. 11592 mDNSlocal void InitDNSSECProxyState(mDNS *const m, DNSQuestion *const question) 11593 { 11594 (void) m; 11595 11596 // DNS server selection affects DNSSEC. Turn off validation if req_DO is not set 11597 // or the request is going over cellular interface. 11598 // 11599 // Note: This needs to be done here before we call FindDuplicateQuestion as it looks 11600 // at ValidationRequired setting also. 11601 if (question->qDNSServer) 11602 { 11603 if (question->qDNSServer->cellIntf) 11604 { 11605 LogInfo("InitDNSSECProxyState: Turning off validation for %##s (%s); going over cell", question->qname.c, DNSTypeName(question->qtype)); 11606 question->ValidationRequired = mDNSfalse; 11607 } 11608 if (DNSSECOptionalQuestion(question) && !(question->qDNSServer->req_DO)) 11609 { 11610 LogInfo("InitDNSSECProxyState: Turning off validation for %##s (%s); req_DO false", 11611 question->qname.c, DNSTypeName(question->qtype)); 11612 question->ValidationRequired = DNSSEC_VALIDATION_NONE; 11613 } 11614 } 11615 question->ValidationState = (question->ValidationRequired ? DNSSECValRequired : DNSSECValNotRequired); 11616 question->ValidationStatus = 0; 11617 question->responseFlags = zeroID; 11618 } 11619 11620 // Once the question is completely initialized including the duplicate logic, this function 11621 // is called to finalize the unicast question which requires flushing the cache if needed, 11622 // activating the query etc. 11623 mDNSlocal void FinalizeUnicastQuestion(mDNS *const m, DNSQuestion *question, mDNSBool purge) 11624 { 11625 // Ensure DNS related info of duplicate question is same as the orig question 11626 if (question->DuplicateOf) 11627 { 11628 mDNSIPPort zp = zeroIPPort; 11629 question->validDNSServers = question->DuplicateOf->validDNSServers; 11630 question->qDNSServer = question->DuplicateOf->qDNSServer; 11631 LogInfo("FinalizeUnicastQuestion: Duplicate question %p (%p) %##s (%s), DNS Server %#a:%d", 11632 question, question->DuplicateOf, question->qname.c, DNSTypeName(question->qtype), 11633 question->qDNSServer ? &question->qDNSServer->addr : mDNSNULL, 11634 mDNSVal16(question->qDNSServer ? question->qDNSServer->port : zp)); 11635 } 11636 11637 ActivateUnicastQuery(m, question, mDNSfalse); 11638 11639 // If purge was set above, flush the cache. Need to do this after we set the 11640 // DNS server on the question 11641 if (purge) 11642 { 11643 question->DelayAnswering = 0; 11644 mDNS_PurgeForQuestion(m, question); 11645 } 11646 else if (!question->DuplicateOf && DNSSECQuestion(question)) 11647 { 11648 // For DNSSEC questions, we need to have the RRSIGs also for verification. 11649 CheckForDNSSECRecords(m, question); 11650 } 11651 if (question->LongLived) 11652 { 11653 // Unlike other initializations, InitLLQNATState should be done after 11654 // we determine that it is a unicast question. LongLived is set for 11655 // both multicast and unicast browse questions but we should initialize 11656 // the LLQ NAT state only for unicast. Otherwise we will unnecessarily 11657 // start the NAT traversal that is not needed. 11658 InitLLQNATState(m); 11659 #if APPLE_OSX_mDNSResponder 11660 UpdateAutoTunnelDomainStatuses(m); 11661 #endif 11662 } 11663 } 11664 11665 mDNSexport mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const question) 11666 { 11667 DNSQuestion **q; 11668 mStatus vStatus; 11669 mDNSBool purge; 11670 mDNSOpaque16 zqid = zeroID; 11671 11672 // First check for cache space (can't do queries if there is no cache space allocated) 11673 if (m->rrcache_size == 0) 11674 return(mStatus_NoCache); 11675 11676 vStatus = ValidateParameters(m, question); 11677 if (vStatus) 11678 return(vStatus); 11679 11680 question->TargetQID = 11681 #ifndef UNICAST_DISABLED 11682 (question->Target.type || Question_uDNS(question)) ? mDNS_NewMessageID(m) : 11683 #endif // UNICAST_DISABLED 11684 zqid; 11685 debugf("mDNS_StartQuery_internal: %##s (%s)", question->qname.c, DNSTypeName(question->qtype)); 11686 11687 // Note: It important that new questions are appended at the *end* of the list, not prepended at the start 11688 q = &m->Questions; 11689 if (question->InterfaceID == mDNSInterface_LocalOnly || question->InterfaceID == mDNSInterface_P2P) 11690 q = &m->LocalOnlyQuestions; 11691 while (*q && *q != question) 11692 q=&(*q)->next; 11693 11694 if (*q) 11695 { 11696 LogMsg("mDNS_StartQuery_internal: Error! Tried to add a question %##s (%s) %p that's already in the active list", 11697 question->qname.c, DNSTypeName(question->qtype), question); 11698 return(mStatus_AlreadyRegistered); 11699 } 11700 *q = question; 11701 11702 11703 // Intialize the question. The only ordering constraint we have today is that 11704 // InitDNSSECProxyState should be called after the DNS server is selected (in 11705 // InitCommonState -> InitDNSConfig) as DNS server selection affects DNSSEC 11706 // validation. 11707 11708 purge = InitCommonState(m, question); 11709 InitWABState(question); 11710 InitLLQState(question); 11711 InitDNSSECProxyState(m, question); 11712 11713 // FindDuplicateQuestion should be called last after all the intialization 11714 // as the duplicate logic could be potentially based on any field in the 11715 // question. 11716 question->DuplicateOf = FindDuplicateQuestion(m, question); 11717 if (question->DuplicateOf) 11718 question->AuthInfo = question->DuplicateOf->AuthInfo; 11719 11720 if (question->InterfaceID == mDNSInterface_LocalOnly || question->InterfaceID == mDNSInterface_P2P) 11721 { 11722 if (!m->NewLocalOnlyQuestions) 11723 m->NewLocalOnlyQuestions = question; 11724 } 11725 else 11726 { 11727 if (!m->NewQuestions) 11728 m->NewQuestions = question; 11729 11730 // If the question's id is non-zero, then it's Wide Area 11731 // MUST NOT do this Wide Area setup until near the end of 11732 // mDNS_StartQuery_internal -- this code may itself issue queries (e.g. SOA, 11733 // NS, etc.) and if we haven't finished setting up our own question and setting 11734 // m->NewQuestions if necessary then we could end up recursively re-entering 11735 // this routine with the question list data structures in an inconsistent state. 11736 if (!mDNSOpaque16IsZero(question->TargetQID)) 11737 { 11738 FinalizeUnicastQuestion(m, question, purge); 11739 } 11740 else 11741 { 11742 if (purge) 11743 { 11744 LogInfo("mDNS_StartQuery_internal: Purging for %##s", question->qname.c); 11745 mDNS_PurgeForQuestion(m, question); 11746 } 11747 } 11748 } 11749 11750 return(mStatus_NoError); 11751 } 11752 11753 // CancelGetZoneData is an internal routine (i.e. must be called with the lock already held) 11754 mDNSexport void CancelGetZoneData(mDNS *const m, ZoneData *nta) 11755 { 11756 debugf("CancelGetZoneData %##s (%s)", nta->question.qname.c, DNSTypeName(nta->question.qtype)); 11757 // This function may be called anytime to free the zone information.The question may or may not have stopped. 11758 // If it was already stopped, mDNS_StopQuery_internal would have set q->ThisQInterval to -1 and should not 11759 // call it again 11760 if (nta->question.ThisQInterval != -1) 11761 { 11762 mDNS_StopQuery_internal(m, &nta->question); 11763 if (nta->question.ThisQInterval != -1) 11764 LogMsg("CancelGetZoneData: Question %##s (%s) ThisQInterval %d not -1", nta->question.qname.c, DNSTypeName(nta->question.qtype), nta->question.ThisQInterval); 11765 } 11766 mDNSPlatformMemFree(nta); 11767 } 11768 11769 mDNSexport mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const question) 11770 { 11771 const mDNSu32 slot = HashSlot(&question->qname); 11772 CacheGroup *cg = CacheGroupForName(m, slot, question->qnamehash, &question->qname); 11773 CacheRecord *rr; 11774 DNSQuestion **qp = &m->Questions; 11775 11776 //LogInfo("mDNS_StopQuery_internal %##s (%s)", question->qname.c, DNSTypeName(question->qtype)); 11777 11778 if (question->InterfaceID == mDNSInterface_LocalOnly || question->InterfaceID == mDNSInterface_P2P) qp = &m->LocalOnlyQuestions; 11779 while (*qp && *qp != question) qp=&(*qp)->next; 11780 if (*qp) *qp = (*qp)->next; 11781 else 11782 { 11783 #if !ForceAlerts 11784 if (question->ThisQInterval >= 0) // Only log error message if the query was supposed to be active 11785 #endif 11786 LogMsg("mDNS_StopQuery_internal: Question %##s (%s) not found in active list", 11787 question->qname.c, DNSTypeName(question->qtype)); 11788 #if ForceAlerts 11789 *(long*)0 = 0; 11790 #endif 11791 return(mStatus_BadReferenceErr); 11792 } 11793 11794 // Take care to cut question from list *before* calling UpdateQuestionDuplicates 11795 UpdateQuestionDuplicates(m, question); 11796 // But don't trash ThisQInterval until afterwards. 11797 question->ThisQInterval = -1; 11798 11799 // If there are any cache records referencing this as their active question, then see if there is any 11800 // other question that is also referencing them, else their CRActiveQuestion needs to get set to NULL. 11801 for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) 11802 { 11803 if (rr->CRActiveQuestion == question) 11804 { 11805 DNSQuestion *q; 11806 // Checking for ActiveQuestion filters questions that are suppressed also 11807 // as suppressed questions are not active 11808 for (q = m->Questions; q; q=q->next) // Scan our list of questions 11809 if (ActiveQuestion(q) && ResourceRecordAnswersQuestion(&rr->resrec, q)) 11810 break; 11811 if (q) 11812 debugf("mDNS_StopQuery_internal: Updating CRActiveQuestion to %p for cache record %s, Original question CurrentAnswers %d, new question " 11813 "CurrentAnswers %d, SuppressQuery %d", q, CRDisplayString(m,rr), question->CurrentAnswers, q->CurrentAnswers, q->SuppressQuery); 11814 rr->CRActiveQuestion = q; // Question used to be active; new value may or may not be null 11815 if (!q) m->rrcache_active--; // If no longer active, decrement rrcache_active count 11816 } 11817 } 11818 11819 // If we just deleted the question that CacheRecordAdd() or CacheRecordRmv() is about to look at, 11820 // bump its pointer forward one question. 11821 if (m->CurrentQuestion == question) 11822 { 11823 debugf("mDNS_StopQuery_internal: Just deleted the currently active question: %##s (%s)", 11824 question->qname.c, DNSTypeName(question->qtype)); 11825 m->CurrentQuestion = question->next; 11826 } 11827 11828 if (m->NewQuestions == question) 11829 { 11830 debugf("mDNS_StopQuery_internal: Just deleted a new question that wasn't even answered yet: %##s (%s)", 11831 question->qname.c, DNSTypeName(question->qtype)); 11832 m->NewQuestions = question->next; 11833 } 11834 11835 if (m->NewLocalOnlyQuestions == question) m->NewLocalOnlyQuestions = question->next; 11836 11837 if (m->RestartQuestion == question) 11838 { 11839 LogMsg("mDNS_StopQuery_internal: Just deleted the current restart question: %##s (%s)", 11840 question->qname.c, DNSTypeName(question->qtype)); 11841 m->RestartQuestion = question->next; 11842 } 11843 11844 if (m->ValidationQuestion == question) 11845 { 11846 LogInfo("mDNS_StopQuery_internal: Just deleted the current Validation question: %##s (%s)", 11847 question->qname.c, DNSTypeName(question->qtype)); 11848 m->ValidationQuestion = question->next; 11849 } 11850 11851 // Take care not to trash question->next until *after* we've updated m->CurrentQuestion and m->NewQuestions 11852 question->next = mDNSNULL; 11853 11854 // LogMsg("mDNS_StopQuery_internal: Question %##s (%s) removed", question->qname.c, DNSTypeName(question->qtype)); 11855 11856 // And finally, cancel any associated GetZoneData operation that's still running. 11857 // Must not do this until last, because there's a good chance the GetZoneData question is the next in the list, 11858 // so if we delete it earlier in this routine, we could find that our "question->next" pointer above is already 11859 // invalid before we even use it. By making sure that we update m->CurrentQuestion and m->NewQuestions if necessary 11860 // *first*, then they're all ready to be updated a second time if necessary when we cancel our GetZoneData query. 11861 if (question->tcp) { DisposeTCPConn(question->tcp); question->tcp = mDNSNULL; } 11862 if (question->LocalSocket) { mDNSPlatformUDPClose(question->LocalSocket); question->LocalSocket = mDNSNULL; } 11863 if (!mDNSOpaque16IsZero(question->TargetQID) && question->LongLived) 11864 { 11865 // Scan our list to see if any more wide-area LLQs remain. If not, stop our NAT Traversal. 11866 DNSQuestion *q; 11867 for (q = m->Questions; q; q=q->next) 11868 if (!mDNSOpaque16IsZero(q->TargetQID) && q->LongLived) break; 11869 if (!q) 11870 { 11871 if (!m->LLQNAT.clientCallback) // Should never happen, but just in case... 11872 { 11873 LogMsg("mDNS_StopQuery ERROR LLQNAT.clientCallback NULL"); 11874 } 11875 else 11876 { 11877 LogInfo("Stopping LLQNAT"); 11878 mDNS_StopNATOperation_internal(m, &m->LLQNAT); 11879 m->LLQNAT.clientCallback = mDNSNULL; // Means LLQ NAT Traversal not running 11880 } 11881 } 11882 11883 // If necessary, tell server it can delete this LLQ state 11884 if (question->state == LLQ_Established) 11885 { 11886 question->ReqLease = 0; 11887 sendLLQRefresh(m, question); 11888 // If we need need to make a TCP connection to cancel the LLQ, that's going to take a little while. 11889 // We clear the tcp->question backpointer so that when the TCP connection completes, it doesn't 11890 // crash trying to access our cancelled question, but we don't cancel the TCP operation itself -- 11891 // we let that run out its natural course and complete asynchronously. 11892 if (question->tcp) 11893 { 11894 question->tcp->question = mDNSNULL; 11895 question->tcp = mDNSNULL; 11896 } 11897 } 11898 #if APPLE_OSX_mDNSResponder 11899 UpdateAutoTunnelDomainStatuses(m); 11900 #endif 11901 } 11902 // wait until we send the refresh above which needs the nta 11903 if (question->nta) { CancelGetZoneData(m, question->nta); question->nta = mDNSNULL; } 11904 11905 if (question->ValidationRequired && question->DNSSECAuthInfo) 11906 { 11907 LogInfo("mDNS_StopQuery_internal: freeing DNSSECAuthInfo %##s", question->qname.c); 11908 question->DAIFreeCallback(m, question->DNSSECAuthInfo); 11909 question->DNSSECAuthInfo = mDNSNULL; 11910 } 11911 if (question->AnonInfo) 11912 { 11913 FreeAnonInfo(question->AnonInfo); 11914 question->AnonInfo = mDNSNULL; 11915 } 11916 11917 return(mStatus_NoError); 11918 } 11919 11920 mDNSexport mStatus mDNS_StartQuery(mDNS *const m, DNSQuestion *const question) 11921 { 11922 mStatus status; 11923 mDNS_Lock(m); 11924 status = mDNS_StartQuery_internal(m, question); 11925 mDNS_Unlock(m); 11926 return(status); 11927 } 11928 11929 mDNSexport mStatus mDNS_StopQuery(mDNS *const m, DNSQuestion *const question) 11930 { 11931 mStatus status; 11932 mDNS_Lock(m); 11933 status = mDNS_StopQuery_internal(m, question); 11934 mDNS_Unlock(m); 11935 return(status); 11936 } 11937 11938 // Note that mDNS_StopQueryWithRemoves() does not currently implement the full generality of the other APIs 11939 // Specifically, question callbacks invoked as a result of this call cannot themselves make API calls. 11940 // We invoke the callback without using mDNS_DropLockBeforeCallback/mDNS_ReclaimLockAfterCallback 11941 // specifically to catch and report if the client callback does try to make API calls 11942 mDNSexport mStatus mDNS_StopQueryWithRemoves(mDNS *const m, DNSQuestion *const question) 11943 { 11944 mStatus status; 11945 DNSQuestion *qq; 11946 mDNS_Lock(m); 11947 11948 // Check if question is new -- don't want to give remove events for a question we haven't even answered yet 11949 for (qq = m->NewQuestions; qq; qq=qq->next) if (qq == question) break; 11950 11951 status = mDNS_StopQuery_internal(m, question); 11952 if (status == mStatus_NoError && !qq) 11953 { 11954 const CacheRecord *rr; 11955 const mDNSu32 slot = HashSlot(&question->qname); 11956 CacheGroup *const cg = CacheGroupForName(m, slot, question->qnamehash, &question->qname); 11957 LogInfo("Generating terminal removes for %##s (%s)", question->qname.c, DNSTypeName(question->qtype)); 11958 for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next) 11959 if (rr->resrec.RecordType != kDNSRecordTypePacketNegative && SameNameRecordAnswersQuestion(&rr->resrec, question)) 11960 { 11961 // Don't use mDNS_DropLockBeforeCallback() here, since we don't allow API calls 11962 if (question->QuestionCallback) 11963 question->QuestionCallback(m, question, &rr->resrec, QC_rmv); 11964 } 11965 } 11966 mDNS_Unlock(m); 11967 return(status); 11968 } 11969 11970 mDNSexport mStatus mDNS_Reconfirm(mDNS *const m, CacheRecord *const cr) 11971 { 11972 mStatus status; 11973 mDNS_Lock(m); 11974 status = mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer); 11975 if (status == mStatus_NoError) ReconfirmAntecedents(m, cr->resrec.name, cr->resrec.namehash, 0); 11976 mDNS_Unlock(m); 11977 return(status); 11978 } 11979 11980 mDNSexport mStatus mDNS_ReconfirmByValue(mDNS *const m, ResourceRecord *const rr) 11981 { 11982 mStatus status = mStatus_BadReferenceErr; 11983 CacheRecord *cr; 11984 mDNS_Lock(m); 11985 cr = FindIdenticalRecordInCache(m, rr); 11986 debugf("mDNS_ReconfirmByValue: %p %s", cr, RRDisplayString(m, rr)); 11987 if (cr) status = mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer); 11988 if (status == mStatus_NoError) ReconfirmAntecedents(m, cr->resrec.name, cr->resrec.namehash, 0); 11989 mDNS_Unlock(m); 11990 return(status); 11991 } 11992 11993 mDNSlocal mStatus mDNS_StartBrowse_internal(mDNS *const m, DNSQuestion *const question, 11994 const domainname *const srv, const domainname *const domain, 11995 const mDNSu8 *anondata, const mDNSInterfaceID InterfaceID, mDNSu32 flags, 11996 mDNSBool ForceMCast, mDNSBool useBackgroundTrafficClass, 11997 mDNSQuestionCallback *Callback, void *Context) 11998 { 11999 question->InterfaceID = InterfaceID; 12000 question->flags = flags; 12001 question->Target = zeroAddr; 12002 question->qtype = kDNSType_PTR; 12003 question->qclass = kDNSClass_IN; 12004 question->LongLived = mDNStrue; 12005 question->ExpectUnique = mDNSfalse; 12006 question->ForceMCast = ForceMCast; 12007 question->ReturnIntermed = mDNSfalse; 12008 question->SuppressUnusable = mDNSfalse; 12009 question->DenyOnCellInterface = mDNSfalse; 12010 question->DenyOnExpInterface = mDNSfalse; 12011 question->SearchListIndex = 0; 12012 question->AppendSearchDomains = 0; 12013 question->RetryWithSearchDomains = mDNSfalse; 12014 question->TimeoutQuestion = 0; 12015 question->WakeOnResolve = 0; 12016 question->UseBackgroundTrafficClass = useBackgroundTrafficClass; 12017 question->ValidationRequired = 0; 12018 question->ValidatingResponse = 0; 12019 question->ProxyQuestion = 0; 12020 question->qnameOrig = mDNSNULL; 12021 question->AnonInfo = mDNSNULL; 12022 question->QuestionCallback = Callback; 12023 question->QuestionContext = Context; 12024 12025 if (!ConstructServiceName(&question->qname, mDNSNULL, srv, domain)) 12026 return(mStatus_BadParamErr); 12027 12028 if (anondata) 12029 { 12030 question->AnonInfo = AllocateAnonInfo(&question->qname, anondata, mDNSPlatformStrLen(anondata), mDNSNULL); 12031 if (!question->AnonInfo) 12032 return(mStatus_BadParamErr); 12033 } 12034 12035 return(mDNS_StartQuery_internal(m, question)); 12036 } 12037 12038 mDNSexport mStatus mDNS_StartBrowse(mDNS *const m, DNSQuestion *const question, 12039 const domainname *const srv, const domainname *const domain, 12040 const mDNSu8 *anondata, const mDNSInterfaceID InterfaceID, mDNSu32 flags, 12041 mDNSBool ForceMCast, mDNSBool useBackgroundTrafficClass, 12042 mDNSQuestionCallback *Callback, void *Context) 12043 { 12044 mStatus status; 12045 mDNS_Lock(m); 12046 status = mDNS_StartBrowse_internal(m, question, srv, domain, anondata, InterfaceID, flags, ForceMCast, useBackgroundTrafficClass, Callback, Context); 12047 mDNS_Unlock(m); 12048 return(status); 12049 } 12050 12051 mDNSlocal mDNSBool MachineHasActiveIPv6(mDNS *const m) 12052 { 12053 NetworkInterfaceInfo *intf; 12054 for (intf = m->HostInterfaces; intf; intf = intf->next) 12055 if (intf->ip.type == mDNSAddrType_IPv6) return(mDNStrue); 12056 return(mDNSfalse); 12057 } 12058 12059 mDNSlocal void FoundServiceInfoSRV(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) 12060 { 12061 ServiceInfoQuery *query = (ServiceInfoQuery *)question->QuestionContext; 12062 mDNSBool PortChanged = !mDNSSameIPPort(query->info->port, answer->rdata->u.srv.port); 12063 if (!AddRecord) return; 12064 if (answer->rrtype != kDNSType_SRV) return; 12065 12066 query->info->port = answer->rdata->u.srv.port; 12067 12068 // If this is our first answer, then set the GotSRV flag and start the address query 12069 if (!query->GotSRV) 12070 { 12071 query->GotSRV = mDNStrue; 12072 query->qAv4.InterfaceID = answer->InterfaceID; 12073 AssignDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target); 12074 query->qAv6.InterfaceID = answer->InterfaceID; 12075 AssignDomainName(&query->qAv6.qname, &answer->rdata->u.srv.target); 12076 mDNS_StartQuery(m, &query->qAv4); 12077 // Only do the AAAA query if this machine actually has IPv6 active 12078 if (MachineHasActiveIPv6(m)) mDNS_StartQuery(m, &query->qAv6); 12079 } 12080 // If this is not our first answer, only re-issue the address query if the target host name has changed 12081 else if ((query->qAv4.InterfaceID != query->qSRV.InterfaceID && query->qAv4.InterfaceID != answer->InterfaceID) || 12082 !SameDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target)) 12083 { 12084 mDNS_StopQuery(m, &query->qAv4); 12085 if (query->qAv6.ThisQInterval >= 0) mDNS_StopQuery(m, &query->qAv6); 12086 if (SameDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target) && !PortChanged) 12087 { 12088 // If we get here, it means: 12089 // 1. This is not our first SRV answer 12090 // 2. The interface ID is different, but the target host and port are the same 12091 // This implies that we're seeing the exact same SRV record on more than one interface, so we should 12092 // make our address queries at least as broad as the original SRV query so that we catch all the answers. 12093 query->qAv4.InterfaceID = query->qSRV.InterfaceID; // Will be mDNSInterface_Any, or a specific interface 12094 query->qAv6.InterfaceID = query->qSRV.InterfaceID; 12095 } 12096 else 12097 { 12098 query->qAv4.InterfaceID = answer->InterfaceID; 12099 AssignDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target); 12100 query->qAv6.InterfaceID = answer->InterfaceID; 12101 AssignDomainName(&query->qAv6.qname, &answer->rdata->u.srv.target); 12102 } 12103 debugf("FoundServiceInfoSRV: Restarting address queries for %##s (%s)", query->qAv4.qname.c, DNSTypeName(query->qAv4.qtype)); 12104 mDNS_StartQuery(m, &query->qAv4); 12105 // Only do the AAAA query if this machine actually has IPv6 active 12106 if (MachineHasActiveIPv6(m)) mDNS_StartQuery(m, &query->qAv6); 12107 } 12108 else if (query->ServiceInfoQueryCallback && query->GotADD && query->GotTXT && PortChanged) 12109 { 12110 if (++query->Answers >= 100) 12111 debugf("**** WARNING **** Have given %lu answers for %##s (SRV) %##s %u", 12112 query->Answers, query->qSRV.qname.c, answer->rdata->u.srv.target.c, 12113 mDNSVal16(answer->rdata->u.srv.port)); 12114 query->ServiceInfoQueryCallback(m, query); 12115 } 12116 // CAUTION: MUST NOT do anything more with query after calling query->Callback(), because the client's 12117 // callback function is allowed to do anything, including deleting this query and freeing its memory. 12118 } 12119 12120 mDNSlocal void FoundServiceInfoTXT(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) 12121 { 12122 ServiceInfoQuery *query = (ServiceInfoQuery *)question->QuestionContext; 12123 if (!AddRecord) return; 12124 if (answer->rrtype != kDNSType_TXT) return; 12125 if (answer->rdlength > sizeof(query->info->TXTinfo)) return; 12126 12127 query->GotTXT = mDNStrue; 12128 query->info->TXTlen = answer->rdlength; 12129 query->info->TXTinfo[0] = 0; // In case answer->rdlength is zero 12130 mDNSPlatformMemCopy(query->info->TXTinfo, answer->rdata->u.txt.c, answer->rdlength); 12131 12132 verbosedebugf("FoundServiceInfoTXT: %##s GotADD=%d", query->info->name.c, query->GotADD); 12133 12134 // CAUTION: MUST NOT do anything more with query after calling query->Callback(), because the client's 12135 // callback function is allowed to do anything, including deleting this query and freeing its memory. 12136 if (query->ServiceInfoQueryCallback && query->GotADD) 12137 { 12138 if (++query->Answers >= 100) 12139 debugf("**** WARNING **** have given %lu answers for %##s (TXT) %#s...", 12140 query->Answers, query->qSRV.qname.c, answer->rdata->u.txt.c); 12141 query->ServiceInfoQueryCallback(m, query); 12142 } 12143 } 12144 12145 mDNSlocal void FoundServiceInfo(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord) 12146 { 12147 ServiceInfoQuery *query = (ServiceInfoQuery *)question->QuestionContext; 12148 //LogInfo("FoundServiceInfo %d %s", AddRecord, RRDisplayString(m, answer)); 12149 if (!AddRecord) return; 12150 12151 if (answer->rrtype == kDNSType_A) 12152 { 12153 query->info->ip.type = mDNSAddrType_IPv4; 12154 query->info->ip.ip.v4 = answer->rdata->u.ipv4; 12155 } 12156 else if (answer->rrtype == kDNSType_AAAA) 12157 { 12158 query->info->ip.type = mDNSAddrType_IPv6; 12159 query->info->ip.ip.v6 = answer->rdata->u.ipv6; 12160 } 12161 else 12162 { 12163 debugf("FoundServiceInfo: answer %##s type %d (%s) unexpected", answer->name->c, answer->rrtype, DNSTypeName(answer->rrtype)); 12164 return; 12165 } 12166 12167 query->GotADD = mDNStrue; 12168 query->info->InterfaceID = answer->InterfaceID; 12169 12170 verbosedebugf("FoundServiceInfo v%ld: %##s GotTXT=%d", query->info->ip.type, query->info->name.c, query->GotTXT); 12171 12172 // CAUTION: MUST NOT do anything more with query after calling query->Callback(), because the client's 12173 // callback function is allowed to do anything, including deleting this query and freeing its memory. 12174 if (query->ServiceInfoQueryCallback && query->GotTXT) 12175 { 12176 if (++query->Answers >= 100) 12177 debugf(answer->rrtype == kDNSType_A ? 12178 "**** WARNING **** have given %lu answers for %##s (A) %.4a" : 12179 "**** WARNING **** have given %lu answers for %##s (AAAA) %.16a", 12180 query->Answers, query->qSRV.qname.c, &answer->rdata->u.data); 12181 query->ServiceInfoQueryCallback(m, query); 12182 } 12183 } 12184 12185 // On entry, the client must have set the name and InterfaceID fields of the ServiceInfo structure 12186 // If the query is not interface-specific, then InterfaceID may be zero 12187 // Each time the Callback is invoked, the remainder of the fields will have been filled in 12188 // In addition, InterfaceID will be updated to give the interface identifier corresponding to that response 12189 mDNSexport mStatus mDNS_StartResolveService(mDNS *const m, 12190 ServiceInfoQuery *query, ServiceInfo *info, mDNSServiceInfoQueryCallback *Callback, void *Context) 12191 { 12192 mStatus status; 12193 mDNS_Lock(m); 12194 12195 query->qSRV.ThisQInterval = -1; // So that mDNS_StopResolveService() knows whether to cancel this question 12196 query->qSRV.InterfaceID = info->InterfaceID; 12197 query->qSRV.flags = 0; 12198 query->qSRV.Target = zeroAddr; 12199 AssignDomainName(&query->qSRV.qname, &info->name); 12200 query->qSRV.qtype = kDNSType_SRV; 12201 query->qSRV.qclass = kDNSClass_IN; 12202 query->qSRV.LongLived = mDNSfalse; 12203 query->qSRV.ExpectUnique = mDNStrue; 12204 query->qSRV.ForceMCast = mDNSfalse; 12205 query->qSRV.ReturnIntermed = mDNSfalse; 12206 query->qSRV.SuppressUnusable = mDNSfalse; 12207 query->qSRV.DenyOnCellInterface = mDNSfalse; 12208 query->qSRV.DenyOnExpInterface = mDNSfalse; 12209 query->qSRV.SearchListIndex = 0; 12210 query->qSRV.AppendSearchDomains = 0; 12211 query->qSRV.RetryWithSearchDomains = mDNSfalse; 12212 query->qSRV.TimeoutQuestion = 0; 12213 query->qSRV.WakeOnResolve = 0; 12214 query->qSRV.UseBackgroundTrafficClass = mDNSfalse; 12215 query->qSRV.ValidationRequired = 0; 12216 query->qSRV.ValidatingResponse = 0; 12217 query->qSRV.ProxyQuestion = 0; 12218 query->qSRV.qnameOrig = mDNSNULL; 12219 query->qSRV.AnonInfo = mDNSNULL; 12220 query->qSRV.QuestionCallback = FoundServiceInfoSRV; 12221 query->qSRV.QuestionContext = query; 12222 12223 query->qTXT.ThisQInterval = -1; // So that mDNS_StopResolveService() knows whether to cancel this question 12224 query->qTXT.InterfaceID = info->InterfaceID; 12225 query->qTXT.flags = 0; 12226 query->qTXT.Target = zeroAddr; 12227 AssignDomainName(&query->qTXT.qname, &info->name); 12228 query->qTXT.qtype = kDNSType_TXT; 12229 query->qTXT.qclass = kDNSClass_IN; 12230 query->qTXT.LongLived = mDNSfalse; 12231 query->qTXT.ExpectUnique = mDNStrue; 12232 query->qTXT.ForceMCast = mDNSfalse; 12233 query->qTXT.ReturnIntermed = mDNSfalse; 12234 query->qTXT.SuppressUnusable = mDNSfalse; 12235 query->qTXT.DenyOnCellInterface = mDNSfalse; 12236 query->qTXT.DenyOnExpInterface = mDNSfalse; 12237 query->qTXT.SearchListIndex = 0; 12238 query->qTXT.AppendSearchDomains = 0; 12239 query->qTXT.RetryWithSearchDomains = mDNSfalse; 12240 query->qTXT.TimeoutQuestion = 0; 12241 query->qTXT.WakeOnResolve = 0; 12242 query->qTXT.UseBackgroundTrafficClass = mDNSfalse; 12243 query->qTXT.ValidationRequired = 0; 12244 query->qTXT.ValidatingResponse = 0; 12245 query->qTXT.ProxyQuestion = 0; 12246 query->qTXT.qnameOrig = mDNSNULL; 12247 query->qTXT.AnonInfo = mDNSNULL; 12248 query->qTXT.QuestionCallback = FoundServiceInfoTXT; 12249 query->qTXT.QuestionContext = query; 12250 12251 query->qAv4.ThisQInterval = -1; // So that mDNS_StopResolveService() knows whether to cancel this question 12252 query->qAv4.InterfaceID = info->InterfaceID; 12253 query->qAv4.flags = 0; 12254 query->qAv4.Target = zeroAddr; 12255 query->qAv4.qname.c[0] = 0; 12256 query->qAv4.qtype = kDNSType_A; 12257 query->qAv4.qclass = kDNSClass_IN; 12258 query->qAv4.LongLived = mDNSfalse; 12259 query->qAv4.ExpectUnique = mDNStrue; 12260 query->qAv4.ForceMCast = mDNSfalse; 12261 query->qAv4.ReturnIntermed = mDNSfalse; 12262 query->qAv4.SuppressUnusable = mDNSfalse; 12263 query->qAv4.DenyOnCellInterface = mDNSfalse; 12264 query->qAv4.DenyOnExpInterface = mDNSfalse; 12265 query->qAv4.SearchListIndex = 0; 12266 query->qAv4.AppendSearchDomains = 0; 12267 query->qAv4.RetryWithSearchDomains = mDNSfalse; 12268 query->qAv4.TimeoutQuestion = 0; 12269 query->qAv4.WakeOnResolve = 0; 12270 query->qAv4.UseBackgroundTrafficClass = mDNSfalse; 12271 query->qAv4.ValidationRequired = 0; 12272 query->qAv4.ValidatingResponse = 0; 12273 query->qAv4.ProxyQuestion = 0; 12274 query->qAv4.qnameOrig = mDNSNULL; 12275 query->qAv4.AnonInfo = mDNSNULL; 12276 query->qAv4.QuestionCallback = FoundServiceInfo; 12277 query->qAv4.QuestionContext = query; 12278 12279 query->qAv6.ThisQInterval = -1; // So that mDNS_StopResolveService() knows whether to cancel this question 12280 query->qAv6.InterfaceID = info->InterfaceID; 12281 query->qAv6.flags = 0; 12282 query->qAv6.Target = zeroAddr; 12283 query->qAv6.qname.c[0] = 0; 12284 query->qAv6.qtype = kDNSType_AAAA; 12285 query->qAv6.qclass = kDNSClass_IN; 12286 query->qAv6.LongLived = mDNSfalse; 12287 query->qAv6.ExpectUnique = mDNStrue; 12288 query->qAv6.ForceMCast = mDNSfalse; 12289 query->qAv6.ReturnIntermed = mDNSfalse; 12290 query->qAv6.SuppressUnusable = mDNSfalse; 12291 query->qAv6.DenyOnCellInterface = mDNSfalse; 12292 query->qAv6.DenyOnExpInterface = mDNSfalse; 12293 query->qAv6.SearchListIndex = 0; 12294 query->qAv6.AppendSearchDomains = 0; 12295 query->qAv6.RetryWithSearchDomains = mDNSfalse; 12296 query->qAv6.TimeoutQuestion = 0; 12297 query->qAv6.UseBackgroundTrafficClass = mDNSfalse; 12298 query->qAv6.ValidationRequired = 0; 12299 query->qAv6.ValidatingResponse = 0; 12300 query->qAv6.ProxyQuestion = 0; 12301 query->qAv6.qnameOrig = mDNSNULL; 12302 query->qAv6.AnonInfo = mDNSNULL; 12303 query->qAv6.QuestionCallback = FoundServiceInfo; 12304 query->qAv6.QuestionContext = query; 12305 12306 query->GotSRV = mDNSfalse; 12307 query->GotTXT = mDNSfalse; 12308 query->GotADD = mDNSfalse; 12309 query->Answers = 0; 12310 12311 query->info = info; 12312 query->ServiceInfoQueryCallback = Callback; 12313 query->ServiceInfoQueryContext = Context; 12314 12315 // info->name = Must already be set up by client 12316 // info->interface = Must already be set up by client 12317 info->ip = zeroAddr; 12318 info->port = zeroIPPort; 12319 info->TXTlen = 0; 12320 12321 // We use mDNS_StartQuery_internal here because we're already holding the lock 12322 status = mDNS_StartQuery_internal(m, &query->qSRV); 12323 if (status == mStatus_NoError) status = mDNS_StartQuery_internal(m, &query->qTXT); 12324 if (status != mStatus_NoError) mDNS_StopResolveService(m, query); 12325 12326 mDNS_Unlock(m); 12327 return(status); 12328 } 12329 12330 mDNSexport void mDNS_StopResolveService (mDNS *const m, ServiceInfoQuery *q) 12331 { 12332 mDNS_Lock(m); 12333 // We use mDNS_StopQuery_internal here because we're already holding the lock 12334 if (q->qSRV.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &q->qSRV); 12335 if (q->qTXT.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &q->qTXT); 12336 if (q->qAv4.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &q->qAv4); 12337 if (q->qAv6.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &q->qAv6); 12338 mDNS_Unlock(m); 12339 } 12340 12341 mDNSexport mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, mDNS_DomainType DomainType, const domainname *dom, 12342 const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *Callback, void *Context) 12343 { 12344 question->InterfaceID = InterfaceID; 12345 question->flags = 0; 12346 question->Target = zeroAddr; 12347 question->qtype = kDNSType_PTR; 12348 question->qclass = kDNSClass_IN; 12349 question->LongLived = mDNSfalse; 12350 question->ExpectUnique = mDNSfalse; 12351 question->ForceMCast = mDNSfalse; 12352 question->ReturnIntermed = mDNSfalse; 12353 question->SuppressUnusable = mDNSfalse; 12354 question->DenyOnCellInterface = mDNSfalse; 12355 question->DenyOnExpInterface = mDNSfalse; 12356 question->SearchListIndex = 0; 12357 question->AppendSearchDomains = 0; 12358 question->RetryWithSearchDomains = mDNSfalse; 12359 question->TimeoutQuestion = 0; 12360 question->WakeOnResolve = 0; 12361 question->UseBackgroundTrafficClass = mDNSfalse; 12362 question->ValidationRequired = 0; 12363 question->ValidatingResponse = 0; 12364 question->ProxyQuestion = 0; 12365 question->qnameOrig = mDNSNULL; 12366 question->AnonInfo = mDNSNULL; 12367 question->pid = mDNSPlatformGetPID(); 12368 question->QuestionCallback = Callback; 12369 question->QuestionContext = Context; 12370 if (DomainType > mDNS_DomainTypeMax) return(mStatus_BadParamErr); 12371 if (!MakeDomainNameFromDNSNameString(&question->qname, mDNS_DomainTypeNames[DomainType])) return(mStatus_BadParamErr); 12372 if (!dom) dom = &localdomain; 12373 if (!AppendDomainName(&question->qname, dom)) return(mStatus_BadParamErr); 12374 return(mDNS_StartQuery(m, question)); 12375 } 12376 12377 // *************************************************************************** 12378 #if COMPILER_LIKES_PRAGMA_MARK 12379 #pragma mark - 12380 #pragma mark - Responder Functions 12381 #endif 12382 12383 mDNSexport mStatus mDNS_Register(mDNS *const m, AuthRecord *const rr) 12384 { 12385 mStatus status; 12386 mDNS_Lock(m); 12387 status = mDNS_Register_internal(m, rr); 12388 mDNS_Unlock(m); 12389 return(status); 12390 } 12391 12392 mDNSexport mStatus mDNS_Update(mDNS *const m, AuthRecord *const rr, mDNSu32 newttl, 12393 const mDNSu16 newrdlength, RData *const newrdata, mDNSRecordUpdateCallback *Callback) 12394 { 12395 if (!ValidateRData(rr->resrec.rrtype, newrdlength, newrdata)) 12396 { 12397 LogMsg("Attempt to update record with invalid rdata: %s", GetRRDisplayString_rdb(&rr->resrec, &newrdata->u, m->MsgBuffer)); 12398 return(mStatus_Invalid); 12399 } 12400 12401 mDNS_Lock(m); 12402 12403 // If TTL is unspecified, leave TTL unchanged 12404 if (newttl == 0) newttl = rr->resrec.rroriginalttl; 12405 12406 // If we already have an update queued up which has not gone through yet, give the client a chance to free that memory 12407 if (rr->NewRData) 12408 { 12409 RData *n = rr->NewRData; 12410 rr->NewRData = mDNSNULL; // Clear the NewRData pointer ... 12411 if (rr->UpdateCallback) 12412 rr->UpdateCallback(m, rr, n, rr->newrdlength); // ...and let the client free this memory, if necessary 12413 } 12414 12415 rr->NewRData = newrdata; 12416 rr->newrdlength = newrdlength; 12417 rr->UpdateCallback = Callback; 12418 12419 #ifndef UNICAST_DISABLED 12420 if (rr->ARType != AuthRecordLocalOnly && rr->ARType != AuthRecordP2P && !IsLocalDomain(rr->resrec.name)) 12421 { 12422 mStatus status = uDNS_UpdateRecord(m, rr); 12423 // The caller frees the memory on error, don't retain stale pointers 12424 if (status != mStatus_NoError) { rr->NewRData = mDNSNULL; rr->newrdlength = 0; } 12425 mDNS_Unlock(m); 12426 return(status); 12427 } 12428 #endif 12429 12430 if (RRLocalOnly(rr) || (rr->resrec.rroriginalttl == newttl && 12431 rr->resrec.rdlength == newrdlength && mDNSPlatformMemSame(rr->resrec.rdata->u.data, newrdata->u.data, newrdlength))) 12432 CompleteRDataUpdate(m, rr); 12433 else 12434 { 12435 rr->AnnounceCount = InitialAnnounceCount; 12436 InitializeLastAPTime(m, rr); 12437 while (rr->NextUpdateCredit && m->timenow - rr->NextUpdateCredit >= 0) GrantUpdateCredit(rr); 12438 if (!rr->UpdateBlocked && rr->UpdateCredits) rr->UpdateCredits--; 12439 if (!rr->NextUpdateCredit) rr->NextUpdateCredit = NonZeroTime(m->timenow + kUpdateCreditRefreshInterval); 12440 if (rr->AnnounceCount > rr->UpdateCredits + 1) rr->AnnounceCount = (mDNSu8)(rr->UpdateCredits + 1); 12441 if (rr->UpdateCredits <= 5) 12442 { 12443 mDNSu32 delay = 6 - rr->UpdateCredits; // Delay 1 second, then 2, then 3, etc. up to 6 seconds maximum 12444 if (!rr->UpdateBlocked) rr->UpdateBlocked = NonZeroTime(m->timenow + (mDNSs32)delay * mDNSPlatformOneSecond); 12445 rr->ThisAPInterval *= 4; 12446 rr->LastAPTime = rr->UpdateBlocked - rr->ThisAPInterval; 12447 LogMsg("Excessive update rate for %##s; delaying announcement by %ld second%s", 12448 rr->resrec.name->c, delay, delay > 1 ? "s" : ""); 12449 } 12450 rr->resrec.rroriginalttl = newttl; 12451 } 12452 12453 mDNS_Unlock(m); 12454 return(mStatus_NoError); 12455 } 12456 12457 // Note: mDNS_Deregister calls mDNS_Deregister_internal which can call a user callback, which may change 12458 // the record list and/or question list. 12459 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this. 12460 mDNSexport mStatus mDNS_Deregister(mDNS *const m, AuthRecord *const rr) 12461 { 12462 mStatus status; 12463 mDNS_Lock(m); 12464 status = mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal); 12465 mDNS_Unlock(m); 12466 return(status); 12467 } 12468 12469 // Circular reference: AdvertiseInterface references mDNS_HostNameCallback, which calls mDNS_SetFQDN, which call AdvertiseInterface 12470 mDNSlocal void mDNS_HostNameCallback(mDNS *const m, AuthRecord *const rr, mStatus result); 12471 12472 mDNSlocal NetworkInterfaceInfo *FindFirstAdvertisedInterface(mDNS *const m) 12473 { 12474 NetworkInterfaceInfo *intf; 12475 for (intf = m->HostInterfaces; intf; intf = intf->next) 12476 if (intf->Advertise) break; 12477 return(intf); 12478 } 12479 12480 mDNSlocal void AdvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set) 12481 { 12482 char buffer[MAX_REVERSE_MAPPING_NAME]; 12483 NetworkInterfaceInfo *primary; 12484 12485 if (!set->McastTxRx) 12486 { 12487 LogInfo("AdvertiseInterface: Returning, not multicast capable %s", set->ifname); 12488 return; 12489 } 12490 #if TARGET_OS_EMBEDDED 12491 if (!m->AutoTargetServices) 12492 { 12493 LogInfo("AdvertiseInterface: Returning due to AutoTargetServices zero for %s", set->ifname); 12494 return; 12495 } 12496 #endif 12497 12498 primary = FindFirstAdvertisedInterface(m); 12499 if (!primary) primary = set; // If no existing advertised interface, this new NetworkInterfaceInfo becomes our new primary 12500 12501 // If interface is marked as a direct link, we can assume the address record is unique 12502 // and does not need to go through the probe phase of the probe/announce packet sequence. 12503 mDNSu8 recordType = (set->DirectLink ? kDNSRecordTypeKnownUnique : kDNSRecordTypeUnique); 12504 12505 if (set->DirectLink) 12506 LogInfo("AdvertiseInterface: Marking address record as kDNSRecordTypeKnownUnique for %s", set->ifname); 12507 12508 // Send dynamic update for non-linklocal IPv4 Addresses 12509 mDNS_SetupResourceRecord(&set->RR_A, mDNSNULL, set->InterfaceID, kDNSType_A, kHostNameTTL, recordType, AuthRecordAny, mDNS_HostNameCallback, set); 12510 mDNS_SetupResourceRecord(&set->RR_PTR, mDNSNULL, set->InterfaceID, kDNSType_PTR, kHostNameTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL); 12511 mDNS_SetupResourceRecord(&set->RR_HINFO, mDNSNULL, set->InterfaceID, kDNSType_HINFO, kHostNameTTL, kDNSRecordTypeUnique, AuthRecordAny, mDNSNULL, mDNSNULL); 12512 12513 #if ANSWER_REMOTE_HOSTNAME_QUERIES 12514 set->RR_A.AllowRemoteQuery = mDNStrue; 12515 set->RR_PTR.AllowRemoteQuery = mDNStrue; 12516 set->RR_HINFO.AllowRemoteQuery = mDNStrue; 12517 #endif 12518 // 1. Set up Address record to map from host name ("foo.local.") to IP address 12519 // 2. Set up reverse-lookup PTR record to map from our address back to our host name 12520 AssignDomainName(&set->RR_A.namestorage, &m->MulticastHostname); 12521 if (set->ip.type == mDNSAddrType_IPv4) 12522 { 12523 set->RR_A.resrec.rrtype = kDNSType_A; 12524 set->RR_A.resrec.rdata->u.ipv4 = set->ip.ip.v4; 12525 // Note: This is reverse order compared to a normal dotted-decimal IP address, so we can't use our customary "%.4a" format code 12526 mDNS_snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d.in-addr.arpa.", 12527 set->ip.ip.v4.b[3], set->ip.ip.v4.b[2], set->ip.ip.v4.b[1], set->ip.ip.v4.b[0]); 12528 } 12529 else if (set->ip.type == mDNSAddrType_IPv6) 12530 { 12531 int i; 12532 set->RR_A.resrec.rrtype = kDNSType_AAAA; 12533 set->RR_A.resrec.rdata->u.ipv6 = set->ip.ip.v6; 12534 for (i = 0; i < 16; i++) 12535 { 12536 static const char hexValues[] = "0123456789ABCDEF"; 12537 buffer[i * 4 ] = hexValues[set->ip.ip.v6.b[15 - i] & 0x0F]; 12538 buffer[i * 4 + 1] = '.'; 12539 buffer[i * 4 + 2] = hexValues[set->ip.ip.v6.b[15 - i] >> 4]; 12540 buffer[i * 4 + 3] = '.'; 12541 } 12542 mDNS_snprintf(&buffer[64], sizeof(buffer)-64, "ip6.arpa."); 12543 } 12544 12545 MakeDomainNameFromDNSNameString(&set->RR_PTR.namestorage, buffer); 12546 set->RR_PTR.AutoTarget = Target_AutoHost; // Tell mDNS that the target of this PTR is to be kept in sync with our host name 12547 set->RR_PTR.ForceMCast = mDNStrue; // This PTR points to our dot-local name, so don't ever try to write it into a uDNS server 12548 12549 set->RR_A.RRSet = &primary->RR_A; // May refer to self 12550 12551 mDNS_Register_internal(m, &set->RR_A); 12552 mDNS_Register_internal(m, &set->RR_PTR); 12553 12554 #if APPLE_OSX_mDNSResponder 12555 // must be after the mDNS_Register_internal() calls so that records have complete rdata fields, etc 12556 D2D_start_advertising_interface(set); 12557 #endif // APPLE_OSX_mDNSResponder 12558 12559 if (!NO_HINFO && m->HIHardware.c[0] > 0 && m->HISoftware.c[0] > 0 && m->HIHardware.c[0] + m->HISoftware.c[0] <= 254) 12560 { 12561 mDNSu8 *p = set->RR_HINFO.resrec.rdata->u.data; 12562 AssignDomainName(&set->RR_HINFO.namestorage, &m->MulticastHostname); 12563 set->RR_HINFO.DependentOn = &set->RR_A; 12564 mDNSPlatformMemCopy(p, &m->HIHardware, 1 + (mDNSu32)m->HIHardware.c[0]); 12565 p += 1 + (int)p[0]; 12566 mDNSPlatformMemCopy(p, &m->HISoftware, 1 + (mDNSu32)m->HISoftware.c[0]); 12567 mDNS_Register_internal(m, &set->RR_HINFO); 12568 } 12569 else 12570 { 12571 debugf("Not creating HINFO record: platform support layer provided no information"); 12572 set->RR_HINFO.resrec.RecordType = kDNSRecordTypeUnregistered; 12573 } 12574 } 12575 12576 mDNSlocal void DeadvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set) 12577 { 12578 NetworkInterfaceInfo *intf; 12579 12580 // If we still have address records referring to this one, update them 12581 NetworkInterfaceInfo *primary = FindFirstAdvertisedInterface(m); 12582 AuthRecord *A = primary ? &primary->RR_A : mDNSNULL; 12583 for (intf = m->HostInterfaces; intf; intf = intf->next) 12584 if (intf->RR_A.RRSet == &set->RR_A) 12585 intf->RR_A.RRSet = A; 12586 12587 // Unregister these records. 12588 // When doing the mDNS_Exit processing, we first call DeadvertiseInterface for each interface, so by the time the platform 12589 // support layer gets to call mDNS_DeregisterInterface, the address and PTR records have already been deregistered for it. 12590 // Also, in the event of a name conflict, one or more of our records will have been forcibly deregistered. 12591 // To avoid unnecessary and misleading warning messages, we check the RecordType before calling mDNS_Deregister_internal(). 12592 if (set->RR_A.resrec.RecordType) mDNS_Deregister_internal(m, &set->RR_A, mDNS_Dereg_normal); 12593 if (set->RR_PTR.resrec.RecordType) mDNS_Deregister_internal(m, &set->RR_PTR, mDNS_Dereg_normal); 12594 if (set->RR_HINFO.resrec.RecordType) mDNS_Deregister_internal(m, &set->RR_HINFO, mDNS_Dereg_normal); 12595 12596 #if APPLE_OSX_mDNSResponder 12597 D2D_stop_advertising_interface(set); 12598 #endif // APPLE_OSX_mDNSResponder 12599 12600 } 12601 12602 mDNSlocal void AdvertiseAllInterfaceRecords(mDNS *const m) 12603 { 12604 NetworkInterfaceInfo *intf; 12605 for (intf = m->HostInterfaces; intf; intf = intf->next) 12606 { 12607 if (intf->Advertise) 12608 { 12609 LogInfo("AdvertiseInterface: Advertising for ifname %s", intf->ifname); 12610 AdvertiseInterface(m, intf); 12611 } 12612 } 12613 } 12614 12615 mDNSlocal void DeadvertiseAllInterfaceRecords(mDNS *const m) 12616 { 12617 #if TARGET_OS_EMBEDDED 12618 NetworkInterfaceInfo *intf; 12619 for (intf = m->HostInterfaces; intf; intf = intf->next) 12620 { 12621 if (intf->Advertise) 12622 { 12623 LogInfo("DeadvertiseInterface: Deadvertising for ifname %s", intf->ifname); 12624 DeadvertiseInterface(m, intf); 12625 } 12626 } 12627 #else 12628 (void) m; //unused 12629 #endif 12630 } 12631 12632 mDNSexport void mDNS_SetFQDN(mDNS *const m) 12633 { 12634 domainname newmname; 12635 NetworkInterfaceInfo *intf; 12636 AuthRecord *rr; 12637 newmname.c[0] = 0; 12638 12639 if (!AppendDomainLabel(&newmname, &m->hostlabel)) { LogMsg("ERROR: mDNS_SetFQDN: Cannot create MulticastHostname"); return; } 12640 if (!AppendLiteralLabelString(&newmname, "local")) { LogMsg("ERROR: mDNS_SetFQDN: Cannot create MulticastHostname"); return; } 12641 12642 mDNS_Lock(m); 12643 12644 if (SameDomainNameCS(&m->MulticastHostname, &newmname)) debugf("mDNS_SetFQDN - hostname unchanged"); 12645 else 12646 { 12647 AssignDomainName(&m->MulticastHostname, &newmname); 12648 12649 // 1. Stop advertising our address records on all interfaces 12650 for (intf = m->HostInterfaces; intf; intf = intf->next) 12651 if (intf->Advertise) DeadvertiseInterface(m, intf); 12652 12653 // 2. Start advertising our address records using the new name 12654 for (intf = m->HostInterfaces; intf; intf = intf->next) 12655 if (intf->Advertise) AdvertiseInterface(m, intf); 12656 } 12657 12658 // 3. Make sure that any AutoTarget SRV records (and the like) get updated 12659 for (rr = m->ResourceRecords; rr; rr=rr->next) if (rr->AutoTarget) SetTargetToHostName(m, rr); 12660 for (rr = m->DuplicateRecords; rr; rr=rr->next) if (rr->AutoTarget) SetTargetToHostName(m, rr); 12661 12662 mDNS_Unlock(m); 12663 } 12664 12665 mDNSlocal void mDNS_HostNameCallback(mDNS *const m, AuthRecord *const rr, mStatus result) 12666 { 12667 (void)rr; // Unused parameter 12668 12669 #if MDNS_DEBUGMSGS 12670 { 12671 char *msg = "Unknown result"; 12672 if (result == mStatus_NoError) msg = "Name registered"; 12673 else if (result == mStatus_NameConflict) msg = "Name conflict"; 12674 debugf("mDNS_HostNameCallback: %##s (%s) %s (%ld)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), msg, result); 12675 } 12676 #endif 12677 12678 if (result == mStatus_NoError) 12679 { 12680 // Notify the client that the host name is successfully registered 12681 if (m->MainCallback) 12682 m->MainCallback(m, mStatus_NoError); 12683 } 12684 else if (result == mStatus_NameConflict) 12685 { 12686 domainlabel oldlabel = m->hostlabel; 12687 12688 // 1. First give the client callback a chance to pick a new name 12689 if (m->MainCallback) 12690 m->MainCallback(m, mStatus_NameConflict); 12691 12692 // 2. If the client callback didn't do it, add (or increment) an index ourselves 12693 // This needs to be case-INSENSITIVE compare, because we need to know that the name has been changed so as to 12694 // remedy the conflict, and a name that differs only in capitalization will just suffer the exact same conflict again. 12695 if (SameDomainLabel(m->hostlabel.c, oldlabel.c)) 12696 IncrementLabelSuffix(&m->hostlabel, mDNSfalse); 12697 12698 // 3. Generate the FQDNs from the hostlabel, 12699 // and make sure all SRV records, etc., are updated to reference our new hostname 12700 mDNS_SetFQDN(m); 12701 LogMsg("Local Hostname %#s.local already in use; will try %#s.local instead", oldlabel.c, m->hostlabel.c); 12702 } 12703 else if (result == mStatus_MemFree) 12704 { 12705 // .local hostnames do not require goodbyes - we ignore the MemFree (which is sent directly by 12706 // mDNS_Deregister_internal), and allow the caller to deallocate immediately following mDNS_DeadvertiseInterface 12707 debugf("mDNS_HostNameCallback: MemFree (ignored)"); 12708 } 12709 else 12710 LogMsg("mDNS_HostNameCallback: Unknown error %d for registration of record %s", result, rr->resrec.name->c); 12711 } 12712 12713 mDNSlocal void UpdateInterfaceProtocols(mDNS *const m, NetworkInterfaceInfo *active) 12714 { 12715 NetworkInterfaceInfo *intf; 12716 active->IPv4Available = mDNSfalse; 12717 active->IPv6Available = mDNSfalse; 12718 for (intf = m->HostInterfaces; intf; intf = intf->next) 12719 if (intf->InterfaceID == active->InterfaceID) 12720 { 12721 if (intf->ip.type == mDNSAddrType_IPv4 && intf->McastTxRx) active->IPv4Available = mDNStrue; 12722 if (intf->ip.type == mDNSAddrType_IPv6 && intf->McastTxRx) active->IPv6Available = mDNStrue; 12723 } 12724 } 12725 12726 mDNSlocal void RestartRecordGetZoneData(mDNS * const m) 12727 { 12728 AuthRecord *rr; 12729 LogInfo("RestartRecordGetZoneData: ResourceRecords"); 12730 for (rr = m->ResourceRecords; rr; rr=rr->next) 12731 if (AuthRecord_uDNS(rr) && rr->state != regState_NoTarget) 12732 { 12733 debugf("RestartRecordGetZoneData: StartGetZoneData for %##s", rr->resrec.name->c); 12734 // Zero out the updateid so that if we have a pending response from the server, it won't 12735 // be accepted as a valid response. If we accept the response, we might free the new "nta" 12736 if (rr->nta) { rr->updateid = zeroID; CancelGetZoneData(m, rr->nta); } 12737 rr->nta = StartGetZoneData(m, rr->resrec.name, ZoneServiceUpdate, RecordRegistrationGotZoneData, rr); 12738 } 12739 } 12740 12741 mDNSlocal void InitializeNetWakeState(mDNS *const m, NetworkInterfaceInfo *set) 12742 { 12743 int i; 12744 // We initialize ThisQInterval to -1 indicating that the question has not been started 12745 // yet. If the question (browse) is started later during interface registration, it will 12746 // be stopped during interface deregistration. We can't sanity check to see if the 12747 // question has been stopped or not before initializing it to -1 because we need to 12748 // initialize it to -1 the very first time. 12749 12750 set->NetWakeBrowse.ThisQInterval = -1; 12751 for (i=0; i<3; i++) 12752 { 12753 set->NetWakeResolve[i].ThisQInterval = -1; 12754 set->SPSAddr[i].type = mDNSAddrType_None; 12755 } 12756 set->NextSPSAttempt = -1; 12757 set->NextSPSAttemptTime = m->timenow; 12758 } 12759 12760 mDNSexport void mDNS_ActivateNetWake_internal(mDNS *const m, NetworkInterfaceInfo *set) 12761 { 12762 NetworkInterfaceInfo *p = m->HostInterfaces; 12763 while (p && p != set) p=p->next; 12764 if (!p) { LogMsg("mDNS_ActivateNetWake_internal: NetworkInterfaceInfo %p not found in active list", set); return; } 12765 12766 if (set->InterfaceActive) 12767 { 12768 LogSPS("ActivateNetWake for %s (%#a)", set->ifname, &set->ip); 12769 mDNS_StartBrowse_internal(m, &set->NetWakeBrowse, &SleepProxyServiceType, &localdomain, mDNSNULL, set->InterfaceID, 0, mDNSfalse, mDNSfalse, m->SPSBrowseCallback, set); 12770 } 12771 } 12772 12773 mDNSexport void mDNS_DeactivateNetWake_internal(mDNS *const m, NetworkInterfaceInfo *set) 12774 { 12775 NetworkInterfaceInfo *p = m->HostInterfaces; 12776 while (p && p != set) p=p->next; 12777 if (!p) { LogMsg("mDNS_DeactivateNetWake_internal: NetworkInterfaceInfo %p not found in active list", set); return; } 12778 12779 // Note: We start the browse only if the interface is NetWake capable and we use this to 12780 // stop the resolves also. Hence, the resolves should not be started without the browse 12781 // being started i.e, resolves should not happen unless NetWake capable which is 12782 // guaranteed by BeginSleepProcessing. 12783 if (set->NetWakeBrowse.ThisQInterval >= 0) 12784 { 12785 int i; 12786 LogSPS("DeactivateNetWake for %s (%#a)", set->ifname, &set->ip); 12787 12788 // Stop our browse and resolve operations 12789 mDNS_StopQuery_internal(m, &set->NetWakeBrowse); 12790 for (i=0; i<3; i++) if (set->NetWakeResolve[i].ThisQInterval >= 0) mDNS_StopQuery_internal(m, &set->NetWakeResolve[i]); 12791 12792 // Make special call to the browse callback to let it know it can to remove all records for this interface 12793 if (m->SPSBrowseCallback) 12794 { 12795 mDNS_DropLockBeforeCallback(); // Allow client to legally make mDNS API calls from the callback 12796 m->SPSBrowseCallback(m, &set->NetWakeBrowse, mDNSNULL, QC_rmv); 12797 mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again 12798 } 12799 12800 // Reset our variables back to initial state, so we're ready for when NetWake is turned back on 12801 // (includes resetting NetWakeBrowse.ThisQInterval back to -1) 12802 InitializeNetWakeState(m, set); 12803 } 12804 } 12805 12806 mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping) 12807 { 12808 AuthRecord *rr; 12809 mDNSBool FirstOfType = mDNStrue; 12810 NetworkInterfaceInfo **p = &m->HostInterfaces; 12811 12812 if (!set->InterfaceID) 12813 { LogMsg("mDNS_RegisterInterface: Error! Tried to register a NetworkInterfaceInfo %#a with zero InterfaceID", &set->ip); return(mStatus_Invalid); } 12814 12815 if (!mDNSAddressIsValidNonZero(&set->mask)) 12816 { LogMsg("mDNS_RegisterInterface: Error! Tried to register a NetworkInterfaceInfo %#a with invalid mask %#a", &set->ip, &set->mask); return(mStatus_Invalid); } 12817 12818 mDNS_Lock(m); 12819 12820 // Assume this interface will be active now, unless we find a duplicate already in the list 12821 set->InterfaceActive = mDNStrue; 12822 set->IPv4Available = (mDNSu8)(set->ip.type == mDNSAddrType_IPv4 && set->McastTxRx); 12823 set->IPv6Available = (mDNSu8)(set->ip.type == mDNSAddrType_IPv6 && set->McastTxRx); 12824 12825 InitializeNetWakeState(m, set); 12826 12827 // Scan list to see if this InterfaceID is already represented 12828 while (*p) 12829 { 12830 if (*p == set) 12831 { 12832 LogMsg("mDNS_RegisterInterface: Error! Tried to register a NetworkInterfaceInfo that's already in the list"); 12833 mDNS_Unlock(m); 12834 return(mStatus_AlreadyRegistered); 12835 } 12836 12837 if ((*p)->InterfaceID == set->InterfaceID) 12838 { 12839 // This InterfaceID already represented by a different interface in the list, so mark this instance inactive for now 12840 set->InterfaceActive = mDNSfalse; 12841 if (set->ip.type == (*p)->ip.type) FirstOfType = mDNSfalse; 12842 if (set->ip.type == mDNSAddrType_IPv4 && set->McastTxRx) (*p)->IPv4Available = mDNStrue; 12843 if (set->ip.type == mDNSAddrType_IPv6 && set->McastTxRx) (*p)->IPv6Available = mDNStrue; 12844 } 12845 12846 p=&(*p)->next; 12847 } 12848 12849 set->next = mDNSNULL; 12850 *p = set; 12851 12852 if (set->Advertise) 12853 AdvertiseInterface(m, set); 12854 12855 LogInfo("mDNS_RegisterInterface: InterfaceID %d %s (%#a) %s", 12856 (uint32_t)set->InterfaceID, set->ifname, &set->ip, 12857 set->InterfaceActive ? 12858 "not represented in list; marking active and retriggering queries" : 12859 "already represented in list; marking inactive for now"); 12860 12861 if (set->NetWake) mDNS_ActivateNetWake_internal(m, set); 12862 12863 // In early versions of OS X the IPv6 address remains on an interface even when the interface is turned off, 12864 // giving the false impression that there's an active representative of this interface when there really isn't. 12865 // Therefore, when registering an interface, we want to re-trigger our questions and re-probe our Resource Records, 12866 // even if we believe that we previously had an active representative of this interface. 12867 if (set->McastTxRx && (FirstOfType || set->InterfaceActive)) 12868 { 12869 DNSQuestion *q; 12870 // Normally, after an interface comes up, we pause half a second before beginning probing. 12871 // This is to guard against cases where there's rapid interface changes, where we could be confused by 12872 // seeing packets we ourselves sent just moments ago (perhaps when this interface had a different address) 12873 // which are then echoed back after a short delay by some Ethernet switches and some 802.11 base stations. 12874 // We don't want to do a probe, and then see a stale echo of an announcement we ourselves sent, 12875 // and think it's a conflicting answer to our probe. 12876 // In the case of a flapping interface, we pause for five seconds, and reduce the announcement count to one packet. 12877 const mDNSs32 probedelay = flapping ? mDNSPlatformOneSecond * 5 : mDNSPlatformOneSecond / 2; 12878 const mDNSu8 numannounce = flapping ? (mDNSu8)1 : InitialAnnounceCount; 12879 12880 // Use a small amount of randomness: 12881 // In the case of a network administrator turning on an Ethernet hub so that all the 12882 // connected machines establish link at exactly the same time, we don't want them all 12883 // to go and hit the network with identical queries at exactly the same moment. 12884 // We set a random delay of up to InitialQuestionInterval (1/3 second). 12885 // We must *never* set m->SuppressSending to more than that (or set it repeatedly in a way 12886 // that causes mDNSResponder to remain in a prolonged state of SuppressSending, because 12887 // suppressing packet sending for more than about 1/3 second can cause protocol correctness 12888 // to start to break down (e.g. we don't answer probes fast enough, and get name conflicts). 12889 // See <rdar://problem/4073853> mDNS: m->SuppressSending set too enthusiastically 12890 if (!m->SuppressSending) m->SuppressSending = m->timenow + (mDNSs32)mDNSRandom((mDNSu32)InitialQuestionInterval); 12891 12892 if (flapping) 12893 { 12894 LogMsg("mDNS_RegisterInterface: Frequent transitions for interface %s (%#a)", set->ifname, &set->ip); 12895 m->mDNSStats.InterfaceUpFlap++; 12896 } 12897 12898 LogInfo("mDNS_RegisterInterface: %s (%#a) probedelay %d", set->ifname, &set->ip, probedelay); 12899 if (m->SuppressProbes == 0 || 12900 m->SuppressProbes - NonZeroTime(m->timenow + probedelay) < 0) 12901 m->SuppressProbes = NonZeroTime(m->timenow + probedelay); 12902 12903 // Include OWNER option in packets for 60 seconds after connecting to the network. Setting 12904 // it here also handles the wake up case as the network link comes UP after waking causing 12905 // us to reconnect to the network. If we do this as part of the wake up code, it is possible 12906 // that the network link comes UP after 60 seconds and we never set the OWNER option 12907 m->AnnounceOwner = NonZeroTime(m->timenow + 60 * mDNSPlatformOneSecond); 12908 LogInfo("mDNS_RegisterInterface: Setting AnnounceOwner"); 12909 12910 m->mDNSStats.InterfaceUp++; 12911 for (q = m->Questions; q; q=q->next) // Scan our list of questions 12912 { 12913 if (mDNSOpaque16IsZero(q->TargetQID)) 12914 { 12915 if (!q->InterfaceID || q->InterfaceID == set->InterfaceID) // If non-specific Q, or Q on this specific interface, 12916 { // then reactivate this question 12917 // If flapping, delay between first and second queries is nine seconds instead of one second 12918 mDNSBool dodelay = flapping && (q->FlappingInterface1 == set->InterfaceID || q->FlappingInterface2 == set->InterfaceID); 12919 mDNSs32 initial = dodelay ? InitialQuestionInterval * QuestionIntervalStep2 : InitialQuestionInterval; 12920 mDNSs32 qdelay = dodelay ? mDNSPlatformOneSecond * 5 : 0; 12921 if (dodelay) LogInfo("No cache records expired for %##s (%s); okay to delay questions a little", q->qname.c, DNSTypeName(q->qtype)); 12922 12923 if (!q->ThisQInterval || q->ThisQInterval > initial) 12924 { 12925 q->ThisQInterval = initial; 12926 12927 #if mDNS_REQUEST_UNICAST_RESPONSE 12928 q->RequestUnicast = SET_QU_IN_FIRST_FOUR_QUERIES; 12929 #else // mDNS_REQUEST_UNICAST_RESPONSE 12930 q->RequestUnicast = SET_QU_IN_FIRST_QUERY; 12931 #endif // mDNS_REQUEST_UNICAST_RESPONSE 12932 12933 } 12934 q->LastQTime = m->timenow - q->ThisQInterval + qdelay; 12935 q->RecentAnswerPkts = 0; 12936 // Change the salt 12937 ReInitAnonInfo(&q->AnonInfo, &q->qname); 12938 SetNextQueryTime(m,q); 12939 } 12940 } 12941 } 12942 12943 // For all our non-specific authoritative resource records (and any dormant records specific to this interface) 12944 // we now need them to re-probe if necessary, and then re-announce. 12945 for (rr = m->ResourceRecords; rr; rr=rr->next) 12946 { 12947 if (!rr->resrec.InterfaceID || rr->resrec.InterfaceID == set->InterfaceID) 12948 { 12949 // Change the salt 12950 ReInitAnonInfo(&rr->resrec.AnonInfo, rr->resrec.name); 12951 mDNSCoreRestartRegistration(m, rr, numannounce); 12952 } 12953 } 12954 #if APPLE_OSX_mDNSResponder && !TARGET_OS_IPHONE 12955 DNSSECProbe(m); 12956 #endif 12957 } 12958 12959 RestartRecordGetZoneData(m); 12960 12961 mDNS_UpdateAllowSleep(m); 12962 12963 mDNS_Unlock(m); 12964 return(mStatus_NoError); 12965 } 12966 12967 // Note: mDNS_DeregisterInterface calls mDNS_Deregister_internal which can call a user callback, which may change 12968 // the record list and/or question list. 12969 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this. 12970 mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping) 12971 { 12972 NetworkInterfaceInfo **p = &m->HostInterfaces; 12973 mDNSBool revalidate = mDNSfalse; 12974 12975 mDNS_Lock(m); 12976 12977 // Find this record in our list 12978 while (*p && *p != set) p=&(*p)->next; 12979 if (!*p) { debugf("mDNS_DeregisterInterface: NetworkInterfaceInfo not found in list"); mDNS_Unlock(m); return; } 12980 12981 mDNS_DeactivateNetWake_internal(m, set); 12982 12983 // Unlink this record from our list 12984 *p = (*p)->next; 12985 set->next = mDNSNULL; 12986 12987 if (!set->InterfaceActive) 12988 { 12989 // If this interface not the active member of its set, update the v4/v6Available flags for the active member 12990 NetworkInterfaceInfo *intf; 12991 for (intf = m->HostInterfaces; intf; intf = intf->next) 12992 if (intf->InterfaceActive && intf->InterfaceID == set->InterfaceID) 12993 UpdateInterfaceProtocols(m, intf); 12994 } 12995 else 12996 { 12997 NetworkInterfaceInfo *intf = FirstInterfaceForID(m, set->InterfaceID); 12998 if (intf) 12999 { 13000 LogInfo("mDNS_DeregisterInterface: Another representative of InterfaceID %d %s (%#a) exists;" 13001 " making it active", (uint32_t)set->InterfaceID, set->ifname, &set->ip); 13002 if (intf->InterfaceActive) 13003 LogMsg("mDNS_DeregisterInterface: ERROR intf->InterfaceActive already set for %s (%#a)", set->ifname, &set->ip); 13004 intf->InterfaceActive = mDNStrue; 13005 UpdateInterfaceProtocols(m, intf); 13006 13007 if (intf->NetWake) mDNS_ActivateNetWake_internal(m, intf); 13008 13009 // See if another representative *of the same type* exists. If not, we mave have gone from 13010 // dual-stack to v6-only (or v4-only) so we need to reconfirm which records are still valid. 13011 for (intf = m->HostInterfaces; intf; intf = intf->next) 13012 if (intf->InterfaceID == set->InterfaceID && intf->ip.type == set->ip.type) 13013 break; 13014 if (!intf) revalidate = mDNStrue; 13015 } 13016 else 13017 { 13018 mDNSu32 slot; 13019 CacheGroup *cg; 13020 CacheRecord *rr; 13021 DNSQuestion *q; 13022 13023 LogInfo("mDNS_DeregisterInterface: Last representative of InterfaceID %d %s (%#a) deregistered;" 13024 " marking questions etc. dormant", (uint32_t)set->InterfaceID, set->ifname, &set->ip); 13025 13026 m->mDNSStats.InterfaceDown++; 13027 13028 if (set->McastTxRx && flapping) 13029 { 13030 LogMsg("DeregisterInterface: Frequent transitions for interface %s (%#a)", set->ifname, &set->ip); 13031 m->mDNSStats.InterfaceDownFlap++; 13032 } 13033 13034 // 1. Deactivate any questions specific to this interface, and tag appropriate questions 13035 // so that mDNS_RegisterInterface() knows how swiftly it needs to reactivate them 13036 for (q = m->Questions; q; q=q->next) 13037 { 13038 if (q->InterfaceID == set->InterfaceID) q->ThisQInterval = 0; 13039 if (!q->InterfaceID || q->InterfaceID == set->InterfaceID) 13040 { 13041 q->FlappingInterface2 = q->FlappingInterface1; 13042 q->FlappingInterface1 = set->InterfaceID; // Keep history of the last two interfaces to go away 13043 } 13044 } 13045 13046 // 2. Flush any cache records received on this interface 13047 revalidate = mDNSfalse; // Don't revalidate if we're flushing the records 13048 FORALL_CACHERECORDS(slot, cg, rr) 13049 { 13050 if (rr->resrec.InterfaceID == set->InterfaceID) 13051 { 13052 // If this interface is deemed flapping, 13053 // postpone deleting the cache records in case the interface comes back again 13054 if (set->McastTxRx && flapping) 13055 { 13056 // For a flapping interface we want these record to go away after 30 seconds 13057 mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForFlappingInterface); 13058 // We set UnansweredQueries = MaxUnansweredQueries so we don't waste time doing any queries for them -- 13059 // if the interface does come back, any relevant questions will be reactivated anyway 13060 rr->UnansweredQueries = MaxUnansweredQueries; 13061 } 13062 else 13063 { 13064 mDNS_PurgeCacheResourceRecord(m, rr); 13065 } 13066 } 13067 } 13068 } 13069 } 13070 13071 // If we were advertising on this interface, deregister those address and reverse-lookup records now 13072 if (set->Advertise) DeadvertiseInterface(m, set); 13073 13074 // If we have any cache records received on this interface that went away, then re-verify them. 13075 // In some versions of OS X the IPv6 address remains on an interface even when the interface is turned off, 13076 // giving the false impression that there's an active representative of this interface when there really isn't. 13077 // Don't need to do this when shutting down, because *all* interfaces are about to go away 13078 if (revalidate && !m->ShutdownTime) 13079 { 13080 mDNSu32 slot; 13081 CacheGroup *cg; 13082 CacheRecord *rr; 13083 FORALL_CACHERECORDS(slot, cg, rr) 13084 if (rr->resrec.InterfaceID == set->InterfaceID) 13085 mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForFlappingInterface); 13086 } 13087 13088 mDNS_UpdateAllowSleep(m); 13089 13090 mDNS_Unlock(m); 13091 } 13092 13093 mDNSlocal void SetAnonInfoSRS(ServiceRecordSet *sr, int NumSubTypes) 13094 { 13095 int i, len; 13096 13097 if (!sr->AnonData) 13098 return; 13099 13100 len = mDNSPlatformStrLen(sr->AnonData); 13101 if (sr->RR_PTR.resrec.AnonInfo) 13102 { 13103 LogMsg("SetAnonInfoSRS: Freeing AnonInfo for PTR record %##s, should have been freed already", sr->RR_PTR.resrec.name->c); 13104 FreeAnonInfo(sr->RR_PTR.resrec.AnonInfo); 13105 } 13106 sr->RR_PTR.resrec.AnonInfo = AllocateAnonInfo(sr->RR_PTR.resrec.name, sr->AnonData, len, mDNSNULL); 13107 for (i=0; i<NumSubTypes; i++) 13108 { 13109 if (sr->SubTypes[i].resrec.AnonInfo) 13110 { 13111 LogMsg("SetAnonInfoSRS: Freeing AnonInfo for subtype record %##s, should have been freed already", sr->SubTypes[i].resrec.name->c); 13112 FreeAnonInfo(sr->SubTypes[i].resrec.AnonInfo); 13113 } 13114 sr->SubTypes[i].resrec.AnonInfo = AllocateAnonInfo(sr->SubTypes[i].resrec.name, sr->AnonData, len, mDNSNULL); 13115 } 13116 } 13117 13118 mDNSlocal void ResetAnonInfoSRS(ServiceRecordSet *sr, int NumSubTypes) 13119 { 13120 int i; 13121 13122 if (!sr->AnonData) 13123 return; 13124 if (sr->RR_PTR.resrec.AnonInfo) 13125 { 13126 FreeAnonInfo(sr->RR_PTR.resrec.AnonInfo); 13127 sr->RR_PTR.resrec.AnonInfo = mDNSNULL; 13128 } 13129 for (i=0; i<NumSubTypes; i++) 13130 { 13131 if (sr->SubTypes[i].resrec.AnonInfo) 13132 { 13133 FreeAnonInfo(sr->SubTypes[i].resrec.AnonInfo); 13134 sr->SubTypes[i].resrec.AnonInfo = mDNSNULL; 13135 } 13136 } 13137 } 13138 13139 mDNSlocal void ServiceCallback(mDNS *const m, AuthRecord *const rr, mStatus result) 13140 { 13141 ServiceRecordSet *sr = (ServiceRecordSet *)rr->RecordContext; 13142 (void)m; // Unused parameter 13143 13144 #if MDNS_DEBUGMSGS 13145 { 13146 char *msg = "Unknown result"; 13147 if (result == mStatus_NoError) msg = "Name Registered"; 13148 else if (result == mStatus_NameConflict) msg = "Name Conflict"; 13149 else if (result == mStatus_MemFree) msg = "Memory Free"; 13150 debugf("ServiceCallback: %##s (%s) %s (%d)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), msg, result); 13151 } 13152 #endif 13153 13154 // Only pass on the NoError acknowledgement for the SRV record (when it finishes probing) 13155 if (result == mStatus_NoError && rr != &sr->RR_SRV) return; 13156 13157 // If we got a name conflict on either SRV or TXT, forcibly deregister this service, and record that we did that 13158 if (result == mStatus_NameConflict) 13159 { 13160 sr->Conflict = mDNStrue; // Record that this service set had a conflict 13161 mDNS_DeregisterService(m, sr); // Unlink the records from our list 13162 return; 13163 } 13164 13165 if (result == mStatus_MemFree) 13166 { 13167 // If the SRV/TXT/PTR records, or the _services._dns-sd._udp record, or any of the subtype PTR records, 13168 // are still in the process of deregistering, don't pass on the NameConflict/MemFree message until 13169 // every record is finished cleaning up. 13170 mDNSu32 i; 13171 ExtraResourceRecord *e = sr->Extras; 13172 13173 if (sr->RR_SRV.resrec.RecordType != kDNSRecordTypeUnregistered) return; 13174 if (sr->RR_TXT.resrec.RecordType != kDNSRecordTypeUnregistered) return; 13175 if (sr->RR_PTR.resrec.RecordType != kDNSRecordTypeUnregistered) return; 13176 if (sr->RR_ADV.resrec.RecordType != kDNSRecordTypeUnregistered) return; 13177 for (i=0; i<sr->NumSubTypes; i++) if (sr->SubTypes[i].resrec.RecordType != kDNSRecordTypeUnregistered) return; 13178 13179 while (e) 13180 { 13181 if (e->r.resrec.RecordType != kDNSRecordTypeUnregistered) return; 13182 e = e->next; 13183 } 13184 ResetAnonInfoSRS(sr, sr->NumSubTypes); 13185 13186 // If this ServiceRecordSet was forcibly deregistered, and now its memory is ready for reuse, 13187 // then we can now report the NameConflict to the client 13188 if (sr->Conflict) result = mStatus_NameConflict; 13189 13190 } 13191 13192 LogInfo("ServiceCallback: All records %s for %##s", (result == mStatus_MemFree ? "Unregistered" : "Registered"), sr->RR_PTR.resrec.name->c); 13193 // CAUTION: MUST NOT do anything more with sr after calling sr->Callback(), because the client's callback 13194 // function is allowed to do anything, including deregistering this service and freeing its memory. 13195 if (sr->ServiceCallback) 13196 sr->ServiceCallback(m, sr, result); 13197 } 13198 13199 mDNSlocal void NSSCallback(mDNS *const m, AuthRecord *const rr, mStatus result) 13200 { 13201 ServiceRecordSet *sr = (ServiceRecordSet *)rr->RecordContext; 13202 if (sr->ServiceCallback) 13203 sr->ServiceCallback(m, sr, result); 13204 } 13205 13206 13207 mDNSlocal AuthRecType setAuthRecType(mDNSInterfaceID InterfaceID, mDNSu32 flags) 13208 { 13209 AuthRecType artype; 13210 13211 if (InterfaceID == mDNSInterface_LocalOnly) 13212 artype = AuthRecordLocalOnly; 13213 else if (InterfaceID == mDNSInterface_P2P) 13214 artype = AuthRecordP2P; 13215 else if ((InterfaceID == mDNSInterface_Any) && (flags & coreFlagIncludeP2P) 13216 && (flags & coreFlagIncludeAWDL)) 13217 artype = AuthRecordAnyIncludeAWDLandP2P; 13218 else if ((InterfaceID == mDNSInterface_Any) && (flags & coreFlagIncludeP2P)) 13219 artype = AuthRecordAnyIncludeP2P; 13220 else if ((InterfaceID == mDNSInterface_Any) && (flags & coreFlagIncludeAWDL)) 13221 artype = AuthRecordAnyIncludeAWDL; 13222 else 13223 artype = AuthRecordAny; 13224 13225 return artype; 13226 } 13227 13228 // Note: 13229 // Name is first label of domain name (any dots in the name are actual dots, not label separators) 13230 // Type is service type (e.g. "_ipp._tcp.") 13231 // Domain is fully qualified domain name (i.e. ending with a null label) 13232 // We always register a TXT, even if it is empty (so that clients are not 13233 // left waiting forever looking for a nonexistent record.) 13234 // If the host parameter is mDNSNULL or the root domain (ASCII NUL), 13235 // then the default host name (m->MulticastHostname) is automatically used 13236 // If the optional target host parameter is set, then the storage it points to must remain valid for the lifetime of the service registration 13237 mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr, 13238 const domainlabel *const name, const domainname *const type, const domainname *const domain, 13239 const domainname *const host, mDNSIPPort port, const mDNSu8 txtinfo[], mDNSu16 txtlen, 13240 AuthRecord *SubTypes, mDNSu32 NumSubTypes, 13241 mDNSInterfaceID InterfaceID, mDNSServiceCallback Callback, void *Context, mDNSu32 flags) 13242 { 13243 mStatus err; 13244 mDNSu32 i; 13245 mDNSu32 hostTTL; 13246 AuthRecType artype; 13247 mDNSu8 recordType = (flags & coreFlagKnownUnique) ? kDNSRecordTypeKnownUnique : kDNSRecordTypeUnique; 13248 13249 sr->ServiceCallback = Callback; 13250 sr->ServiceContext = Context; 13251 sr->Conflict = mDNSfalse; 13252 13253 sr->Extras = mDNSNULL; 13254 sr->NumSubTypes = NumSubTypes; 13255 sr->SubTypes = SubTypes; 13256 sr->flags = flags; 13257 13258 artype = setAuthRecType(InterfaceID, flags); 13259 13260 // Initialize the AuthRecord objects to sane values 13261 // Need to initialize everything correctly *before* making the decision whether to do a RegisterNoSuchService and bail out 13262 mDNS_SetupResourceRecord(&sr->RR_ADV, mDNSNULL, InterfaceID, kDNSType_PTR, kStandardTTL, kDNSRecordTypeAdvisory, artype, ServiceCallback, sr); 13263 mDNS_SetupResourceRecord(&sr->RR_PTR, mDNSNULL, InterfaceID, kDNSType_PTR, kStandardTTL, kDNSRecordTypeShared, artype, ServiceCallback, sr); 13264 13265 if (flags & coreFlagWakeOnly) 13266 { 13267 sr->RR_PTR.AuthFlags = AuthFlagsWakeOnly; 13268 } 13269 13270 if (SameDomainName(type, (const domainname *) "\x4" "_ubd" "\x4" "_tcp")) 13271 hostTTL = kHostNameSmallTTL; 13272 else 13273 hostTTL = kHostNameTTL; 13274 13275 mDNS_SetupResourceRecord(&sr->RR_SRV, mDNSNULL, InterfaceID, kDNSType_SRV, hostTTL, recordType, artype, ServiceCallback, sr); 13276 mDNS_SetupResourceRecord(&sr->RR_TXT, mDNSNULL, InterfaceID, kDNSType_TXT, kStandardTTL, kDNSRecordTypeUnique, artype, ServiceCallback, sr); 13277 13278 // If port number is zero, that means the client is really trying to do a RegisterNoSuchService 13279 if (mDNSIPPortIsZero(port)) 13280 return(mDNS_RegisterNoSuchService(m, &sr->RR_SRV, name, type, domain, mDNSNULL, InterfaceID, NSSCallback, sr, flags)); 13281 13282 // If the client is registering an oversized TXT record, 13283 // it is the client's responsibility to alloate a ServiceRecordSet structure that is large enough for it 13284 if (sr->RR_TXT.resrec.rdata->MaxRDLength < txtlen) 13285 sr->RR_TXT.resrec.rdata->MaxRDLength = txtlen; 13286 13287 // Set up the record names 13288 // For now we only create an advisory record for the main type, not for subtypes 13289 // We need to gain some operational experience before we decide if there's a need to create them for subtypes too 13290 if (ConstructServiceName(&sr->RR_ADV.namestorage, (const domainlabel*)"\x09_services", (const domainname*)"\x07_dns-sd\x04_udp", domain) == mDNSNULL) 13291 return(mStatus_BadParamErr); 13292 if (ConstructServiceName(&sr->RR_PTR.namestorage, mDNSNULL, type, domain) == mDNSNULL) return(mStatus_BadParamErr); 13293 if (ConstructServiceName(&sr->RR_SRV.namestorage, name, type, domain) == mDNSNULL) return(mStatus_BadParamErr); 13294 AssignDomainName(&sr->RR_TXT.namestorage, sr->RR_SRV.resrec.name); 13295 13296 // 1. Set up the ADV record rdata to advertise our service type 13297 AssignDomainName(&sr->RR_ADV.resrec.rdata->u.name, sr->RR_PTR.resrec.name); 13298 13299 // 2. Set up the PTR record rdata to point to our service name 13300 // We set up two additionals, so when a client asks for this PTR we automatically send the SRV and the TXT too 13301 // Note: uDNS registration code assumes that Additional1 points to the SRV record 13302 AssignDomainName(&sr->RR_PTR.resrec.rdata->u.name, sr->RR_SRV.resrec.name); 13303 sr->RR_PTR.Additional1 = &sr->RR_SRV; 13304 sr->RR_PTR.Additional2 = &sr->RR_TXT; 13305 13306 // 2a. Set up any subtype PTRs to point to our service name 13307 // If the client is using subtypes, it is the client's responsibility to have 13308 // already set the first label of the record name to the subtype being registered 13309 for (i=0; i<NumSubTypes; i++) 13310 { 13311 domainname st; 13312 AssignDomainName(&st, sr->SubTypes[i].resrec.name); 13313 st.c[1+st.c[0]] = 0; // Only want the first label, not the whole FQDN (particularly for mDNS_RenameAndReregisterService()) 13314 AppendDomainName(&st, type); 13315 mDNS_SetupResourceRecord(&sr->SubTypes[i], mDNSNULL, InterfaceID, kDNSType_PTR, kStandardTTL, kDNSRecordTypeShared, artype, ServiceCallback, sr); 13316 if (ConstructServiceName(&sr->SubTypes[i].namestorage, mDNSNULL, &st, domain) == mDNSNULL) return(mStatus_BadParamErr); 13317 AssignDomainName(&sr->SubTypes[i].resrec.rdata->u.name, &sr->RR_SRV.namestorage); 13318 sr->SubTypes[i].Additional1 = &sr->RR_SRV; 13319 sr->SubTypes[i].Additional2 = &sr->RR_TXT; 13320 } 13321 13322 SetAnonInfoSRS(sr, NumSubTypes); 13323 13324 // 3. Set up the SRV record rdata. 13325 sr->RR_SRV.resrec.rdata->u.srv.priority = 0; 13326 sr->RR_SRV.resrec.rdata->u.srv.weight = 0; 13327 sr->RR_SRV.resrec.rdata->u.srv.port = port; 13328 13329 // Setting AutoTarget tells DNS that the target of this SRV is to be automatically kept in sync with our host name 13330 if (host && host->c[0]) AssignDomainName(&sr->RR_SRV.resrec.rdata->u.srv.target, host); 13331 else { sr->RR_SRV.AutoTarget = Target_AutoHost; sr->RR_SRV.resrec.rdata->u.srv.target.c[0] = '\0'; } 13332 13333 // 4. Set up the TXT record rdata, 13334 // and set DependentOn because we're depending on the SRV record to find and resolve conflicts for us 13335 // Note: uDNS registration code assumes that DependentOn points to the SRV record 13336 if (txtinfo == mDNSNULL) sr->RR_TXT.resrec.rdlength = 0; 13337 else if (txtinfo != sr->RR_TXT.resrec.rdata->u.txt.c) 13338 { 13339 sr->RR_TXT.resrec.rdlength = txtlen; 13340 if (sr->RR_TXT.resrec.rdlength > sr->RR_TXT.resrec.rdata->MaxRDLength) return(mStatus_BadParamErr); 13341 mDNSPlatformMemCopy(sr->RR_TXT.resrec.rdata->u.txt.c, txtinfo, txtlen); 13342 } 13343 sr->RR_TXT.DependentOn = &sr->RR_SRV; 13344 13345 mDNS_Lock(m); 13346 // It is important that we register SRV first. uDNS assumes that SRV is registered first so 13347 // that if the SRV cannot find a target, rest of the records that belong to this service 13348 // will not be activated. 13349 err = mDNS_Register_internal(m, &sr->RR_SRV); 13350 // If we can't register the SRV record due to errors, bail out. It has not been inserted in 13351 // any list and hence no need to deregister. We could probably do similar checks for other 13352 // records below and bail out. For now, this seems to be sufficient to address rdar://9304275 13353 if (err) 13354 { 13355 mDNS_Unlock(m); 13356 return err; 13357 } 13358 if (!err) err = mDNS_Register_internal(m, &sr->RR_TXT); 13359 // We register the RR_PTR last, because we want to be sure that in the event of a forced call to 13360 // mDNS_StartExit, the RR_PTR will be the last one to be forcibly deregistered, since that is what triggers 13361 // the mStatus_MemFree callback to ServiceCallback, which in turn passes on the mStatus_MemFree back to 13362 // the client callback, which is then at liberty to free the ServiceRecordSet memory at will. We need to 13363 // make sure we've deregistered all our records and done any other necessary cleanup before that happens. 13364 if (!err) err = mDNS_Register_internal(m, &sr->RR_ADV); 13365 for (i=0; i<NumSubTypes; i++) if (!err) err = mDNS_Register_internal(m, &sr->SubTypes[i]); 13366 if (!err) err = mDNS_Register_internal(m, &sr->RR_PTR); 13367 13368 mDNS_Unlock(m); 13369 13370 if (err) mDNS_DeregisterService(m, sr); 13371 return(err); 13372 } 13373 13374 mDNSexport mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, 13375 ExtraResourceRecord *extra, RData *rdata, mDNSu32 ttl, mDNSu32 flags) 13376 { 13377 ExtraResourceRecord **e; 13378 mStatus status; 13379 AuthRecType artype; 13380 mDNSInterfaceID InterfaceID = sr->RR_PTR.resrec.InterfaceID; 13381 13382 artype = setAuthRecType(InterfaceID, flags); 13383 13384 extra->next = mDNSNULL; 13385 mDNS_SetupResourceRecord(&extra->r, rdata, sr->RR_PTR.resrec.InterfaceID, 13386 extra->r.resrec.rrtype, ttl, kDNSRecordTypeUnique, artype, ServiceCallback, sr); 13387 AssignDomainName(&extra->r.namestorage, sr->RR_SRV.resrec.name); 13388 13389 mDNS_Lock(m); 13390 e = &sr->Extras; 13391 while (*e) e = &(*e)->next; 13392 13393 if (ttl == 0) ttl = kStandardTTL; 13394 13395 extra->r.DependentOn = &sr->RR_SRV; 13396 13397 debugf("mDNS_AddRecordToService adding record to %##s %s %d", 13398 extra->r.resrec.name->c, DNSTypeName(extra->r.resrec.rrtype), extra->r.resrec.rdlength); 13399 13400 status = mDNS_Register_internal(m, &extra->r); 13401 if (status == mStatus_NoError) *e = extra; 13402 13403 mDNS_Unlock(m); 13404 return(status); 13405 } 13406 13407 mDNSexport mStatus mDNS_RemoveRecordFromService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra, 13408 mDNSRecordCallback MemFreeCallback, void *Context) 13409 { 13410 ExtraResourceRecord **e; 13411 mStatus status; 13412 13413 mDNS_Lock(m); 13414 e = &sr->Extras; 13415 while (*e && *e != extra) e = &(*e)->next; 13416 if (!*e) 13417 { 13418 debugf("mDNS_RemoveRecordFromService failed to remove record from %##s", extra->r.resrec.name->c); 13419 status = mStatus_BadReferenceErr; 13420 } 13421 else 13422 { 13423 debugf("mDNS_RemoveRecordFromService removing record from %##s", extra->r.resrec.name->c); 13424 extra->r.RecordCallback = MemFreeCallback; 13425 extra->r.RecordContext = Context; 13426 *e = (*e)->next; 13427 status = mDNS_Deregister_internal(m, &extra->r, mDNS_Dereg_normal); 13428 } 13429 mDNS_Unlock(m); 13430 return(status); 13431 } 13432 13433 mDNSexport mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordSet *const sr, const domainlabel *newname) 13434 { 13435 // Note: Don't need to use mDNS_Lock(m) here, because this code is just using public routines 13436 // mDNS_RegisterService() and mDNS_AddRecordToService(), which do the right locking internally. 13437 domainlabel name1, name2; 13438 domainname type, domain; 13439 const domainname *host = sr->RR_SRV.AutoTarget ? mDNSNULL : &sr->RR_SRV.resrec.rdata->u.srv.target; 13440 ExtraResourceRecord *extras = sr->Extras; 13441 mStatus err; 13442 13443 DeconstructServiceName(sr->RR_SRV.resrec.name, &name1, &type, &domain); 13444 if (!newname) 13445 { 13446 name2 = name1; 13447 IncrementLabelSuffix(&name2, mDNStrue); 13448 newname = &name2; 13449 } 13450 13451 if (SameDomainName(&domain, &localdomain)) 13452 debugf("%##s service renamed from \"%#s\" to \"%#s\"", type.c, name1.c, newname->c); 13453 else debugf("%##s service (domain %##s) renamed from \"%#s\" to \"%#s\"",type.c, domain.c, name1.c, newname->c); 13454 13455 err = mDNS_RegisterService(m, sr, newname, &type, &domain, 13456 host, sr->RR_SRV.resrec.rdata->u.srv.port, sr->RR_TXT.resrec.rdata->u.txt.c, sr->RR_TXT.resrec.rdlength, 13457 sr->SubTypes, sr->NumSubTypes, 13458 sr->RR_PTR.resrec.InterfaceID, sr->ServiceCallback, sr->ServiceContext, sr->flags); 13459 13460 // mDNS_RegisterService() just reset sr->Extras to NULL. 13461 // Fortunately we already grabbed ourselves a copy of this pointer (above), so we can now run 13462 // through the old list of extra records, and re-add them to our freshly created service registration 13463 while (!err && extras) 13464 { 13465 ExtraResourceRecord *e = extras; 13466 extras = extras->next; 13467 err = mDNS_AddRecordToService(m, sr, e, e->r.resrec.rdata, e->r.resrec.rroriginalttl, 0); 13468 } 13469 13470 return(err); 13471 } 13472 13473 // Note: mDNS_DeregisterService calls mDNS_Deregister_internal which can call a user callback, 13474 // which may change the record list and/or question list. 13475 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this. 13476 mDNSexport mStatus mDNS_DeregisterService_drt(mDNS *const m, ServiceRecordSet *sr, mDNS_Dereg_type drt) 13477 { 13478 // If port number is zero, that means this was actually registered using mDNS_RegisterNoSuchService() 13479 if (mDNSIPPortIsZero(sr->RR_SRV.resrec.rdata->u.srv.port)) return(mDNS_DeregisterNoSuchService(m, &sr->RR_SRV)); 13480 13481 if (sr->RR_PTR.resrec.RecordType == kDNSRecordTypeUnregistered) 13482 { 13483 debugf("Service set for %##s already deregistered", sr->RR_SRV.resrec.name->c); 13484 return(mStatus_BadReferenceErr); 13485 } 13486 else if (sr->RR_PTR.resrec.RecordType == kDNSRecordTypeDeregistering) 13487 { 13488 LogInfo("Service set for %##s already in the process of deregistering", sr->RR_SRV.resrec.name->c); 13489 // Avoid race condition: 13490 // If a service gets a conflict, then we set the Conflict flag to tell us to generate 13491 // an mStatus_NameConflict message when we get the mStatus_MemFree for our PTR record. 13492 // If the client happens to deregister the service in the middle of that process, then 13493 // we clear the flag back to the normal state, so that we deliver a plain mStatus_MemFree 13494 // instead of incorrectly promoting it to mStatus_NameConflict. 13495 // This race condition is exposed particularly when the conformance test generates 13496 // a whole batch of simultaneous conflicts across a range of services all advertised 13497 // using the same system default name, and if we don't take this precaution then 13498 // we end up incrementing m->nicelabel multiple times instead of just once. 13499 // <rdar://problem/4060169> Bug when auto-renaming Computer Name after name collision 13500 sr->Conflict = mDNSfalse; 13501 return(mStatus_NoError); 13502 } 13503 else 13504 { 13505 mDNSu32 i; 13506 mStatus status; 13507 ExtraResourceRecord *e; 13508 mDNS_Lock(m); 13509 e = sr->Extras; 13510 13511 // We use mDNS_Dereg_repeat because, in the event of a collision, some or all of the 13512 // SRV, TXT, or Extra records could have already been automatically deregistered, and that's okay 13513 mDNS_Deregister_internal(m, &sr->RR_SRV, mDNS_Dereg_repeat); 13514 mDNS_Deregister_internal(m, &sr->RR_TXT, mDNS_Dereg_repeat); 13515 13516 mDNS_Deregister_internal(m, &sr->RR_ADV, drt); 13517 13518 // We deregister all of the extra records, but we leave the sr->Extras list intact 13519 // in case the client wants to do a RenameAndReregister and reinstate the registration 13520 while (e) 13521 { 13522 mDNS_Deregister_internal(m, &e->r, mDNS_Dereg_repeat); 13523 e = e->next; 13524 } 13525 13526 for (i=0; i<sr->NumSubTypes; i++) 13527 mDNS_Deregister_internal(m, &sr->SubTypes[i], drt); 13528 13529 status = mDNS_Deregister_internal(m, &sr->RR_PTR, drt); 13530 mDNS_Unlock(m); 13531 return(status); 13532 } 13533 } 13534 13535 // Create a registration that asserts that no such service exists with this name. 13536 // This can be useful where there is a given function is available through several protocols. 13537 // For example, a printer called "Stuart's Printer" may implement printing via the "pdl-datastream" and "IPP" 13538 // protocols, but not via "LPR". In this case it would be prudent for the printer to assert the non-existence of an 13539 // "LPR" service called "Stuart's Printer". Without this precaution, another printer than offers only "LPR" printing 13540 // could inadvertently advertise its service under the same name "Stuart's Printer", which might be confusing for users. 13541 mDNSexport mStatus mDNS_RegisterNoSuchService(mDNS *const m, AuthRecord *const rr, 13542 const domainlabel *const name, const domainname *const type, const domainname *const domain, 13543 const domainname *const host, 13544 const mDNSInterfaceID InterfaceID, mDNSRecordCallback Callback, void *Context, mDNSu32 flags) 13545 { 13546 AuthRecType artype; 13547 13548 artype = setAuthRecType(InterfaceID, flags); 13549 13550 mDNS_SetupResourceRecord(rr, mDNSNULL, InterfaceID, kDNSType_SRV, kHostNameTTL, kDNSRecordTypeUnique, artype, Callback, Context); 13551 if (ConstructServiceName(&rr->namestorage, name, type, domain) == mDNSNULL) return(mStatus_BadParamErr); 13552 rr->resrec.rdata->u.srv.priority = 0; 13553 rr->resrec.rdata->u.srv.weight = 0; 13554 rr->resrec.rdata->u.srv.port = zeroIPPort; 13555 if (host && host->c[0]) AssignDomainName(&rr->resrec.rdata->u.srv.target, host); 13556 else rr->AutoTarget = Target_AutoHost; 13557 return(mDNS_Register(m, rr)); 13558 } 13559 13560 mDNSexport mStatus mDNS_AdvertiseDomains(mDNS *const m, AuthRecord *rr, 13561 mDNS_DomainType DomainType, const mDNSInterfaceID InterfaceID, char *domname) 13562 { 13563 AuthRecType artype; 13564 13565 if (InterfaceID == mDNSInterface_LocalOnly) 13566 artype = AuthRecordLocalOnly; 13567 else if (InterfaceID == mDNSInterface_P2P) 13568 artype = AuthRecordP2P; 13569 else 13570 artype = AuthRecordAny; 13571 mDNS_SetupResourceRecord(rr, mDNSNULL, InterfaceID, kDNSType_PTR, kStandardTTL, kDNSRecordTypeShared, artype, mDNSNULL, mDNSNULL); 13572 if (!MakeDomainNameFromDNSNameString(&rr->namestorage, mDNS_DomainTypeNames[DomainType])) return(mStatus_BadParamErr); 13573 if (!MakeDomainNameFromDNSNameString(&rr->resrec.rdata->u.name, domname)) return(mStatus_BadParamErr); 13574 return(mDNS_Register(m, rr)); 13575 } 13576 13577 mDNSlocal mDNSBool mDNS_IdUsedInResourceRecordsList(mDNS * const m, mDNSOpaque16 id) 13578 { 13579 AuthRecord *r; 13580 for (r = m->ResourceRecords; r; r=r->next) if (mDNSSameOpaque16(id, r->updateid)) return mDNStrue; 13581 return mDNSfalse; 13582 } 13583 13584 mDNSlocal mDNSBool mDNS_IdUsedInQuestionsList(mDNS * const m, mDNSOpaque16 id) 13585 { 13586 DNSQuestion *q; 13587 for (q = m->Questions; q; q=q->next) if (mDNSSameOpaque16(id, q->TargetQID)) return mDNStrue; 13588 return mDNSfalse; 13589 } 13590 13591 mDNSexport mDNSOpaque16 mDNS_NewMessageID(mDNS * const m) 13592 { 13593 mDNSOpaque16 id; 13594 int i; 13595 13596 for (i=0; i<10; i++) 13597 { 13598 id = mDNSOpaque16fromIntVal(1 + (mDNSu16)mDNSRandom(0xFFFE)); 13599 if (!mDNS_IdUsedInResourceRecordsList(m, id) && !mDNS_IdUsedInQuestionsList(m, id)) break; 13600 } 13601 13602 debugf("mDNS_NewMessageID: %5d", mDNSVal16(id)); 13603 13604 return id; 13605 } 13606 13607 // *************************************************************************** 13608 #if COMPILER_LIKES_PRAGMA_MARK 13609 #pragma mark - 13610 #pragma mark - Sleep Proxy Server 13611 #endif 13612 13613 mDNSlocal void RestartARPProbing(mDNS *const m, AuthRecord *const rr) 13614 { 13615 // If we see an ARP from a machine we think is sleeping, then either 13616 // (i) the machine has woken, or 13617 // (ii) it's just a stray old packet from before the machine slept 13618 // To handle the second case, we reset ProbeCount, so we'll suppress our own answers for a while, to avoid 13619 // generating ARP conflicts with a waking machine, and set rr->LastAPTime so we'll start probing again in 10 seconds. 13620 // If the machine has just woken then we'll discard our records when we see the first new mDNS probe from that machine. 13621 // If it was a stray old packet, then after 10 seconds we'll probe again and then start answering ARPs again. In this case we *do* 13622 // need to send new ARP Announcements, because the owner's ARP broadcasts will have updated neighboring ARP caches, so we need to 13623 // re-assert our (temporary) ownership of that IP address in order to receive subsequent packets addressed to that IPv4 address. 13624 13625 rr->resrec.RecordType = kDNSRecordTypeUnique; 13626 rr->ProbeCount = DefaultProbeCountForTypeUnique; 13627 rr->ProbeRestartCount++; 13628 13629 // If we haven't started announcing yet (and we're not already in ten-second-delay mode) the machine is probably 13630 // still going to sleep, so we just reset rr->ProbeCount so we'll continue probing until it stops responding. 13631 // If we *have* started announcing, the machine is probably in the process of waking back up, so in that case 13632 // we're more cautious and we wait ten seconds before probing it again. We do this because while waking from 13633 // sleep, some network interfaces tend to lose or delay inbound packets, and without this delay, if the waking machine 13634 // didn't answer our three probes within three seconds then we'd announce and cause it an unnecessary address conflict. 13635 if (rr->AnnounceCount == InitialAnnounceCount && m->timenow - rr->LastAPTime >= 0) 13636 InitializeLastAPTime(m, rr); 13637 else 13638 { 13639 rr->AnnounceCount = InitialAnnounceCount; 13640 rr->ThisAPInterval = mDNSPlatformOneSecond; 13641 rr->LastAPTime = m->timenow + mDNSPlatformOneSecond * 9; // Send first packet at rr->LastAPTime + rr->ThisAPInterval, i.e. 10 seconds from now 13642 SetNextAnnounceProbeTime(m, rr); 13643 } 13644 } 13645 13646 mDNSlocal void mDNSCoreReceiveRawARP(mDNS *const m, const ARP_EthIP *const arp, const mDNSInterfaceID InterfaceID) 13647 { 13648 static const mDNSOpaque16 ARP_op_request = { { 0, 1 } }; 13649 AuthRecord *rr; 13650 NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID); 13651 if (!intf) return; 13652 13653 mDNS_Lock(m); 13654 13655 // Pass 1: 13656 // Process ARP Requests and Probes (but not Announcements), and generate an ARP Reply if necessary. 13657 // We also process ARPs from our own kernel (and 'answer' them by injecting a local ARP table entry) 13658 // We ignore ARP Announcements here -- Announcements are not questions, they're assertions, so we don't need to answer them. 13659 // The times we might need to react to an ARP Announcement are: 13660 // (i) as an indication that the host in question has not gone to sleep yet (so we should delay beginning to proxy for it) or 13661 // (ii) if it's a conflicting Announcement from another host 13662 // -- and we check for these in Pass 2 below. 13663 if (mDNSSameOpaque16(arp->op, ARP_op_request) && !mDNSSameIPv4Address(arp->spa, arp->tpa)) 13664 { 13665 for (rr = m->ResourceRecords; rr; rr=rr->next) 13666 if (rr->resrec.InterfaceID == InterfaceID && rr->resrec.RecordType != kDNSRecordTypeDeregistering && 13667 rr->AddressProxy.type == mDNSAddrType_IPv4 && mDNSSameIPv4Address(rr->AddressProxy.ip.v4, arp->tpa)) 13668 { 13669 static const char msg1[] = "ARP Req from owner -- re-probing"; 13670 static const char msg2[] = "Ignoring ARP Request from "; 13671 static const char msg3[] = "Creating Local ARP Cache entry "; 13672 static const char msg4[] = "Answering ARP Request from "; 13673 const char *const msg = mDNSSameEthAddress(&arp->sha, &rr->WakeUp.IMAC) ? msg1 : 13674 (rr->AnnounceCount == InitialAnnounceCount) ? msg2 : 13675 mDNSSameEthAddress(&arp->sha, &intf->MAC) ? msg3 : msg4; 13676 LogSPS("%-7s %s %.6a %.4a for %.4a -- H-MAC %.6a I-MAC %.6a %s", 13677 intf->ifname, msg, &arp->sha, &arp->spa, &arp->tpa, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr)); 13678 if (msg == msg1) 13679 { 13680 if ( rr->ProbeRestartCount < MAX_PROBE_RESTARTS) 13681 RestartARPProbing(m, rr); 13682 else 13683 LogSPS("Reached maximum number of restarts for probing - %s", ARDisplayString(m,rr)); 13684 } 13685 else if (msg == msg3) 13686 { 13687 mDNSPlatformSetLocalAddressCacheEntry(m, &rr->AddressProxy, &rr->WakeUp.IMAC, InterfaceID); 13688 } 13689 else if (msg == msg4) 13690 { 13691 SendARP(m, 2, rr, &arp->tpa, &arp->sha, &arp->spa, &arp->sha); 13692 } 13693 } 13694 } 13695 13696 // Pass 2: 13697 // For all types of ARP packet we check the Sender IP address to make sure it doesn't conflict with any AddressProxy record we're holding. 13698 // (Strictly speaking we're only checking Announcement/Request/Reply packets, since ARP Probes have zero Sender IP address, 13699 // so by definition (and by design) they can never conflict with any real (i.e. non-zero) IP address). 13700 // We ignore ARPs we sent ourselves (Sender MAC address is our MAC address) because our own proxy ARPs do not constitute a conflict that we need to handle. 13701 // If we see an apparently conflicting ARP, we check the sender hardware address: 13702 // If the sender hardware address is the original owner this is benign, so we just suppress our own proxy answering for a while longer. 13703 // If the sender hardware address is *not* the original owner, then this is a conflict, and we need to wake the sleeping machine to handle it. 13704 if (mDNSSameEthAddress(&arp->sha, &intf->MAC)) 13705 debugf("ARP from self for %.4a", &arp->tpa); 13706 else 13707 { 13708 if (!mDNSSameIPv4Address(arp->spa, zerov4Addr)) 13709 for (rr = m->ResourceRecords; rr; rr=rr->next) 13710 if (rr->resrec.InterfaceID == InterfaceID && rr->resrec.RecordType != kDNSRecordTypeDeregistering && 13711 rr->AddressProxy.type == mDNSAddrType_IPv4 && mDNSSameIPv4Address(rr->AddressProxy.ip.v4, arp->spa) && (rr->ProbeRestartCount < MAX_PROBE_RESTARTS)) 13712 { 13713 if (mDNSSameEthAddress(&zeroEthAddr, &rr->WakeUp.HMAC)) 13714 { 13715 LogSPS("%-7s ARP from %.6a %.4a for %.4a -- Invalid H-MAC %.6a I-MAC %.6a %s", intf->ifname, 13716 &arp->sha, &arp->spa, &arp->tpa, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr)); 13717 } 13718 else 13719 { 13720 RestartARPProbing(m, rr); 13721 if (mDNSSameEthAddress(&arp->sha, &rr->WakeUp.IMAC)) 13722 { 13723 LogSPS("%-7s ARP %s from owner %.6a %.4a for %-15.4a -- re-starting probing for %s", intf->ifname, 13724 mDNSSameIPv4Address(arp->spa, arp->tpa) ? "Announcement " : mDNSSameOpaque16(arp->op, ARP_op_request) ? "Request " : "Response ", 13725 &arp->sha, &arp->spa, &arp->tpa, ARDisplayString(m, rr)); 13726 } 13727 else 13728 { 13729 LogMsg("%-7s Conflicting ARP from %.6a %.4a for %.4a -- waking H-MAC %.6a I-MAC %.6a %s", intf->ifname, 13730 &arp->sha, &arp->spa, &arp->tpa, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr)); 13731 ScheduleWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.HMAC); 13732 } 13733 } 13734 } 13735 } 13736 13737 mDNS_Unlock(m); 13738 } 13739 13740 /* 13741 // Option 1 is Source Link Layer Address Option 13742 // Option 2 is Target Link Layer Address Option 13743 mDNSlocal const mDNSEthAddr *GetLinkLayerAddressOption(const IPv6NDP *const ndp, const mDNSu8 *const end, mDNSu8 op) 13744 { 13745 const mDNSu8 *options = (mDNSu8 *)(ndp+1); 13746 while (options < end) 13747 { 13748 debugf("NDP Option %02X len %2d %d", options[0], options[1], end - options); 13749 if (options[0] == op && options[1] == 1) return (const mDNSEthAddr*)(options+2); 13750 options += options[1] * 8; 13751 } 13752 return mDNSNULL; 13753 } 13754 */ 13755 13756 mDNSlocal void mDNSCoreReceiveRawND(mDNS *const m, const mDNSEthAddr *const sha, const mDNSv6Addr *spa, 13757 const IPv6NDP *const ndp, const mDNSu8 *const end, const mDNSInterfaceID InterfaceID) 13758 { 13759 AuthRecord *rr; 13760 NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID); 13761 if (!intf) return; 13762 13763 mDNS_Lock(m); 13764 13765 // Pass 1: Process Neighbor Solicitations, and generate a Neighbor Advertisement if necessary. 13766 if (ndp->type == NDP_Sol) 13767 { 13768 //const mDNSEthAddr *const sha = GetLinkLayerAddressOption(ndp, end, NDP_SrcLL); 13769 (void)end; 13770 for (rr = m->ResourceRecords; rr; rr=rr->next) 13771 if (rr->resrec.InterfaceID == InterfaceID && rr->resrec.RecordType != kDNSRecordTypeDeregistering && 13772 rr->AddressProxy.type == mDNSAddrType_IPv6 && mDNSSameIPv6Address(rr->AddressProxy.ip.v6, ndp->target)) 13773 { 13774 static const char msg1[] = "NDP Req from owner -- re-probing"; 13775 static const char msg2[] = "Ignoring NDP Request from "; 13776 static const char msg3[] = "Creating Local NDP Cache entry "; 13777 static const char msg4[] = "Answering NDP Request from "; 13778 static const char msg5[] = "Answering NDP Probe from "; 13779 const char *const msg = sha && mDNSSameEthAddress(sha, &rr->WakeUp.IMAC) ? msg1 : 13780 (rr->AnnounceCount == InitialAnnounceCount) ? msg2 : 13781 sha && mDNSSameEthAddress(sha, &intf->MAC) ? msg3 : 13782 spa && mDNSIPv6AddressIsZero(*spa) ? msg4 : msg5; 13783 LogSPS("%-7s %s %.6a %.16a for %.16a -- H-MAC %.6a I-MAC %.6a %s", 13784 intf->ifname, msg, sha, spa, &ndp->target, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr)); 13785 if (msg == msg1) 13786 { 13787 if (rr->ProbeRestartCount < MAX_PROBE_RESTARTS) 13788 RestartARPProbing(m, rr); 13789 else 13790 LogSPS("Reached maximum number of restarts for probing - %s", ARDisplayString(m,rr)); 13791 } 13792 else if (msg == msg3) 13793 mDNSPlatformSetLocalAddressCacheEntry(m, &rr->AddressProxy, &rr->WakeUp.IMAC, InterfaceID); 13794 else if (msg == msg4) 13795 SendNDP(m, NDP_Adv, NDP_Solicited, rr, &ndp->target, mDNSNULL, spa, sha); 13796 else if (msg == msg5) 13797 SendNDP(m, NDP_Adv, 0, rr, &ndp->target, mDNSNULL, &AllHosts_v6, &AllHosts_v6_Eth); 13798 } 13799 } 13800 13801 // Pass 2: For all types of NDP packet we check the Sender IP address to make sure it doesn't conflict with any AddressProxy record we're holding. 13802 if (mDNSSameEthAddress(sha, &intf->MAC)) 13803 debugf("NDP from self for %.16a", &ndp->target); 13804 else 13805 { 13806 // For Neighbor Advertisements we check the Target address field, not the actual IPv6 source address. 13807 // When a machine has both link-local and routable IPv6 addresses, it may send NDP packets making assertions 13808 // about its routable IPv6 address, using its link-local address as the source address for all NDP packets. 13809 // Hence it is the NDP target address we care about, not the actual packet source address. 13810 if (ndp->type == NDP_Adv) spa = &ndp->target; 13811 if (!mDNSSameIPv6Address(*spa, zerov6Addr)) 13812 for (rr = m->ResourceRecords; rr; rr=rr->next) 13813 if (rr->resrec.InterfaceID == InterfaceID && rr->resrec.RecordType != kDNSRecordTypeDeregistering && 13814 rr->AddressProxy.type == mDNSAddrType_IPv6 && mDNSSameIPv6Address(rr->AddressProxy.ip.v6, *spa) && (rr->ProbeRestartCount < MAX_PROBE_RESTARTS)) 13815 { 13816 if (mDNSSameEthAddress(&zeroEthAddr, &rr->WakeUp.HMAC)) 13817 { 13818 LogSPS("%-7s NDP from %.6a %.16a for %.16a -- Invalid H-MAC %.6a I-MAC %.6a %s", intf->ifname, 13819 sha, spa, &ndp->target, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr)); 13820 } 13821 else 13822 { 13823 RestartARPProbing(m, rr); 13824 if (mDNSSameEthAddress(sha, &rr->WakeUp.IMAC)) 13825 { 13826 LogSPS("%-7s NDP %s from owner %.6a %.16a for %.16a -- re-starting probing for %s", intf->ifname, 13827 ndp->type == NDP_Sol ? "Solicitation " : "Advertisement", sha, spa, &ndp->target, ARDisplayString(m, rr)); 13828 } 13829 else 13830 { 13831 LogMsg("%-7s Conflicting NDP from %.6a %.16a for %.16a -- waking H-MAC %.6a I-MAC %.6a %s", intf->ifname, 13832 sha, spa, &ndp->target, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, rr)); 13833 ScheduleWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.HMAC); 13834 } 13835 } 13836 } 13837 } 13838 13839 mDNS_Unlock(m); 13840 } 13841 13842 mDNSlocal void mDNSCoreReceiveRawTransportPacket(mDNS *const m, const mDNSEthAddr *const sha, const mDNSAddr *const src, const mDNSAddr *const dst, const mDNSu8 protocol, 13843 const mDNSu8 *const p, const TransportLayerPacket *const t, const mDNSu8 *const end, const mDNSInterfaceID InterfaceID, const mDNSu16 len) 13844 { 13845 const mDNSIPPort port = (protocol == 0x06) ? t->tcp.dst : (protocol == 0x11) ? t->udp.dst : zeroIPPort; 13846 mDNSBool wake = mDNSfalse; 13847 mDNSBool kaWake = mDNSfalse; 13848 13849 switch (protocol) 13850 { 13851 #define XX wake ? "Received" : "Ignoring", end-p 13852 case 0x01: LogSPS("Ignoring %d-byte ICMP from %#a to %#a", end-p, src, dst); 13853 break; 13854 13855 case 0x06: { 13856 AuthRecord *kr; 13857 mDNSu32 seq, ack; 13858 #define TH_FIN 0x01 13859 #define TH_SYN 0x02 13860 #define TH_RST 0x04 13861 #define TH_ACK 0x10 13862 13863 kr = mDNS_MatchKeepaliveInfo(m, dst, src, port, t->tcp.src, &seq, &ack); 13864 if (kr) 13865 { 13866 LogSPS("mDNSCoreReceiveRawTransportPacket: Found a Keepalive record from %#a:%d to %#a:%d", src, mDNSVal16(t->tcp.src), dst, mDNSVal16(port)); 13867 // Plan to wake if 13868 // (a) RST or FIN is set (the keepalive that we sent could have caused a reset) 13869 // (b) packet that contains new data and acks a sequence number higher than the one 13870 // we have been sending in the keepalive 13871 13872 wake = ((t->tcp.flags & TH_RST) || (t->tcp.flags & TH_FIN)) ; 13873 if (!wake) 13874 { 13875 mDNSu8 *ptr; 13876 mDNSu32 pseq, pack; 13877 mDNSBool data = mDNSfalse; 13878 mDNSu8 tcphlen; 13879 13880 // Convert to host order 13881 ptr = (mDNSu8 *)&seq; 13882 seq = ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3]; 13883 13884 ptr = (mDNSu8 *)&ack; 13885 ack = ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3]; 13886 13887 pseq = t->tcp.seq; 13888 ptr = (mDNSu8 *)&pseq; 13889 pseq = ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3]; 13890 13891 pack = t->tcp.ack; 13892 ptr = (mDNSu8 *)&pack; 13893 pack = ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | ptr[3]; 13894 13895 // If the other side is acking one more than our sequence number (keepalive is one 13896 // less than the last valid sequence sent) and it's sequence is more than what we 13897 // acked before 13898 //if (end - p - 34 - ((t->tcp.offset >> 4) * 4) > 0) data = mDNStrue; 13899 tcphlen = ((t->tcp.offset >> 4) * 4); 13900 if (end - ((mDNSu8 *)t + tcphlen) > 0) data = mDNStrue; 13901 wake = ((int)(pack - seq) > 0) && ((int)(pseq - ack) >= 0) && data; 13902 13903 // If we got a regular keepalive on a connection that was registed with the KeepAlive API, respond with an ACK 13904 if ((t->tcp.flags & TH_ACK) && (data == mDNSfalse) && 13905 ((int)(ack - pseq) == 1)) 13906 { 13907 // Send an ACK; 13908 mDNS_SendKeepaliveACK(m, kr); 13909 } 13910 LogSPS("mDNSCoreReceiveRawTransportPacket: End %p, hlen %d, Datalen %d, pack %u, seq %u, pseq %u, ack %u, wake %d", 13911 end, tcphlen, end - ((mDNSu8 *)t + tcphlen), pack, seq, pseq, ack, wake); 13912 } 13913 else { LogSPS("mDNSCoreReceiveRawTransportPacket: waking because of RST or FIN th_flags %d", t->tcp.flags); } 13914 kaWake = wake; 13915 } 13916 else 13917 { 13918 // Plan to wake if 13919 // (a) RST is not set, AND 13920 // (b) packet is SYN, SYN+FIN, or plain data packet (no SYN or FIN). We won't wake for FIN alone. 13921 wake = (!(t->tcp.flags & TH_RST) && (t->tcp.flags & (TH_FIN|TH_SYN)) != TH_FIN); 13922 13923 // For now, to reduce spurious wakeups, we wake only for TCP SYN, 13924 // except for ssh connections, where we'll wake for plain data packets too 13925 if (!mDNSSameIPPort(port, SSHPort) && !(t->tcp.flags & 2)) wake = mDNSfalse; 13926 13927 LogSPS("%s %d-byte TCP from %#a:%d to %#a:%d%s%s%s", XX, 13928 src, mDNSVal16(t->tcp.src), dst, mDNSVal16(port), 13929 (t->tcp.flags & 2) ? " SYN" : "", 13930 (t->tcp.flags & 1) ? " FIN" : "", 13931 (t->tcp.flags & 4) ? " RST" : ""); 13932 } 13933 break; 13934 } 13935 13936 case 0x11: { 13937 #define ARD_AsNumber 3283 13938 static const mDNSIPPort ARD = { { ARD_AsNumber >> 8, ARD_AsNumber & 0xFF } }; 13939 const mDNSu16 udplen = (mDNSu16)((mDNSu16)t->bytes[4] << 8 | t->bytes[5]); // Length *including* 8-byte UDP header 13940 if (udplen >= sizeof(UDPHeader)) 13941 { 13942 const mDNSu16 datalen = udplen - sizeof(UDPHeader); 13943 wake = mDNStrue; 13944 13945 // For Back to My Mac UDP port 4500 (IPSEC) packets, we do some special handling 13946 if (mDNSSameIPPort(port, IPSECPort)) 13947 { 13948 // Specifically ignore NAT keepalive packets 13949 if (datalen == 1 && end >= &t->bytes[9] && t->bytes[8] == 0xFF) wake = mDNSfalse; 13950 else 13951 { 13952 // Skip over the Non-ESP Marker if present 13953 const mDNSBool NonESP = (end >= &t->bytes[12] && t->bytes[8] == 0 && t->bytes[9] == 0 && t->bytes[10] == 0 && t->bytes[11] == 0); 13954 const IKEHeader *const ike = (IKEHeader *)(t + (NonESP ? 12 : 8)); 13955 const mDNSu16 ikelen = datalen - (NonESP ? 4 : 0); 13956 if (ikelen >= sizeof(IKEHeader) && end >= ((mDNSu8 *)ike) + sizeof(IKEHeader)) 13957 if ((ike->Version & 0x10) == 0x10) 13958 { 13959 // ExchangeType == 5 means 'Informational' <http://www.ietf.org/rfc/rfc2408.txt> 13960 // ExchangeType == 34 means 'IKE_SA_INIT' <http://www.iana.org/assignments/ikev2-parameters> 13961 if (ike->ExchangeType == 5 || ike->ExchangeType == 34) wake = mDNSfalse; 13962 LogSPS("%s %d-byte IKE ExchangeType %d", XX, ike->ExchangeType); 13963 } 13964 } 13965 } 13966 13967 // For now, because we haven't yet worked out a clean elegant way to do this, we just special-case the 13968 // Apple Remote Desktop port number -- we ignore all packets to UDP 3283 (the "Net Assistant" port), 13969 // except for Apple Remote Desktop's explicit manual wakeup packet, which looks like this: 13970 // UDP header (8 bytes) 13971 // Payload: 13 88 00 6a 41 4e 41 20 (8 bytes) ffffffffffff (6 bytes) 16xMAC (96 bytes) = 110 bytes total 13972 if (mDNSSameIPPort(port, ARD)) wake = (datalen >= 110 && end >= &t->bytes[10] && t->bytes[8] == 0x13 && t->bytes[9] == 0x88); 13973 13974 LogSPS("%s %d-byte UDP from %#a:%d to %#a:%d", XX, src, mDNSVal16(t->udp.src), dst, mDNSVal16(port)); 13975 } 13976 } 13977 break; 13978 13979 case 0x3A: if (&t->bytes[len] <= end) 13980 { 13981 mDNSu16 checksum = IPv6CheckSum(&src->ip.v6, &dst->ip.v6, protocol, t->bytes, len); 13982 if (!checksum) mDNSCoreReceiveRawND(m, sha, &src->ip.v6, &t->ndp, &t->bytes[len], InterfaceID); 13983 else LogInfo("IPv6CheckSum bad %04X %02X%02X from %#a to %#a", checksum, t->bytes[2], t->bytes[3], src, dst); 13984 } 13985 break; 13986 13987 default: LogSPS("Ignoring %d-byte IP packet unknown protocol %d from %#a to %#a", end-p, protocol, src, dst); 13988 break; 13989 } 13990 13991 if (wake) 13992 { 13993 AuthRecord *rr, *r2; 13994 13995 mDNS_Lock(m); 13996 for (rr = m->ResourceRecords; rr; rr=rr->next) 13997 if (rr->resrec.InterfaceID == InterfaceID && 13998 rr->resrec.RecordType != kDNSRecordTypeDeregistering && 13999 rr->AddressProxy.type && mDNSSameAddress(&rr->AddressProxy, dst)) 14000 { 14001 const mDNSu8 *const tp = (protocol == 6) ? (const mDNSu8 *)"\x4_tcp" : (const mDNSu8 *)"\x4_udp"; 14002 for (r2 = m->ResourceRecords; r2; r2=r2->next) 14003 if (r2->resrec.InterfaceID == InterfaceID && mDNSSameEthAddress(&r2->WakeUp.HMAC, &rr->WakeUp.HMAC) && 14004 r2->resrec.RecordType != kDNSRecordTypeDeregistering && 14005 r2->resrec.rrtype == kDNSType_SRV && mDNSSameIPPort(r2->resrec.rdata->u.srv.port, port) && 14006 SameDomainLabel(ThirdLabel(r2->resrec.name)->c, tp)) 14007 break; 14008 if (!r2 && mDNSSameIPPort(port, IPSECPort)) r2 = rr; // So that we wake for BTMM IPSEC packets, even without a matching SRV record 14009 if (!r2 && kaWake) r2 = rr; // So that we wake for keepalive packets, even without a matching SRV record 14010 if (r2) 14011 { 14012 LogMsg("Waking host at %s %#a H-MAC %.6a I-MAC %.6a for %s", 14013 InterfaceNameForID(m, rr->resrec.InterfaceID), dst, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m, r2)); 14014 ScheduleWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.HMAC); 14015 } 14016 else 14017 LogSPS("Sleeping host at %s %#a %.6a has no service on %#s %d", 14018 InterfaceNameForID(m, rr->resrec.InterfaceID), dst, &rr->WakeUp.HMAC, tp, mDNSVal16(port)); 14019 } 14020 mDNS_Unlock(m); 14021 } 14022 } 14023 14024 mDNSexport void mDNSCoreReceiveRawPacket(mDNS *const m, const mDNSu8 *const p, const mDNSu8 *const end, const mDNSInterfaceID InterfaceID) 14025 { 14026 static const mDNSOpaque16 Ethertype_ARP = { { 0x08, 0x06 } }; // Ethertype 0x0806 = ARP 14027 static const mDNSOpaque16 Ethertype_IPv4 = { { 0x08, 0x00 } }; // Ethertype 0x0800 = IPv4 14028 static const mDNSOpaque16 Ethertype_IPv6 = { { 0x86, 0xDD } }; // Ethertype 0x86DD = IPv6 14029 static const mDNSOpaque16 ARP_hrd_eth = { { 0x00, 0x01 } }; // Hardware address space (Ethernet = 1) 14030 static const mDNSOpaque16 ARP_pro_ip = { { 0x08, 0x00 } }; // Protocol address space (IP = 0x0800) 14031 14032 // Note: BPF guarantees that the NETWORK LAYER header will be word aligned, not the link-layer header. 14033 // In other words, we can safely assume that pkt below (ARP, IPv4 or IPv6) is properly word aligned, 14034 // but if pkt is 4-byte aligned, that necessarily means that eth CANNOT also be 4-byte aligned 14035 // since it points to a an address 14 bytes before pkt. 14036 const EthernetHeader *const eth = (const EthernetHeader *)p; 14037 const NetworkLayerPacket *const pkt = (const NetworkLayerPacket *)(eth+1); 14038 mDNSAddr src, dst; 14039 #define RequiredCapLen(P) ((P)==0x01 ? 4 : (P)==0x06 ? 20 : (P)==0x11 ? 8 : (P)==0x3A ? 24 : 0) 14040 14041 // Is ARP? Length must be at least 14 + 28 = 42 bytes 14042 if (end >= p+42 && mDNSSameOpaque16(eth->ethertype, Ethertype_ARP) && mDNSSameOpaque16(pkt->arp.hrd, ARP_hrd_eth) && mDNSSameOpaque16(pkt->arp.pro, ARP_pro_ip)) 14043 mDNSCoreReceiveRawARP(m, &pkt->arp, InterfaceID); 14044 // Is IPv4 with zero fragmentation offset? Length must be at least 14 + 20 = 34 bytes 14045 else if (end >= p+34 && mDNSSameOpaque16(eth->ethertype, Ethertype_IPv4) && (pkt->v4.flagsfrags.b[0] & 0x1F) == 0 && pkt->v4.flagsfrags.b[1] == 0) 14046 { 14047 const mDNSu8 *const trans = p + 14 + (pkt->v4.vlen & 0xF) * 4; 14048 debugf("Got IPv4 %02X from %.4a to %.4a", pkt->v4.protocol, &pkt->v4.src, &pkt->v4.dst); 14049 src.type = mDNSAddrType_IPv4; src.ip.v4 = pkt->v4.src; 14050 dst.type = mDNSAddrType_IPv4; dst.ip.v4 = pkt->v4.dst; 14051 if (end >= trans + RequiredCapLen(pkt->v4.protocol)) 14052 mDNSCoreReceiveRawTransportPacket(m, ð->src, &src, &dst, pkt->v4.protocol, p, (TransportLayerPacket*)trans, end, InterfaceID, 0); 14053 } 14054 // Is IPv6? Length must be at least 14 + 28 = 42 bytes 14055 else if (end >= p+54 && mDNSSameOpaque16(eth->ethertype, Ethertype_IPv6)) 14056 { 14057 const mDNSu8 *const trans = p + 54; 14058 debugf("Got IPv6 %02X from %.16a to %.16a", pkt->v6.pro, &pkt->v6.src, &pkt->v6.dst); 14059 src.type = mDNSAddrType_IPv6; src.ip.v6 = pkt->v6.src; 14060 dst.type = mDNSAddrType_IPv6; dst.ip.v6 = pkt->v6.dst; 14061 if (end >= trans + RequiredCapLen(pkt->v6.pro)) 14062 mDNSCoreReceiveRawTransportPacket(m, ð->src, &src, &dst, pkt->v6.pro, p, (TransportLayerPacket*)trans, end, InterfaceID, 14063 (mDNSu16)pkt->bytes[4] << 8 | pkt->bytes[5]); 14064 } 14065 } 14066 14067 mDNSlocal void ConstructSleepProxyServerName(mDNS *const m, domainlabel *name) 14068 { 14069 name->c[0] = (mDNSu8)mDNS_snprintf((char*)name->c+1, 62, "%d-%d-%d-%d.%d %#s", 14070 m->SPSType, m->SPSPortability, m->SPSMarginalPower, m->SPSTotalPower, m->SPSFeatureFlags, &m->nicelabel); 14071 } 14072 14073 #ifndef SPC_DISABLED 14074 mDNSlocal void SleepProxyServerCallback(mDNS *const m, ServiceRecordSet *const srs, mStatus result) 14075 { 14076 if (result == mStatus_NameConflict) 14077 mDNS_RenameAndReregisterService(m, srs, mDNSNULL); 14078 else if (result == mStatus_MemFree) 14079 { 14080 if (m->SleepState) 14081 m->SPSState = 3; 14082 else 14083 { 14084 m->SPSState = (mDNSu8)(m->SPSSocket != mDNSNULL); 14085 if (m->SPSState) 14086 { 14087 domainlabel name; 14088 ConstructSleepProxyServerName(m, &name); 14089 mDNS_RegisterService(m, srs, 14090 &name, &SleepProxyServiceType, &localdomain, 14091 mDNSNULL, m->SPSSocket->port, // Host, port 14092 (mDNSu8 *)"", 1, // TXT data, length 14093 mDNSNULL, 0, // Subtypes (none) 14094 mDNSInterface_Any, // Interface ID 14095 SleepProxyServerCallback, mDNSNULL, 0); // Callback, context, flags 14096 } 14097 LogSPS("Sleep Proxy Server %#s %s", srs->RR_SRV.resrec.name->c, m->SPSState ? "started" : "stopped"); 14098 } 14099 } 14100 } 14101 #endif 14102 14103 // Called with lock held 14104 mDNSexport void mDNSCoreBeSleepProxyServer_internal(mDNS *const m, mDNSu8 sps, mDNSu8 port, mDNSu8 marginalpower, mDNSu8 totpower, mDNSu8 features) 14105 { 14106 // This routine uses mDNS_DeregisterService and calls SleepProxyServerCallback, so we execute in user callback context 14107 mDNS_DropLockBeforeCallback(); 14108 14109 // If turning off SPS, close our socket 14110 // (Do this first, BEFORE calling mDNS_DeregisterService below) 14111 if (!sps && m->SPSSocket) { mDNSPlatformUDPClose(m->SPSSocket); m->SPSSocket = mDNSNULL; } 14112 14113 // If turning off, or changing type, deregister old name 14114 #ifndef SPC_DISABLED 14115 if (m->SPSState == 1 && sps != m->SPSType) 14116 { m->SPSState = 2; mDNS_DeregisterService_drt(m, &m->SPSRecords, sps ? mDNS_Dereg_rapid : mDNS_Dereg_normal); } 14117 #endif // SPC_DISABLED 14118 14119 // Record our new SPS parameters 14120 m->SPSType = sps; 14121 m->SPSPortability = port; 14122 m->SPSMarginalPower = marginalpower; 14123 m->SPSTotalPower = totpower; 14124 m->SPSFeatureFlags = features; 14125 // If turning on, open socket and advertise service 14126 if (sps) 14127 { 14128 if (!m->SPSSocket) 14129 { 14130 m->SPSSocket = mDNSPlatformUDPSocket(m, zeroIPPort); 14131 if (!m->SPSSocket) { LogMsg("mDNSCoreBeSleepProxyServer: Failed to allocate SPSSocket"); goto fail; } 14132 } 14133 #ifndef SPC_DISABLED 14134 if (m->SPSState == 0) SleepProxyServerCallback(m, &m->SPSRecords, mStatus_MemFree); 14135 #endif // SPC_DISABLED 14136 } 14137 else if (m->SPSState) 14138 { 14139 LogSPS("mDNSCoreBeSleepProxyServer turning off from state %d; will wake clients", m->SPSState); 14140 m->NextScheduledSPS = m->timenow; 14141 } 14142 fail: 14143 mDNS_ReclaimLockAfterCallback(); 14144 } 14145 14146 // *************************************************************************** 14147 #if COMPILER_LIKES_PRAGMA_MARK 14148 #pragma mark - 14149 #pragma mark - Startup and Shutdown 14150 #endif 14151 14152 mDNSlocal void mDNS_GrowCache_internal(mDNS *const m, CacheEntity *storage, mDNSu32 numrecords) 14153 { 14154 if (storage && numrecords) 14155 { 14156 mDNSu32 i; 14157 debugf("Adding cache storage for %d more records (%d bytes)", numrecords, numrecords*sizeof(CacheEntity)); 14158 for (i=0; i<numrecords; i++) storage[i].next = &storage[i+1]; 14159 storage[numrecords-1].next = m->rrcache_free; 14160 m->rrcache_free = storage; 14161 m->rrcache_size += numrecords; 14162 } 14163 } 14164 14165 mDNSexport void mDNS_GrowCache(mDNS *const m, CacheEntity *storage, mDNSu32 numrecords) 14166 { 14167 mDNS_Lock(m); 14168 mDNS_GrowCache_internal(m, storage, numrecords); 14169 mDNS_Unlock(m); 14170 } 14171 14172 mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p, 14173 CacheEntity *rrcachestorage, mDNSu32 rrcachesize, 14174 mDNSBool AdvertiseLocalAddresses, mDNSCallback *Callback, void *Context) 14175 { 14176 mDNSu32 slot; 14177 mDNSs32 timenow; 14178 mStatus result; 14179 14180 if (!rrcachestorage) rrcachesize = 0; 14181 14182 m->p = p; 14183 m->CanReceiveUnicastOn5353 = mDNSfalse; // Assume we can't receive unicasts on 5353, unless platform layer tells us otherwise 14184 m->AdvertiseLocalAddresses = AdvertiseLocalAddresses; 14185 m->DivertMulticastAdvertisements = mDNSfalse; 14186 m->mDNSPlatformStatus = mStatus_Waiting; 14187 m->UnicastPort4 = zeroIPPort; 14188 m->UnicastPort6 = zeroIPPort; 14189 m->PrimaryMAC = zeroEthAddr; 14190 m->MainCallback = Callback; 14191 m->MainContext = Context; 14192 m->rec.r.resrec.RecordType = 0; 14193 m->rec.r.resrec.AnonInfo = mDNSNULL; 14194 14195 // For debugging: To catch and report locking failures 14196 m->mDNS_busy = 0; 14197 m->mDNS_reentrancy = 0; 14198 m->ShutdownTime = 0; 14199 m->lock_rrcache = 0; 14200 m->lock_Questions = 0; 14201 m->lock_Records = 0; 14202 14203 // Task Scheduling variables 14204 result = mDNSPlatformTimeInit(); 14205 if (result != mStatus_NoError) return(result); 14206 m->timenow_adjust = (mDNSs32)mDNSRandom(0xFFFFFFFF); 14207 timenow = mDNS_TimeNow_NoLock(m); 14208 14209 m->timenow = 0; // MUST only be set within mDNS_Lock/mDNS_Unlock section 14210 m->timenow_last = timenow; 14211 m->NextScheduledEvent = timenow; 14212 m->SuppressSending = timenow; 14213 m->NextCacheCheck = timenow + 0x78000000; 14214 m->NextScheduledQuery = timenow + 0x78000000; 14215 m->NextScheduledProbe = timenow + 0x78000000; 14216 m->NextScheduledResponse = timenow + 0x78000000; 14217 m->NextScheduledNATOp = timenow + 0x78000000; 14218 m->NextScheduledSPS = timenow + 0x78000000; 14219 m->NextScheduledKA = timenow + 0x78000000; 14220 m->NextScheduledStopTime = timenow + 0x78000000; 14221 m->RandomQueryDelay = 0; 14222 m->RandomReconfirmDelay = 0; 14223 m->PktNum = 0; 14224 m->MPktNum = 0; 14225 m->LocalRemoveEvents = mDNSfalse; 14226 m->SleepState = SleepState_Awake; 14227 m->SleepSeqNum = 0; 14228 m->SystemWakeOnLANEnabled = mDNSfalse; 14229 m->AnnounceOwner = NonZeroTime(timenow + 60 * mDNSPlatformOneSecond); 14230 m->DelaySleep = 0; 14231 m->SleepLimit = 0; 14232 14233 #if APPLE_OSX_mDNSResponder 14234 m->StatStartTime = mDNSPlatformUTC(); 14235 m->NextStatLogTime = m->StatStartTime + kDefaultNextStatsticsLogTime; 14236 m->ActiveStatTime = 0; 14237 m->UnicastPacketsSent = 0; 14238 m->MulticastPacketsSent = 0; 14239 m->RemoteSubnet = 0; 14240 #endif // APPLE_OSX_mDNSResponder 14241 14242 // These fields only required for mDNS Searcher... 14243 m->Questions = mDNSNULL; 14244 m->NewQuestions = mDNSNULL; 14245 m->CurrentQuestion = mDNSNULL; 14246 m->LocalOnlyQuestions = mDNSNULL; 14247 m->NewLocalOnlyQuestions = mDNSNULL; 14248 m->RestartQuestion = mDNSNULL; 14249 m->ValidationQuestion = mDNSNULL; 14250 m->rrcache_size = 0; 14251 m->rrcache_totalused = 0; 14252 m->rrcache_active = 0; 14253 m->rrcache_report = 10; 14254 m->rrcache_free = mDNSNULL; 14255 14256 for (slot = 0; slot < CACHE_HASH_SLOTS; slot++) 14257 { 14258 m->rrcache_hash[slot] = mDNSNULL; 14259 m->rrcache_nextcheck[slot] = timenow + 0x78000000;; 14260 } 14261 14262 mDNS_GrowCache_internal(m, rrcachestorage, rrcachesize); 14263 m->rrauth.rrauth_free = mDNSNULL; 14264 14265 for (slot = 0; slot < AUTH_HASH_SLOTS; slot++) 14266 m->rrauth.rrauth_hash[slot] = mDNSNULL; 14267 14268 // Fields below only required for mDNS Responder... 14269 m->hostlabel.c[0] = 0; 14270 m->nicelabel.c[0] = 0; 14271 m->MulticastHostname.c[0] = 0; 14272 m->HIHardware.c[0] = 0; 14273 m->HISoftware.c[0] = 0; 14274 m->ResourceRecords = mDNSNULL; 14275 m->DuplicateRecords = mDNSNULL; 14276 m->NewLocalRecords = mDNSNULL; 14277 m->NewLocalOnlyRecords = mDNSfalse; 14278 m->CurrentRecord = mDNSNULL; 14279 m->HostInterfaces = mDNSNULL; 14280 m->ProbeFailTime = 0; 14281 m->NumFailedProbes = 0; 14282 m->SuppressProbes = 0; 14283 14284 #ifndef UNICAST_DISABLED 14285 m->NextuDNSEvent = timenow + 0x78000000; 14286 m->NextSRVUpdate = timenow + 0x78000000; 14287 14288 m->DNSServers = mDNSNULL; 14289 14290 m->Router = zeroAddr; 14291 m->AdvertisedV4 = zeroAddr; 14292 m->AdvertisedV6 = zeroAddr; 14293 14294 m->AuthInfoList = mDNSNULL; 14295 14296 m->ReverseMap.ThisQInterval = -1; 14297 m->StaticHostname.c[0] = 0; 14298 m->FQDN.c[0] = 0; 14299 m->Hostnames = mDNSNULL; 14300 m->AutoTunnelNAT.clientContext = mDNSNULL; 14301 14302 m->WABBrowseQueriesCount = 0; 14303 m->WABLBrowseQueriesCount = 0; 14304 m->WABRegQueriesCount = 0; 14305 #if !TARGET_OS_EMBEDDED 14306 m->mDNSOppCaching = mDNStrue; 14307 #else 14308 m->mDNSOppCaching = mDNSfalse; 14309 #endif 14310 m->AutoTargetServices = 0; 14311 14312 // NAT traversal fields 14313 m->LLQNAT.clientCallback = mDNSNULL; 14314 m->LLQNAT.clientContext = mDNSNULL; 14315 m->NATTraversals = mDNSNULL; 14316 m->CurrentNATTraversal = mDNSNULL; 14317 m->retryIntervalGetAddr = 0; // delta between time sent and retry 14318 m->retryGetAddr = timenow + 0x78000000; // absolute time when we retry 14319 m->ExtAddress = zerov4Addr; 14320 m->PCPNonce[0] = mDNSRandom(-1); 14321 m->PCPNonce[1] = mDNSRandom(-1); 14322 m->PCPNonce[2] = mDNSRandom(-1); 14323 14324 m->NATMcastRecvskt = mDNSNULL; 14325 m->LastNATupseconds = 0; 14326 m->LastNATReplyLocalTime = timenow; 14327 m->LastNATMapResultCode = NATErr_None; 14328 14329 m->UPnPInterfaceID = 0; 14330 m->SSDPSocket = mDNSNULL; 14331 m->SSDPWANPPPConnection = mDNSfalse; 14332 m->UPnPRouterPort = zeroIPPort; 14333 m->UPnPSOAPPort = zeroIPPort; 14334 m->UPnPRouterURL = mDNSNULL; 14335 m->UPnPWANPPPConnection = mDNSfalse; 14336 m->UPnPSOAPURL = mDNSNULL; 14337 m->UPnPRouterAddressString = mDNSNULL; 14338 m->UPnPSOAPAddressString = mDNSNULL; 14339 m->SPSType = 0; 14340 m->SPSPortability = 0; 14341 m->SPSMarginalPower = 0; 14342 m->SPSTotalPower = 0; 14343 m->SPSFeatureFlags = 0; 14344 m->SPSState = 0; 14345 m->SPSProxyListChanged = mDNSNULL; 14346 m->SPSSocket = mDNSNULL; 14347 m->SPSBrowseCallback = mDNSNULL; 14348 m->ProxyRecords = 0; 14349 14350 #endif 14351 14352 #if APPLE_OSX_mDNSResponder 14353 m->TunnelClients = mDNSNULL; 14354 14355 #if !NO_WCF 14356 CHECK_WCF_FUNCTION(WCFConnectionNew) 14357 { 14358 m->WCF = WCFConnectionNew(); 14359 if (!m->WCF) { LogMsg("WCFConnectionNew failed"); return -1; } 14360 } 14361 #endif 14362 14363 #endif 14364 14365 result = mDNSPlatformInit(m); 14366 14367 #ifndef UNICAST_DISABLED 14368 // It's better to do this *after* the platform layer has set up the 14369 // interface list and security credentials 14370 uDNS_SetupDNSConfig(m); // Get initial DNS configuration 14371 #endif 14372 14373 return(result); 14374 } 14375 14376 mDNSexport void mDNS_ConfigChanged(mDNS *const m) 14377 { 14378 if (m->SPSState == 1) 14379 { 14380 domainlabel name, newname; 14381 #ifndef SPC_DISABLED 14382 domainname type, domain; 14383 DeconstructServiceName(m->SPSRecords.RR_SRV.resrec.name, &name, &type, &domain); 14384 #endif // SPC_DISABLED 14385 ConstructSleepProxyServerName(m, &newname); 14386 if (!SameDomainLabelCS(name.c, newname.c)) 14387 { 14388 LogSPS("Renaming SPS from “%#s” to “%#s”", name.c, newname.c); 14389 // When SleepProxyServerCallback gets the mStatus_MemFree message, 14390 // it will reregister the service under the new name 14391 m->SPSState = 2; 14392 #ifndef SPC_DISABLED 14393 mDNS_DeregisterService_drt(m, &m->SPSRecords, mDNS_Dereg_rapid); 14394 #endif // SPC_DISABLED 14395 } 14396 } 14397 14398 if (m->MainCallback) 14399 m->MainCallback(m, mStatus_ConfigChanged); 14400 } 14401 14402 mDNSlocal void DynDNSHostNameCallback(mDNS *const m, AuthRecord *const rr, mStatus result) 14403 { 14404 (void)m; // unused 14405 debugf("NameStatusCallback: result %d for registration of name %##s", result, rr->resrec.name->c); 14406 mDNSPlatformDynDNSHostNameStatusChanged(rr->resrec.name, result); 14407 } 14408 14409 mDNSlocal void PurgeOrReconfirmCacheRecord(mDNS *const m, CacheRecord *cr, const DNSServer * const ptr, mDNSBool lameduck) 14410 { 14411 mDNSBool purge = cr->resrec.RecordType == kDNSRecordTypePacketNegative || 14412 cr->resrec.rrtype == kDNSType_A || 14413 cr->resrec.rrtype == kDNSType_AAAA || 14414 cr->resrec.rrtype == kDNSType_SRV; 14415 14416 (void) lameduck; 14417 (void) ptr; 14418 debugf("PurgeOrReconfirmCacheRecord: %s cache record due to %s server %p %#a:%d (%##s): %s", 14419 purge ? "purging" : "reconfirming", 14420 lameduck ? "lame duck" : "new", 14421 ptr, &ptr->addr, mDNSVal16(ptr->port), ptr->domain.c, CRDisplayString(m, cr)); 14422 14423 if (purge) 14424 { 14425 LogInfo("PurgeorReconfirmCacheRecord: Purging Resourcerecord %s, RecordType %x", CRDisplayString(m, cr), cr->resrec.RecordType); 14426 mDNS_PurgeCacheResourceRecord(m, cr); 14427 } 14428 else 14429 { 14430 LogInfo("PurgeorReconfirmCacheRecord: Reconfirming Resourcerecord %s, RecordType %x", CRDisplayString(m, cr), cr->resrec.RecordType); 14431 mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer); 14432 } 14433 } 14434 14435 mDNSlocal void mDNS_PurgeForQuestion(mDNS *const m, DNSQuestion *q) 14436 { 14437 const mDNSu32 slot = HashSlot(&q->qname); 14438 CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); 14439 CacheRecord *rp; 14440 mDNSu8 validatingResponse = 0; 14441 14442 // For DNSSEC questions, purge the corresponding RRSIGs also. 14443 if (DNSSECQuestion(q)) 14444 { 14445 validatingResponse = q->ValidatingResponse; 14446 q->ValidatingResponse = mDNStrue; 14447 } 14448 for (rp = cg ? cg->members : mDNSNULL; rp; rp = rp->next) 14449 { 14450 if (SameNameRecordAnswersQuestion(&rp->resrec, q)) 14451 { 14452 LogInfo("mDNS_PurgeForQuestion: Flushing %s", CRDisplayString(m, rp)); 14453 mDNS_PurgeCacheResourceRecord(m, rp); 14454 } 14455 } 14456 if (DNSSECQuestion(q)) 14457 { 14458 q->ValidatingResponse = validatingResponse; 14459 } 14460 } 14461 14462 // For DNSSEC question, we need the DNSSEC records also. If the cache does not 14463 // have the DNSSEC records, we need to re-issue the question with EDNS0/DO bit set. 14464 // Just re-issuing the question for RRSIGs does not work in practice as the response 14465 // may not contain the RRSIGs whose typeCovered field matches the question's qtype. 14466 // 14467 // For negative responses, we need the NSECs to prove the non-existence. If we don't 14468 // have the cached NSECs, purge them. For positive responses, if we don't have the 14469 // RRSIGs and if we have not already issued the question with EDNS0/DO bit set, purge 14470 // them. 14471 mDNSlocal void CheckForDNSSECRecords(mDNS *const m, DNSQuestion *q) 14472 { 14473 const mDNSu32 slot = HashSlot(&q->qname); 14474 CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); 14475 CacheRecord *rp; 14476 14477 for (rp = cg ? cg->members : mDNSNULL; rp; rp = rp->next) 14478 { 14479 if (SameNameRecordAnswersQuestion(&rp->resrec, q)) 14480 { 14481 if (rp->resrec.RecordType != kDNSRecordTypePacketNegative || !rp->nsec) 14482 { 14483 if (!rp->CRDNSSECQuestion) 14484 { 14485 LogInfo("CheckForDNSSECRecords: Flushing %s", CRDisplayString(m, rp)); 14486 mDNS_PurgeCacheResourceRecord(m, rp); 14487 } 14488 } 14489 } 14490 } 14491 } 14492 14493 // Check for a positive unicast response to the question but with qtype 14494 mDNSexport mDNSBool mDNS_CheckForCacheRecord(mDNS *const m, DNSQuestion *q, mDNSu16 qtype) 14495 { 14496 DNSQuestion question; 14497 const mDNSu32 slot = HashSlot(&q->qname); 14498 CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname); 14499 CacheRecord *rp; 14500 14501 // Create an identical question but with qtype 14502 mDNS_SetupQuestion(&question, q->InterfaceID, &q->qname, qtype, mDNSNULL, mDNSNULL); 14503 question.qDNSServer = q->qDNSServer; 14504 14505 for (rp = cg ? cg->members : mDNSNULL; rp; rp = rp->next) 14506 { 14507 if (!rp->resrec.InterfaceID && rp->resrec.RecordType != kDNSRecordTypePacketNegative && 14508 SameNameRecordAnswersQuestion(&rp->resrec, &question)) 14509 { 14510 LogInfo("mDNS_CheckForCacheRecord: Found %s", CRDisplayString(m, rp)); 14511 return mDNStrue; 14512 } 14513 } 14514 return mDNSfalse; 14515 } 14516 14517 mDNSexport void DNSServerChangeForQuestion(mDNS *const m, DNSQuestion *q, DNSServer *new) 14518 { 14519 DNSQuestion *qptr; 14520 14521 (void) m; 14522 14523 if (q->DuplicateOf) 14524 LogMsg("DNSServerChangeForQuestion: ERROR: Called for duplicate question %##s", q->qname.c); 14525 14526 // Make sure all the duplicate questions point to the same DNSServer so that delivery 14527 // of events for all of them are consistent. Duplicates for a question are always inserted 14528 // after in the list. 14529 q->qDNSServer = new; 14530 for (qptr = q->next ; qptr; qptr = qptr->next) 14531 { 14532 if (qptr->DuplicateOf == q) { qptr->validDNSServers = q->validDNSServers; qptr->qDNSServer = new; } 14533 } 14534 } 14535 14536 mDNSlocal void SetConfigState(mDNS *const m, mDNSBool delete) 14537 { 14538 McastResolver *mr; 14539 DNSServer *ptr; 14540 14541 if (delete) 14542 { 14543 for (ptr = m->DNSServers; ptr; ptr = ptr->next) 14544 { 14545 ptr->penaltyTime = 0; 14546 NumUnicastDNSServers--; 14547 ptr->flags |= DNSServer_FlagDelete; 14548 } 14549 // We handle the mcast resolvers here itself as mDNSPlatformSetDNSConfig looks at 14550 // mcast resolvers. Today we get both mcast and ucast configuration using the same 14551 // API 14552 for (mr = m->McastResolvers; mr; mr = mr->next) 14553 mr->flags |= McastResolver_FlagDelete; 14554 } 14555 else 14556 { 14557 for (ptr = m->DNSServers; ptr; ptr = ptr->next) 14558 { 14559 ptr->penaltyTime = 0; 14560 NumUnicastDNSServers++; 14561 ptr->flags &= ~DNSServer_FlagDelete; 14562 } 14563 for (mr = m->McastResolvers; mr; mr = mr->next) 14564 mr->flags &= ~McastResolver_FlagDelete; 14565 } 14566 } 14567 14568 mDNSexport mStatus uDNS_SetupDNSConfig(mDNS *const m) 14569 { 14570 mDNSu32 slot; 14571 CacheGroup *cg; 14572 CacheRecord *cr; 14573 mDNSBool Restart = mDNSfalse; 14574 mDNSAddr v4, v6, r; 14575 domainname fqdn; 14576 DNSServer *ptr, **p = &m->DNSServers; 14577 const DNSServer *oldServers = m->DNSServers; 14578 DNSQuestion *q; 14579 McastResolver *mr, **mres = &m->McastResolvers; 14580 14581 debugf("uDNS_SetupDNSConfig: entry"); 14582 14583 // Let the platform layer get the current DNS information and setup the WAB queries if needed. 14584 uDNS_SetupWABQueries(m); 14585 14586 mDNS_Lock(m); 14587 14588 // We need to first mark all the entries to be deleted. If the configuration changed, then 14589 // the entries would be undeleted appropriately. Otherwise, we need to clear them. 14590 // 14591 // Note: The last argument to mDNSPlatformSetDNSConfig is "mDNStrue" which means ack the 14592 // configuration. We already processed search domains in uDNS_SetupWABQueries above and 14593 // hence we are ready to ack the configuration as this is the last call to mDNSPlatformSetConfig 14594 // for the dns configuration change notification. 14595 SetConfigState(m, mDNStrue); 14596 if (!mDNSPlatformSetDNSConfig(m, mDNStrue, mDNSfalse, &fqdn, mDNSNULL, mDNSNULL, mDNStrue)) 14597 { 14598 SetConfigState(m, mDNSfalse); 14599 mDNS_Unlock(m); 14600 LogInfo("uDNS_SetupDNSConfig: No configuration change"); 14601 return mStatus_NoError; 14602 } 14603 14604 // For now, we just delete the mcast resolvers. We don't deal with cache or 14605 // questions here. Neither question nor cache point to mcast resolvers. Questions 14606 // do inherit the timeout values from mcast resolvers. But we don't bother 14607 // affecting them as they never change. 14608 while (*mres) 14609 { 14610 if (((*mres)->flags & DNSServer_FlagDelete) != 0) 14611 { 14612 mr = *mres; 14613 *mres = (*mres)->next; 14614 debugf("uDNS_SetupDNSConfig: Deleting mcast resolver %##s", mr, mr->domain.c); 14615 mDNSPlatformMemFree(mr); 14616 } 14617 else 14618 { 14619 (*mres)->flags &= ~McastResolver_FlagNew; 14620 mres = &(*mres)->next; 14621 } 14622 } 14623 14624 // Update our qDNSServer pointers before we go and free the DNSServer object memory 14625 // 14626 // All non-scoped resolvers share the same resGroupID. At no point in time a cache entry using DNSServer 14627 // from scoped resolver will be used to answer non-scoped questions and vice versa, as scoped and non-scoped 14628 // resolvers don't share the same resGroupID. A few examples to describe the interaction with how we pick 14629 // DNSServers and flush the cache. 14630 // 14631 // - A non-scoped question picks DNSServer X, creates a cache entry with X. If a new resolver gets added later that 14632 // is a better match, we pick the new DNSServer for the question and activate the unicast query. We may or may not 14633 // flush the cache (See PurgeOrReconfirmCacheRecord). In either case, we don't change the cache record's DNSServer 14634 // pointer immediately (qDNSServer and rDNSServer may be different but still share the same resGroupID). If we don't 14635 // flush the cache immediately, the record's rDNSServer pointer will be updated (in mDNSCoreReceiveResponse) 14636 // later when we get the response. If we purge the cache, we still deliver a RMV when it is purged even though 14637 // we don't update the cache record's DNSServer pointer to match the question's DNSSever, as they both point to 14638 // the same resGroupID. 14639 // 14640 // Note: If the new DNSServer comes back with a different response than what we have in the cache, we will deliver a RMV 14641 // of the old followed by ADD of the new records. 14642 // 14643 // - A non-scoped question picks DNSServer X, creates a cache entry with X. If the resolver gets removed later, we will 14644 // pick a new DNSServer for the question which may or may not be NULL and set the cache record's pointer to the same 14645 // as in question's qDNSServer if the cache record is not flushed. If there is no active question, it will be set to NULL. 14646 // 14647 // - Two questions scoped and non-scoped for the same name will pick two different DNSServer and will end up creating separate 14648 // cache records and as the resGroupID is different, you can't use the cache record from the scoped DNSServer to answer the 14649 // non-scoped question and vice versa. 14650 // 14651 for (q = m->Questions; q; q=q->next) 14652 { 14653 if (!mDNSOpaque16IsZero(q->TargetQID)) 14654 { 14655 DNSServer *s, *t; 14656 DNSQuestion *qptr; 14657 if (q->DuplicateOf) continue; 14658 SetValidDNSServers(m, q); 14659 q->triedAllServersOnce = 0; 14660 s = GetServerForQuestion(m, q); 14661 t = q->qDNSServer; 14662 if (t != s) 14663 { 14664 mDNSBool old, new; 14665 mDNSIPPort tport, sport; 14666 14667 if (t) 14668 tport = t->port; 14669 else 14670 tport = zeroIPPort; 14671 if (s) 14672 sport = s->port; 14673 else 14674 sport = zeroIPPort; 14675 // If DNS Server for this question has changed, reactivate it 14676 LogInfo("uDNS_SetupDNSConfig: Updating DNS Server from %#a:%d (%##s) to %#a:%d (%##s) for question %##s (%s) (scope:%p)", 14677 t ? &t->addr : mDNSNULL, mDNSVal16(tport), t ? t->domain.c : (mDNSu8*)"", 14678 s ? &s->addr : mDNSNULL, mDNSVal16(sport), s ? s->domain.c : (mDNSu8*)"", 14679 q->qname.c, DNSTypeName(q->qtype), q->InterfaceID); 14680 14681 old = q->SuppressQuery; 14682 new = ShouldSuppressUnicastQuery(m, q, s); 14683 if (old != new) 14684 { 14685 // Changing the DNS server affected the SuppressQuery status. We need to 14686 // deliver RMVs for the previous ADDs (if any) before switching to the new 14687 // DNSServer. To keep it simple, we walk all the questions and mark them 14688 // to be restarted and then handle all of them at once. 14689 q->Restart = 1; 14690 q->SuppressQuery = new; 14691 for (qptr = q->next ; qptr; qptr = qptr->next) 14692 { 14693 if (qptr->DuplicateOf == q) 14694 qptr->Restart = 1; 14695 } 14696 Restart = mDNStrue; 14697 } 14698 else 14699 { 14700 DNSServerChangeForQuestion(m, q, s); 14701 q->unansweredQueries = 0; 14702 14703 // If we had sent a query out to DNSServer "t" and we are changing to "s", we 14704 // need to ignore the responses coming back from "t" as the DNS configuration 14705 // has changed e.g., when a new interface is coming up and that becomes the primary 14706 // interface, we switch to the DNS servers configured for the primary interface. In 14707 // this case, we should not accept responses associated with the previous interface as 14708 // the "name" could resolve differently on this new primary interface. Hence, discard 14709 // in-flight responses. 14710 q->TargetQID = mDNS_NewMessageID(m); 14711 14712 if (!QuerySuppressed(q)) 14713 { 14714 debugf("uDNS_SetupDNSConfig: Activating query %p %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype)); 14715 ActivateUnicastQuery(m, q, mDNStrue); 14716 // ActivateUnicastQuery is called for duplicate questions also as it does something 14717 // special for AutoTunnel questions 14718 for (qptr = q->next ; qptr; qptr = qptr->next) 14719 { 14720 if (qptr->DuplicateOf == q) ActivateUnicastQuery(m, qptr, mDNStrue); 14721 } 14722 } 14723 } 14724 } 14725 else 14726 { 14727 debugf("uDNS_SetupDNSConfig: Not Updating DNS server question %p %##s (%s) DNS server %#a:%d %p %d", 14728 q, q->qname.c, DNSTypeName(q->qtype), t ? &t->addr : mDNSNULL, mDNSVal16(t ? t->port : zeroIPPort), q->DuplicateOf, q->SuppressUnusable); 14729 for (qptr = q->next ; qptr; qptr = qptr->next) 14730 if (qptr->DuplicateOf == q) { qptr->validDNSServers = q->validDNSServers; qptr->qDNSServer = q->qDNSServer; } 14731 } 14732 } 14733 } 14734 if (Restart) 14735 RestartUnicastQuestions(m); 14736 14737 FORALL_CACHERECORDS(slot, cg, cr) 14738 { 14739 if (cr->resrec.InterfaceID) 14740 continue; 14741 14742 // We already walked the questions and restarted/reactivated them if the dns server 14743 // change affected the question. That should take care of updating the cache. But 14744 // what if there is no active question at this point when the DNS server change 14745 // happened ? There could be old cache entries lying around and if we don't flush 14746 // them, a new question after the DNS server change could pick up these stale 14747 // entries and get a wrong answer. 14748 // 14749 // For cache entries that have active questions we might have skipped rescheduling 14750 // the questions if they were suppressed (see above). To keep it simple, we walk 14751 // all the cache entries to make sure that there are no stale entries. We use the 14752 // active question's InterfaceID/ServiceID for looking up the right DNS server. 14753 // Note that the unscoped value for ServiceID is -1. 14754 // 14755 // Note: If GetServerForName returns NULL, it could either mean that there are no 14756 // DNS servers or no matching DNS servers for this question. In either case, 14757 // the cache should get purged below when we process deleted DNS servers. 14758 14759 ptr = GetServerForName(m, cr->resrec.name, 14760 (cr->CRActiveQuestion ? cr->CRActiveQuestion->InterfaceID : mDNSNULL), 14761 (cr->CRActiveQuestion ? cr->CRActiveQuestion->ServiceID : -1)); 14762 14763 // Purge or Reconfirm if this cache entry would use the new DNS server 14764 if (ptr && (ptr != cr->resrec.rDNSServer)) 14765 { 14766 // As the DNSServers for this cache record is not the same anymore, we don't 14767 // want any new questions to pick this old value. If there is no active question, 14768 // we can't possibly re-confirm, so purge in that case. If it is a DNSSEC question, 14769 // purge the cache as the DNSSEC capabilities of the DNS server may have changed. 14770 14771 if (cr->CRActiveQuestion == mDNSNULL || DNSSECQuestion(cr->CRActiveQuestion)) 14772 { 14773 LogInfo("uDNS_SetupDNSConfig: Purging Resourcerecord %s, New DNS server %#a , Old DNS server %#a", CRDisplayString(m, cr), 14774 &ptr->addr, (cr->resrec.rDNSServer != mDNSNULL ? &cr->resrec.rDNSServer->addr : mDNSNULL)); 14775 mDNS_PurgeCacheResourceRecord(m, cr); 14776 } 14777 else 14778 { 14779 LogInfo("uDNS_SetupDNSConfig: Purging/Reconfirming Resourcerecord %s, New DNS server %#a, Old DNS server %#a", CRDisplayString(m, cr), 14780 &ptr->addr, (cr->resrec.rDNSServer != mDNSNULL ? &cr->resrec.rDNSServer->addr : mDNSNULL)); 14781 PurgeOrReconfirmCacheRecord(m, cr, ptr, mDNSfalse); 14782 } 14783 } 14784 } 14785 14786 while (*p) 14787 { 14788 if (((*p)->flags & DNSServer_FlagDelete) != 0) 14789 { 14790 // Scan our cache, looking for uDNS records that we would have queried this server for. 14791 // We reconfirm any records that match, because in this world of split DNS, firewalls, etc. 14792 // different DNS servers can give different answers to the same question. 14793 ptr = *p; 14794 FORALL_CACHERECORDS(slot, cg, cr) 14795 { 14796 if (cr->resrec.InterfaceID) continue; 14797 if (cr->resrec.rDNSServer == ptr) 14798 { 14799 // If we don't have an active question for this cache record, neither Purge can 14800 // generate RMV events nor Reconfirm can send queries out. Just set the DNSServer 14801 // pointer on the record NULL so that we don't point to freed memory (We might dereference 14802 // DNSServer pointers from resource record for logging purposes). 14803 // 14804 // If there is an active question, point to its DNSServer as long as it does not point to the 14805 // freed one. We already went through the questions above and made them point at either the 14806 // new server or NULL if there is no server. 14807 14808 if (cr->CRActiveQuestion) 14809 { 14810 DNSQuestion *qptr = cr->CRActiveQuestion; 14811 14812 if (qptr->qDNSServer == ptr) 14813 { 14814 LogMsg("uDNS_SetupDNSConfig: ERROR!! Cache Record %s Active question %##s (%s) (scope:%p) poining to DNSServer Address %#a" 14815 " to be freed", CRDisplayString(m, cr), qptr->qname.c, DNSTypeName(qptr->qtype), qptr->InterfaceID, &ptr->addr); 14816 qptr->validDNSServers = zeroOpaque64; 14817 qptr->qDNSServer = mDNSNULL; 14818 cr->resrec.rDNSServer = mDNSNULL; 14819 } 14820 else 14821 { 14822 LogInfo("uDNS_SetupDNSConfig: Cache Record %s, Active question %##s (%s) (scope:%p), pointing to DNSServer %#a (to be deleted)," 14823 " resetting to question's DNSServer Address %#a", CRDisplayString(m, cr), qptr->qname.c, DNSTypeName(qptr->qtype), 14824 qptr->InterfaceID, &ptr->addr, (qptr->qDNSServer ? &qptr->qDNSServer->addr : mDNSNULL)); 14825 cr->resrec.rDNSServer = qptr->qDNSServer; 14826 } 14827 } 14828 else 14829 { 14830 LogInfo("uDNS_SetupDNSConfig: Cache Record %##s has no Active question, Record's DNSServer Address %#a, Server to be deleted %#a", 14831 cr->resrec.name, &cr->resrec.rDNSServer->addr, &ptr->addr); 14832 cr->resrec.rDNSServer = mDNSNULL; 14833 } 14834 14835 PurgeOrReconfirmCacheRecord(m, cr, ptr, mDNStrue); 14836 } 14837 } 14838 *p = (*p)->next; 14839 LogInfo("uDNS_SetupDNSConfig: Deleting server %p %#a:%d (%##s) %d", ptr, &ptr->addr, mDNSVal16(ptr->port), ptr->domain.c, NumUnicastDNSServers); 14840 mDNSPlatformMemFree(ptr); 14841 } 14842 else 14843 { 14844 (*p)->flags &= ~DNSServer_FlagNew; 14845 p = &(*p)->next; 14846 } 14847 } 14848 14849 // If we now have no DNS servers at all and we used to have some, then immediately purge all unicast cache records (including for LLQs). 14850 // This is important for giving prompt remove events when the user disconnects the Ethernet cable or turns off wireless. 14851 // Otherwise, stale data lingers for 5-10 seconds, which is not the user-experience people expect from Bonjour. 14852 // Similarly, if we now have some DNS servers and we used to have none, we want to purge any fake negative results we may have generated. 14853 if ((m->DNSServers != mDNSNULL) != (oldServers != mDNSNULL)) 14854 { 14855 int count = 0; 14856 FORALL_CACHERECORDS(slot, cg, cr) 14857 { 14858 if (!cr->resrec.InterfaceID) 14859 { 14860 mDNS_PurgeCacheResourceRecord(m, cr); 14861 count++; 14862 } 14863 } 14864 LogInfo("uDNS_SetupDNSConfig: %s available; purged %d unicast DNS records from cache", 14865 m->DNSServers ? "DNS server became" : "No DNS servers", count); 14866 14867 // Force anything that needs to get zone data to get that information again 14868 RestartRecordGetZoneData(m); 14869 } 14870 14871 // Did our FQDN change? 14872 if (!SameDomainName(&fqdn, &m->FQDN)) 14873 { 14874 if (m->FQDN.c[0]) mDNS_RemoveDynDNSHostName(m, &m->FQDN); 14875 14876 AssignDomainName(&m->FQDN, &fqdn); 14877 14878 if (m->FQDN.c[0]) 14879 { 14880 mDNSPlatformDynDNSHostNameStatusChanged(&m->FQDN, 1); 14881 mDNS_AddDynDNSHostName(m, &m->FQDN, DynDNSHostNameCallback, mDNSNULL); 14882 } 14883 } 14884 14885 mDNS_Unlock(m); 14886 14887 // handle router and primary interface changes 14888 v4 = v6 = r = zeroAddr; 14889 v4.type = r.type = mDNSAddrType_IPv4; 14890 14891 if (mDNSPlatformGetPrimaryInterface(m, &v4, &v6, &r) == mStatus_NoError && !mDNSv4AddressIsLinkLocal(&v4.ip.v4)) 14892 { 14893 mDNS_SetPrimaryInterfaceInfo(m, 14894 !mDNSIPv4AddressIsZero(v4.ip.v4) ? &v4 : mDNSNULL, 14895 !mDNSIPv6AddressIsZero(v6.ip.v6) ? &v6 : mDNSNULL, 14896 !mDNSIPv4AddressIsZero(r.ip.v4) ? &r : mDNSNULL); 14897 } 14898 else 14899 { 14900 mDNS_SetPrimaryInterfaceInfo(m, mDNSNULL, mDNSNULL, mDNSNULL); 14901 if (m->FQDN.c[0]) mDNSPlatformDynDNSHostNameStatusChanged(&m->FQDN, 1); // Set status to 1 to indicate temporary failure 14902 } 14903 14904 debugf("uDNS_SetupDNSConfig: number of unicast DNS servers %d", NumUnicastDNSServers); 14905 return mStatus_NoError; 14906 } 14907 14908 mDNSexport void mDNSCoreInitComplete(mDNS *const m, mStatus result) 14909 { 14910 m->mDNSPlatformStatus = result; 14911 if (m->MainCallback) 14912 { 14913 mDNS_Lock(m); 14914 mDNS_DropLockBeforeCallback(); // Allow client to legally make mDNS API calls from the callback 14915 m->MainCallback(m, mStatus_NoError); 14916 mDNS_ReclaimLockAfterCallback(); // Decrement mDNS_reentrancy to block mDNS API calls again 14917 mDNS_Unlock(m); 14918 } 14919 } 14920 14921 mDNSlocal void DeregLoop(mDNS *const m, AuthRecord *const start) 14922 { 14923 m->CurrentRecord = start; 14924 while (m->CurrentRecord) 14925 { 14926 AuthRecord *rr = m->CurrentRecord; 14927 LogInfo("DeregLoop: %s deregistration for %p %02X %s", 14928 (rr->resrec.RecordType != kDNSRecordTypeDeregistering) ? "Initiating " : "Accelerating", 14929 rr, rr->resrec.RecordType, ARDisplayString(m, rr)); 14930 if (rr->resrec.RecordType != kDNSRecordTypeDeregistering) 14931 mDNS_Deregister_internal(m, rr, mDNS_Dereg_rapid); 14932 else if (rr->AnnounceCount > 1) 14933 { 14934 rr->AnnounceCount = 1; 14935 rr->LastAPTime = m->timenow - rr->ThisAPInterval; 14936 } 14937 // Mustn't advance m->CurrentRecord until *after* mDNS_Deregister_internal, because 14938 // new records could have been added to the end of the list as a result of that call. 14939 if (m->CurrentRecord == rr) // If m->CurrentRecord was not advanced for us, do it now 14940 m->CurrentRecord = rr->next; 14941 } 14942 } 14943 14944 mDNSexport void mDNS_StartExit(mDNS *const m) 14945 { 14946 NetworkInterfaceInfo *intf; 14947 AuthRecord *rr; 14948 14949 mDNS_Lock(m); 14950 14951 LogInfo("mDNS_StartExit"); 14952 m->ShutdownTime = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 5); 14953 14954 mDNSCoreBeSleepProxyServer_internal(m, 0, 0, 0, 0, 0); 14955 14956 #if APPLE_OSX_mDNSResponder 14957 #if !NO_WCF 14958 CHECK_WCF_FUNCTION(WCFConnectionDealloc) 14959 { 14960 if (m->WCF) WCFConnectionDealloc((WCFConnection *)m->WCF); 14961 } 14962 #endif 14963 #endif 14964 14965 #ifndef UNICAST_DISABLED 14966 { 14967 SearchListElem *s; 14968 SuspendLLQs(m); 14969 // Don't need to do SleepRecordRegistrations() here 14970 // because we deregister all records and services later in this routine 14971 while (m->Hostnames) mDNS_RemoveDynDNSHostName(m, &m->Hostnames->fqdn); 14972 14973 // For each member of our SearchList, deregister any records it may have created, and cut them from the list. 14974 // Otherwise they'll be forcibly deregistered for us (without being cut them from the appropriate list) 14975 // and we may crash because the list still contains dangling pointers. 14976 for (s = SearchList; s; s = s->next) 14977 while (s->AuthRecs) 14978 { 14979 ARListElem *dereg = s->AuthRecs; 14980 s->AuthRecs = s->AuthRecs->next; 14981 mDNS_Deregister_internal(m, &dereg->ar, mDNS_Dereg_normal); // Memory will be freed in the FreeARElemCallback 14982 } 14983 } 14984 #endif 14985 14986 for (intf = m->HostInterfaces; intf; intf = intf->next) 14987 if (intf->Advertise) 14988 DeadvertiseInterface(m, intf); 14989 14990 // Shut down all our active NAT Traversals 14991 while (m->NATTraversals) 14992 { 14993 NATTraversalInfo *t = m->NATTraversals; 14994 mDNS_StopNATOperation_internal(m, t); // This will cut 't' from the list, thereby advancing m->NATTraversals in the process 14995 14996 // After stopping the NAT Traversal, we zero out the fields. 14997 // This has particularly important implications for our AutoTunnel records -- 14998 // when we deregister our AutoTunnel records below, we don't want their mStatus_MemFree 14999 // handlers to just turn around and attempt to re-register those same records. 15000 // Clearing t->ExternalPort/t->RequestedPort will cause the mStatus_MemFree callback handlers 15001 // to not do this. 15002 t->ExternalAddress = zerov4Addr; 15003 t->NewAddress = zerov4Addr; 15004 t->ExternalPort = zeroIPPort; 15005 t->RequestedPort = zeroIPPort; 15006 t->Lifetime = 0; 15007 t->Result = mStatus_NoError; 15008 } 15009 15010 // Make sure there are nothing but deregistering records remaining in the list 15011 if (m->CurrentRecord) 15012 LogMsg("mDNS_StartExit: ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord)); 15013 15014 // We're in the process of shutting down, so queries, etc. are no longer available. 15015 // Consequently, determining certain information, e.g. the uDNS update server's IP 15016 // address, will not be possible. The records on the main list are more likely to 15017 // already contain such information, so we deregister the duplicate records first. 15018 LogInfo("mDNS_StartExit: Deregistering duplicate resource records"); 15019 DeregLoop(m, m->DuplicateRecords); 15020 LogInfo("mDNS_StartExit: Deregistering resource records"); 15021 DeregLoop(m, m->ResourceRecords); 15022 15023 // If we scheduled a response to send goodbye packets, we set NextScheduledResponse to now. Normally when deregistering records, 15024 // we allow up to 100ms delay (to help improve record grouping) but when shutting down we don't want any such delay. 15025 if (m->NextScheduledResponse - m->timenow < mDNSPlatformOneSecond) 15026 { 15027 m->NextScheduledResponse = m->timenow; 15028 m->SuppressSending = 0; 15029 } 15030 15031 if (m->ResourceRecords) LogInfo("mDNS_StartExit: Sending final record deregistrations"); 15032 else LogInfo("mDNS_StartExit: No deregistering records remain"); 15033 15034 for (rr = m->DuplicateRecords; rr; rr = rr->next) 15035 LogMsg("mDNS_StartExit: Should not still have Duplicate Records remaining: %02X %s", rr->resrec.RecordType, ARDisplayString(m, rr)); 15036 15037 // If any deregistering records remain, send their deregistration announcements before we exit 15038 if (m->mDNSPlatformStatus != mStatus_NoError) DiscardDeregistrations(m); 15039 15040 mDNS_Unlock(m); 15041 15042 LogInfo("mDNS_StartExit: done"); 15043 } 15044 15045 mDNSexport void mDNS_FinalExit(mDNS *const m) 15046 { 15047 mDNSu32 rrcache_active = 0; 15048 mDNSu32 slot; 15049 AuthRecord *rr; 15050 15051 LogInfo("mDNS_FinalExit: mDNSPlatformClose"); 15052 mDNSPlatformClose(m); 15053 15054 for (slot = 0; slot < CACHE_HASH_SLOTS; slot++) 15055 { 15056 while (m->rrcache_hash[slot]) 15057 { 15058 CacheGroup *cg = m->rrcache_hash[slot]; 15059 while (cg->members) 15060 { 15061 CacheRecord *cr = cg->members; 15062 cg->members = cg->members->next; 15063 if (cr->CRActiveQuestion) rrcache_active++; 15064 ReleaseCacheRecord(m, cr); 15065 } 15066 cg->rrcache_tail = &cg->members; 15067 ReleaseCacheGroup(m, &m->rrcache_hash[slot]); 15068 } 15069 } 15070 debugf("mDNS_FinalExit: RR Cache was using %ld records, %lu active", m->rrcache_totalused, rrcache_active); 15071 if (rrcache_active != m->rrcache_active) 15072 LogMsg("*** ERROR *** rrcache_active %lu != m->rrcache_active %lu", rrcache_active, m->rrcache_active); 15073 15074 for (rr = m->ResourceRecords; rr; rr = rr->next) 15075 LogMsg("mDNS_FinalExit failed to send goodbye for: %p %02X %s", rr, rr->resrec.RecordType, ARDisplayString(m, rr)); 15076 15077 LogInfo("mDNS_FinalExit: done"); 15078 } 15079