1 /* -*- Mode: C; tab-width: 4; c-file-style: "bsd"; c-basic-offset: 4; fill-column: 108; indent-tabs-mode: nil; -*-
2  *
3  * Copyright (c) 2002-2020 Apple 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 
29 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
30 #include "D2D.h"
31 #endif
32 
33 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
34 #include <bsm/libbsm.h>
35 #endif
36 
37 #if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_ANALYTICS)
38 #include "dnssd_analytics.h"
39 #endif
40 
41 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
42 #include "QuerierSupport.h"
43 #endif
44 
45 // Disable certain benign warnings with Microsoft compilers
46 #if (defined(_MSC_VER))
47 // Disable "conditional expression is constant" warning for debug macros.
48 // Otherwise, this generates warnings for the perfectly natural construct "while(1)"
49 // If someone knows a variant way of writing "while(1)" that doesn't generate warning messages, please let us know
50     #pragma warning(disable:4127)
51 
52 // Disable "assignment within conditional expression".
53 // Other compilers understand the convention that if you place the assignment expression within an extra pair
54 // of parentheses, this signals to the compiler that you really intended an assignment and no warning is necessary.
55 // The Microsoft compiler doesn't understand this convention, so in the absense of any other way to signal
56 // to the compiler that the assignment is intentional, we have to just turn this warning off completely.
57     #pragma warning(disable:4706)
58 #endif
59 
60 #include "dns_sd.h" // for kDNSServiceFlags* definitions
61 #include "dns_sd_internal.h"
62 
63 #if APPLE_OSX_mDNSResponder
64 // Delay in seconds before disabling multicast after there are no active queries or registrations.
65 #define BONJOUR_DISABLE_DELAY 60
66 #endif
67 
68 #if MDNSRESPONDER_SUPPORTS(APPLE, WEB_CONTENT_FILTER)
69 #include <WebFilterDNS/WebFilterDNS.h>
70 
71 WCFConnection *WCFConnectionNew(void) __attribute__((weak_import));
72 void WCFConnectionDealloc(WCFConnection* c) __attribute__((weak_import));
73 #endif
74 
75 #if MDNSRESPONDER_SUPPORTS(APPLE, METRICS)
76 #include "Metrics.h"
77 #endif
78 
79 #if MDNSRESPONDER_SUPPORTS(APPLE, DNS64)
80 #include "DNS64.h"
81 #endif
82 
83 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
84 #include "dnssec_v2.h"
85 #endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
86 
87 // Forward declarations
88 mDNSlocal void BeginSleepProcessing(mDNS *const m);
89 mDNSlocal void RetrySPSRegistrations(mDNS *const m);
90 mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password, mDNSBool unicastOnly);
91 #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
92 mDNSlocal mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q);
93 #endif
94 mDNSlocal void mDNS_PurgeBeforeResolve(mDNS *const m, DNSQuestion *q);
95 mDNSlocal void mDNS_SendKeepalives(mDNS *const m);
96 mDNSlocal void mDNS_ExtractKeepaliveInfo(AuthRecord *ar, mDNSu32 *timeout, mDNSAddr *laddr, mDNSAddr *raddr, mDNSEthAddr *eth,
97                                          mDNSu32 *seq, mDNSu32 *ack, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu16 *win);
98 
99 typedef mDNSu32 DeadvertiseFlags;
100 #define kDeadvertiseFlag_NormalHostname (1U << 0)
101 #define kDeadvertiseFlag_RandHostname   (1U << 1)
102 #define kDeadvertiseFlag_All            (kDeadvertiseFlag_NormalHostname | kDeadvertiseFlag_RandHostname)
103 
104 mDNSlocal void DeadvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set, DeadvertiseFlags flags);
105 mDNSlocal void AdvertiseInterfaceIfNeeded(mDNS *const m, NetworkInterfaceInfo *set);
106 mDNSlocal mDNSu8 *GetValueForMACAddr(mDNSu8 *ptr, mDNSu8 *limit, mDNSEthAddr *eth);
107 
108 // ***************************************************************************
109 #if COMPILER_LIKES_PRAGMA_MARK
110 #pragma mark - Program Constants
111 #endif
112 
113 // To Turn OFF mDNS_Tracer set MDNS_TRACER to 0 or undef it
114 #define MDNS_TRACER 1
115 
116 // Any records bigger than this are considered 'large' records
117 #define SmallRecordLimit 1024
118 
119 #define kMaxUpdateCredits 10
120 #define kUpdateCreditRefreshInterval (mDNSPlatformOneSecond * 6)
121 
122 // define special NR_AnswerTo values
123 #define NR_AnswerMulticast  (mDNSu8*)~0
124 #define NR_AnswerUnicast    (mDNSu8*)~1
125 
126 // Question default timeout values
127 #define DEFAULT_MCAST_TIMEOUT       5
128 #define DEFAULT_LO_OR_P2P_TIMEOUT   5
129 
130 // The code (see SendQueries() and BuildQuestion()) needs to have the
131 // RequestUnicast value set to a value one greater than the number of times you want the query
132 // sent with the "request unicast response" (QU) bit set.
133 #define SET_QU_IN_FIRST_QUERY   2
134 #define kDefaultRequestUnicastCount SET_QU_IN_FIRST_QUERY
135 
136 // The time needed to offload records to a sleep proxy after powerd sends the kIOMessageSystemWillSleep notification
137 #define DARK_WAKE_DELAY_SLEEP  5
138 #define kDarkWakeDelaySleep    (mDNSPlatformOneSecond * DARK_WAKE_DELAY_SLEEP)
139 
140 // The maximum number of times we delay probing to prevent spurious conflicts due to stale packets
141 #define MAX_CONFLICT_PROCESSING_DELAYS 3
142 
143 // RFC 6762 defines Passive Observation Of Failures (POOF)
144 //
145 //    A host observes the multicast queries issued by the other hosts on
146 //    the network.  One of the major benefits of also sending responses
147 //    using multicast is that it allows all hosts to see the responses
148 //    (or lack thereof) to those queries.
149 //
150 //    If a host sees queries, for which a record in its cache would be
151 //    expected to be given as an answer in a multicast response, but no
152 //    such answer is seen, then the host may take this as an indication
153 //    that the record may no longer be valid.
154 //
155 //    After seeing two or more of these queries, and seeing no multicast
156 //    response containing the expected answer within ten seconds, then even
157 //    though its TTL may indicate that it is not yet due to expire, that
158 //    record SHOULD be flushed from the cache.
159 //
160 // <https://tools.ietf.org/html/rfc6762#section-10.5>
161 
162 #define POOF_ENABLED 1
163 
164 mDNSexport const char *const mDNS_DomainTypeNames[] =
165 {
166     "b._dns-sd._udp.",      // Browse
167     "db._dns-sd._udp.",     // Default Browse
168     "lb._dns-sd._udp.",     // Automatic Browse
169     "r._dns-sd._udp.",      // Registration
170     "dr._dns-sd._udp."      // Default Registration
171 };
172 
173 #ifdef UNICAST_DISABLED
174 #define uDNS_IsActiveQuery(q, u) mDNSfalse
175 #endif
176 
177 // ***************************************************************************
178 #if COMPILER_LIKES_PRAGMA_MARK
179 #pragma mark -
180 #pragma mark - General Utility Functions
181 #endif
182 
183 #if MDNS_MALLOC_DEBUGGING
184 // When doing memory allocation debugging, this function traverses all lists in the mDNS query
185 // structures and caches and checks each entry in the list to make sure it's still good.
mDNS_ValidateLists(void * context)186 mDNSlocal void mDNS_ValidateLists(void *context)
187 {
188     mDNS *m = context;
189 #if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
190     mDNSu32 NumAllInterfaceRecords   = 0;
191     mDNSu32 NumAllInterfaceQuestions = 0;
192 #endif
193 
194     // Check core mDNS lists
195     AuthRecord                  *rr;
196     for (rr = m->ResourceRecords; rr; rr=rr->next)
197     {
198         if (rr->next == (AuthRecord *)~0 || rr->resrec.RecordType == 0 || rr->resrec.RecordType == 0xFF)
199             LogMemCorruption("ResourceRecords list: %p is garbage (%X)", rr, rr->resrec.RecordType);
200         if (rr->resrec.name != &rr->namestorage)
201             LogMemCorruption("ResourceRecords list: %p name %p does not point to namestorage %p %##s",
202                              rr, rr->resrec.name->c, rr->namestorage.c, rr->namestorage.c);
203 #if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
204         if (!AuthRecord_uDNS(rr) && !RRLocalOnly(rr)) NumAllInterfaceRecords++;
205 #endif
206     }
207 
208     for (rr = m->DuplicateRecords; rr; rr=rr->next)
209     {
210         if (rr->next == (AuthRecord *)~0 || rr->resrec.RecordType == 0 || rr->resrec.RecordType == 0xFF)
211             LogMemCorruption("DuplicateRecords list: %p is garbage (%X)", rr, rr->resrec.RecordType);
212 #if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
213         if (!AuthRecord_uDNS(rr) && !RRLocalOnly(rr)) NumAllInterfaceRecords++;
214 #endif
215     }
216 
217     rr = m->NewLocalRecords;
218     if (rr)
219         if (rr->next == (AuthRecord *)~0 || rr->resrec.RecordType == 0 || rr->resrec.RecordType == 0xFF)
220             LogMemCorruption("NewLocalRecords: %p is garbage (%X)", rr, rr->resrec.RecordType);
221 
222     rr = m->CurrentRecord;
223     if (rr)
224         if (rr->next == (AuthRecord *)~0 || rr->resrec.RecordType == 0 || rr->resrec.RecordType == 0xFF)
225             LogMemCorruption("CurrentRecord: %p is garbage (%X)", rr, rr->resrec.RecordType);
226 
227     DNSQuestion                 *q;
228     for (q = m->Questions; q; q=q->next)
229     {
230         if (q->next == (DNSQuestion*)~0 || q->ThisQInterval == (mDNSs32) ~0)
231             LogMemCorruption("Questions list: %p is garbage (%lX %p)", q, q->ThisQInterval, q->next);
232         if (q->DuplicateOf && q->LocalSocket)
233             LogMemCorruption("Questions list: Duplicate Question %p should not have LocalSocket set %##s (%s)", q, q->qname.c, DNSTypeName(q->qtype));
234 #if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
235         if (!LocalOnlyOrP2PInterface(q->InterfaceID) && mDNSOpaque16IsZero(q->TargetQID))
236             NumAllInterfaceQuestions++;
237 #endif
238     }
239 
240     CacheGroup                  *cg;
241     CacheRecord                 *cr;
242     mDNSu32 slot;
243     FORALL_CACHERECORDS(slot, cg, cr)
244     {
245         if (cr->resrec.RecordType == 0 || cr->resrec.RecordType == 0xFF)
246             LogMemCorruption("Cache slot %lu: %p is garbage (%X)", slot, cr, cr->resrec.RecordType);
247         if (cr->CRActiveQuestion)
248         {
249             for (q = m->Questions; q; q=q->next) if (q == cr->CRActiveQuestion) break;
250             if (!q) LogMemCorruption("Cache slot %lu: CRActiveQuestion %p not in m->Questions list %s", slot, cr->CRActiveQuestion, CRDisplayString(m, cr));
251         }
252     }
253 
254 #if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
255     if (m->NumAllInterfaceRecords != NumAllInterfaceRecords)
256     	LogMemCorruption("NumAllInterfaceRecords is %d should be %d", m->NumAllInterfaceRecords, NumAllInterfaceRecords);
257 
258     if (m->NumAllInterfaceQuestions != NumAllInterfaceQuestions)
259     	LogMemCorruption("NumAllInterfaceQuestions is %d should be %d", m->NumAllInterfaceQuestions, NumAllInterfaceQuestions);
260 #endif // MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
261 }
262 #endif // MDNS_MALLOC_DEBUGGING
263 
264 // Returns true if this is a  unique, authoritative LocalOnly record that answers questions of type
265 // A, AAAA , CNAME, or PTR.  The caller should answer the question with this record and not send out
266 // the question on the wire if LocalOnlyRecordAnswersQuestion() also returns true.
267 // Main use is to handle /etc/hosts records and the LocalOnly PTR records created for localhost.
268 #define UniqueLocalOnlyRecord(rr) ((rr)->ARType == AuthRecordLocalOnly && \
269                                         (rr)->resrec.RecordType & kDNSRecordTypeUniqueMask && \
270                                         ((rr)->resrec.rrtype == kDNSType_A || (rr)->resrec.rrtype == kDNSType_AAAA || \
271                                          (rr)->resrec.rrtype == kDNSType_CNAME || \
272                                          (rr)->resrec.rrtype == kDNSType_PTR))
273 
SetNextQueryStopTime(mDNS * const m,const DNSQuestion * const q)274 mDNSlocal void SetNextQueryStopTime(mDNS *const m, const DNSQuestion *const q)
275 {
276     mDNS_CheckLock(m);
277 
278     if (m->NextScheduledStopTime - q->StopTime > 0)
279         m->NextScheduledStopTime = q->StopTime;
280 }
281 
SetNextQueryTime(mDNS * const m,const DNSQuestion * const q)282 mDNSexport void SetNextQueryTime(mDNS *const m, const DNSQuestion *const q)
283 {
284     mDNS_CheckLock(m);
285 
286     if (ActiveQuestion(q))
287     {
288         // Depending on whether this is a multicast or unicast question we want to set either:
289         // m->NextScheduledQuery = NextQSendTime(q) or
290         // m->NextuDNSEvent      = NextQSendTime(q)
291         mDNSs32 *const timer = mDNSOpaque16IsZero(q->TargetQID) ? &m->NextScheduledQuery : &m->NextuDNSEvent;
292         if (*timer - NextQSendTime(q) > 0)
293             *timer = NextQSendTime(q);
294     }
295 }
296 
ReleaseAuthEntity(AuthHash * r,AuthEntity * e)297 mDNSlocal void ReleaseAuthEntity(AuthHash *r, AuthEntity *e)
298 {
299 #if MDNS_MALLOC_DEBUGGING >= 1
300     unsigned int i;
301     for (i=0; i<sizeof(*e); i++) ((char*)e)[i] = 0xFF;
302 #endif
303     e->next = r->rrauth_free;
304     r->rrauth_free = e;
305     r->rrauth_totalused--;
306 }
307 
ReleaseAuthGroup(AuthHash * r,AuthGroup ** cp)308 mDNSlocal void ReleaseAuthGroup(AuthHash *r, AuthGroup **cp)
309 {
310     AuthEntity *e = (AuthEntity *)(*cp);
311     LogMsg("ReleaseAuthGroup:  Releasing AuthGroup %##s", (*cp)->name->c);
312     if ((*cp)->rrauth_tail != &(*cp)->members)
313         LogMsg("ERROR: (*cp)->members == mDNSNULL but (*cp)->rrauth_tail != &(*cp)->members)");
314     if ((*cp)->name != (domainname*)((*cp)->namestorage)) mDNSPlatformMemFree((*cp)->name);
315     (*cp)->name = mDNSNULL;
316     *cp = (*cp)->next;          // Cut record from list
317     ReleaseAuthEntity(r, e);
318 }
319 
GetAuthEntity(AuthHash * r,const AuthGroup * const PreserveAG)320 mDNSlocal AuthEntity *GetAuthEntity(AuthHash *r, const AuthGroup *const PreserveAG)
321 {
322     AuthEntity *e = mDNSNULL;
323 
324     if (r->rrauth_lock) { LogMsg("GetFreeCacheRR ERROR! Cache already locked!"); return(mDNSNULL); }
325     r->rrauth_lock = 1;
326 
327     if (!r->rrauth_free)
328     {
329         // We allocate just one AuthEntity at a time because we need to be able
330         // free them all individually which normally happens when we parse /etc/hosts into
331         // AuthHash where we add the "new" entries and discard (free) the already added
332         // entries. If we allocate as chunks, we can't free them individually.
333         AuthEntity *storage = (AuthEntity *) mDNSPlatformMemAllocateClear(sizeof(*storage));
334         storage->next = mDNSNULL;
335         r->rrauth_free = storage;
336     }
337 
338     // If we still have no free records, recycle all the records we can.
339     // Enumerating the entire auth is moderately expensive, so when we do it, we reclaim all the records we can in one pass.
340     if (!r->rrauth_free)
341     {
342         mDNSu32 oldtotalused = r->rrauth_totalused;
343         mDNSu32 slot;
344         for (slot = 0; slot < AUTH_HASH_SLOTS; slot++)
345         {
346             AuthGroup **cp = &r->rrauth_hash[slot];
347             while (*cp)
348             {
349                 if ((*cp)->members || (*cp)==PreserveAG) cp=&(*cp)->next;
350                 else ReleaseAuthGroup(r, cp);
351             }
352         }
353         LogInfo("GetAuthEntity: Recycled %d records to reduce auth cache from %d to %d",
354                 oldtotalused - r->rrauth_totalused, oldtotalused, r->rrauth_totalused);
355     }
356 
357     if (r->rrauth_free) // If there are records in the free list, take one
358     {
359         e = r->rrauth_free;
360         r->rrauth_free = e->next;
361         if (++r->rrauth_totalused >= r->rrauth_report)
362         {
363             LogInfo("RR Auth now using %ld objects", r->rrauth_totalused);
364             if      (r->rrauth_report <  100) r->rrauth_report += 10;
365             else if (r->rrauth_report < 1000) r->rrauth_report += 100;
366             else r->rrauth_report += 1000;
367         }
368         mDNSPlatformMemZero(e, sizeof(*e));
369     }
370 
371     r->rrauth_lock = 0;
372 
373     return(e);
374 }
375 
AuthGroupForName(AuthHash * r,const mDNSu32 namehash,const domainname * const name)376 mDNSexport AuthGroup *AuthGroupForName(AuthHash *r, const mDNSu32 namehash, const domainname *const name)
377 {
378     AuthGroup *ag;
379     const mDNSu32 slot = namehash % AUTH_HASH_SLOTS;
380 
381     for (ag = r->rrauth_hash[slot]; ag; ag=ag->next)
382         if (ag->namehash == namehash && SameDomainName(ag->name, name))
383             break;
384     return(ag);
385 }
386 
AuthGroupForRecord(AuthHash * r,const ResourceRecord * const rr)387 mDNSexport AuthGroup *AuthGroupForRecord(AuthHash *r, const ResourceRecord *const rr)
388 {
389     return(AuthGroupForName(r, rr->namehash, rr->name));
390 }
391 
GetAuthGroup(AuthHash * r,const ResourceRecord * const rr)392 mDNSlocal AuthGroup *GetAuthGroup(AuthHash *r, const ResourceRecord *const rr)
393 {
394     mDNSu16 namelen = DomainNameLength(rr->name);
395     AuthGroup *ag = (AuthGroup*)GetAuthEntity(r, mDNSNULL);
396     const mDNSu32 slot = rr->namehash % AUTH_HASH_SLOTS;
397     if (!ag) { LogMsg("GetAuthGroup: Failed to allocate memory for %##s", rr->name->c); return(mDNSNULL); }
398     ag->next         = r->rrauth_hash[slot];
399     ag->namehash     = rr->namehash;
400     ag->members      = mDNSNULL;
401     ag->rrauth_tail  = &ag->members;
402     ag->NewLocalOnlyRecords = mDNSNULL;
403     if (namelen > sizeof(ag->namestorage))
404         ag->name = (domainname *) mDNSPlatformMemAllocate(namelen);
405     else
406         ag->name = (domainname*)ag->namestorage;
407     if (!ag->name)
408     {
409         LogMsg("GetAuthGroup: Failed to allocate name storage for %##s", rr->name->c);
410         ReleaseAuthEntity(r, (AuthEntity*)ag);
411         return(mDNSNULL);
412     }
413     AssignDomainName(ag->name, rr->name);
414 
415     if (AuthGroupForRecord(r, rr)) LogMsg("GetAuthGroup: Already have AuthGroup for %##s", rr->name->c);
416     r->rrauth_hash[slot] = ag;
417     if (AuthGroupForRecord(r, rr) != ag) LogMsg("GetAuthGroup: Not finding AuthGroup for %##s", rr->name->c);
418 
419     return(ag);
420 }
421 
422 // Returns the AuthGroup in which the AuthRecord was inserted
InsertAuthRecord(mDNS * const m,AuthHash * r,AuthRecord * rr)423 mDNSexport AuthGroup *InsertAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr)
424 {
425     AuthGroup *ag;
426 
427     (void)m;
428     ag = AuthGroupForRecord(r, &rr->resrec);
429     if (!ag) ag = GetAuthGroup(r, &rr->resrec);   // If we don't have a AuthGroup for this name, make one now
430     if (ag)
431     {
432         *(ag->rrauth_tail) = rr;                // Append this record to tail of cache slot list
433         ag->rrauth_tail = &(rr->next);          // Advance tail pointer
434     }
435     return ag;
436 }
437 
RemoveAuthRecord(mDNS * const m,AuthHash * r,AuthRecord * rr)438 mDNSexport AuthGroup *RemoveAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr)
439 {
440     AuthGroup *a;
441     AuthRecord **rp;
442 
443     a = AuthGroupForRecord(r, &rr->resrec);
444     if (!a) { LogMsg("RemoveAuthRecord: ERROR!! AuthGroup not found for %s", ARDisplayString(m, rr)); return mDNSNULL; }
445     rp = &a->members;
446     while (*rp)
447     {
448         if (*rp != rr)
449             rp=&(*rp)->next;
450         else
451         {
452             // We don't break here, so that we can set the tail below without tracking "prev" pointers
453 
454             LogInfo("RemoveAuthRecord: removing auth record %s from table", ARDisplayString(m, rr));
455             *rp = (*rp)->next;          // Cut record from list
456         }
457     }
458     // TBD: If there are no more members, release authgroup ?
459     a->rrauth_tail = rp;
460     return a;
461 }
462 
CacheGroupForName(const mDNS * const m,const mDNSu32 namehash,const domainname * const name)463 mDNSexport CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 namehash, const domainname *const name)
464 {
465     CacheGroup *cg;
466     mDNSu32    slot = HashSlotFromNameHash(namehash);
467     for (cg = m->rrcache_hash[slot]; cg; cg=cg->next)
468         if (cg->namehash == namehash && SameDomainName(cg->name, name))
469             break;
470     return(cg);
471 }
472 
CacheGroupForRecord(const mDNS * const m,const ResourceRecord * const rr)473 mDNSlocal CacheGroup *CacheGroupForRecord(const mDNS *const m, const ResourceRecord *const rr)
474 {
475     return(CacheGroupForName(m, rr->namehash, rr->name));
476 }
477 
mDNS_AddressIsLocalSubnet(mDNS * const m,const mDNSInterfaceID InterfaceID,const mDNSAddr * addr)478 mDNSexport mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr)
479 {
480     NetworkInterfaceInfo *intf;
481 
482     if (addr->type == mDNSAddrType_IPv4)
483     {
484         // Normally we resist touching the NotAnInteger fields, but here we're doing tricky bitwise masking so we make an exception
485         if (mDNSv4AddressIsLinkLocal(&addr->ip.v4)) return(mDNStrue);
486         for (intf = m->HostInterfaces; intf; intf = intf->next)
487             if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID && intf->McastTxRx)
488                 if (((intf->ip.ip.v4.NotAnInteger ^ addr->ip.v4.NotAnInteger) & intf->mask.ip.v4.NotAnInteger) == 0)
489                     return(mDNStrue);
490     }
491 
492     if (addr->type == mDNSAddrType_IPv6)
493     {
494         if (mDNSv6AddressIsLinkLocal(&addr->ip.v6)) return(mDNStrue);
495         for (intf = m->HostInterfaces; intf; intf = intf->next)
496             if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID && intf->McastTxRx)
497                 if ((((intf->ip.ip.v6.l[0] ^ addr->ip.v6.l[0]) & intf->mask.ip.v6.l[0]) == 0) &&
498                     (((intf->ip.ip.v6.l[1] ^ addr->ip.v6.l[1]) & intf->mask.ip.v6.l[1]) == 0) &&
499                     (((intf->ip.ip.v6.l[2] ^ addr->ip.v6.l[2]) & intf->mask.ip.v6.l[2]) == 0) &&
500                     (((intf->ip.ip.v6.l[3] ^ addr->ip.v6.l[3]) & intf->mask.ip.v6.l[3]) == 0))
501                         return(mDNStrue);
502     }
503 
504     return(mDNSfalse);
505 }
506 
FirstInterfaceForID(mDNS * const m,const mDNSInterfaceID InterfaceID)507 mDNSlocal NetworkInterfaceInfo *FirstInterfaceForID(mDNS *const m, const mDNSInterfaceID InterfaceID)
508 {
509     NetworkInterfaceInfo *intf = m->HostInterfaces;
510     while (intf && intf->InterfaceID != InterfaceID) intf = intf->next;
511     return(intf);
512 }
513 
FirstIPv4LLInterfaceForID(mDNS * const m,const mDNSInterfaceID InterfaceID)514 mDNSlocal NetworkInterfaceInfo *FirstIPv4LLInterfaceForID(mDNS *const m, const mDNSInterfaceID InterfaceID)
515 {
516     NetworkInterfaceInfo *intf;
517 
518     if (!InterfaceID)
519         return mDNSNULL;
520 
521     // Note: We don't check for InterfaceActive, as the active interface could be IPv6 and
522     // we still want to find the first IPv4 Link-Local interface
523     for (intf = m->HostInterfaces; intf; intf = intf->next)
524     {
525         if (intf->InterfaceID == InterfaceID &&
526             intf->ip.type == mDNSAddrType_IPv4 && mDNSv4AddressIsLinkLocal(&intf->ip.ip.v4))
527         {
528             debugf("FirstIPv4LLInterfaceForID: found LL interface with address %.4a", &intf->ip.ip.v4);
529             return intf;
530         }
531     }
532     return (mDNSNULL);
533 }
534 
InterfaceNameForID(mDNS * const m,const mDNSInterfaceID InterfaceID)535 mDNSexport char *InterfaceNameForID(mDNS *const m, const mDNSInterfaceID InterfaceID)
536 {
537     NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID);
538     return(intf ? intf->ifname : mDNSNULL);
539 }
540 
541 // Caller should hold the lock
GenerateNegativeResponseEx(mDNS * const m,mDNSInterfaceID InterfaceID,QC_result qc,mDNSBool noData)542 mDNSlocal void GenerateNegativeResponseEx(mDNS *const m, mDNSInterfaceID InterfaceID, QC_result qc, mDNSBool noData)
543 {
544     DNSQuestion *q;
545     if (!m->CurrentQuestion) { LogMsg("GenerateNegativeResponse: ERROR!! CurrentQuestion not set"); return; }
546     q = m->CurrentQuestion;
547     LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
548            "[R%d->Q%d] GenerateNegativeResponse: Generating negative response for question " PRI_DM_NAME " (" PUB_S ")",
549            q->request_id, mDNSVal16(q->TargetQID), DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype));
550 
551     MakeNegativeCacheRecord(m, &m->rec.r, &q->qname, q->qnamehash, q->qtype, q->qclass, 60, InterfaceID, mDNSNULL);
552     m->rec.r.resrec.negativeRecordType = noData ? kNegativeRecordType_NoData : kNegativeRecordType_Unspecified;
553 
554     // We need to force the response through in the following cases
555     //
556     //  a) SuppressUnusable questions that are suppressed
557     //  b) Append search domains and retry the question
558     //
559     // The question may not have set Intermediates in which case we don't deliver negative responses. So, to force
560     // through we use "QC_forceresponse".
561     AnswerCurrentQuestionWithResourceRecord(m, &m->rec.r, qc);
562     if (m->CurrentQuestion == q) { q->ThisQInterval = 0; }              // Deactivate this question
563     // Don't touch the question after this
564     m->rec.r.resrec.RecordType = 0;     // Clear RecordType to show we're not still using it
565 }
566 #define GenerateNegativeResponse(M, INTERFACE_ID, QC) GenerateNegativeResponseEx(M, INTERFACE_ID, QC, mDNSfalse)
567 
AnswerQuestionByFollowingCNAME(mDNS * const m,DNSQuestion * q,ResourceRecord * rr)568 mDNSexport void AnswerQuestionByFollowingCNAME(mDNS *const m, DNSQuestion *q, ResourceRecord *rr)
569 {
570     const mDNSBool selfref = SameDomainName(&q->qname, &rr->rdata->u.name);
571     if (q->CNAMEReferrals >= 10 || selfref)
572     {
573         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
574                "[R%d->Q%d] AnswerQuestionByFollowingCNAME: %p " PRI_DM_NAME " (" PUB_S ")  NOT following CNAME referral %d" PUB_S " for " PRI_S,
575                q->request_id, mDNSVal16(q->TargetQID), q, DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype),
576                q->CNAMEReferrals, selfref ? " (Self-Referential)" : "", RRDisplayString(m, rr));
577 
578     }
579     else
580     {
581         UDPSocket *sock = q->LocalSocket;
582         mDNSOpaque16 id = q->TargetQID;
583 #if MDNSRESPONDER_SUPPORTS(APPLE, METRICS)
584         uDNSMetrics metrics;
585 #endif
586 
587         q->LocalSocket = mDNSNULL;
588 
589         // The SameDomainName check above is to ignore bogus CNAME records that point right back at
590         // themselves. Without that check we can get into a case where we have two duplicate questions,
591         // A and B, and when we stop question A, UpdateQuestionDuplicates copies the value of CNAMEReferrals
592         // from A to B, and then A is re-appended to the end of the list as a duplicate of B (because
593         // the target name is still the same), and then when we stop question B, UpdateQuestionDuplicates
594         // copies the B's value of CNAMEReferrals back to A, and we end up not incrementing CNAMEReferrals
595         // for either of them. This is not a problem for CNAME loops of two or more records because in
596         // those cases the newly re-appended question A has a different target name and therefore cannot be
597         // a duplicate of any other question ('B') which was itself a duplicate of the previous question A.
598 
599         // Right now we just stop and re-use the existing query. If we really wanted to be 100% perfect,
600         // and track CNAMEs coming and going, we should really create a subordinate query here,
601         // which we would subsequently cancel and retract if the CNAME referral record were removed.
602         // In reality this is such a corner case we'll ignore it until someone actually needs it.
603 
604         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
605                "[R%d->Q%d] AnswerQuestionByFollowingCNAME: %p " PRI_DM_NAME " (" PUB_S ") following CNAME referral %d for " PRI_S,
606                q->request_id, mDNSVal16(q->TargetQID), q, DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype),
607                q->CNAMEReferrals, RRDisplayString(m, rr));
608 
609 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
610         if (!mDNSOpaque16IsZero(q->TargetQID))
611         {
612             // Must be called before zeroing out q->metrics below.
613             Querier_PrepareQuestionForCNAMERestart(q);
614         }
615 #endif
616 #if MDNSRESPONDER_SUPPORTS(APPLE, METRICS)
617         if ((q->CNAMEReferrals == 0) && !q->metrics.originalQName)
618         {
619             domainname *    qName;
620             mDNSu16         qNameLen;
621 
622             qNameLen = DomainNameLength(&q->qname);
623             if ((qNameLen > 0) && (qNameLen <= MAX_DOMAIN_NAME))
624             {
625                 qName = (domainname *) mDNSPlatformMemAllocate(qNameLen);
626                 if (qName)
627                 {
628                     mDNSPlatformMemCopy(qName->c, q->qname.c, qNameLen);
629                     q->metrics.originalQName = qName;
630                 }
631             }
632         }
633         metrics = q->metrics;
634         // The metrics will be transplanted to the restarted question, so zero out the old copy instead of using
635         // uDNSMetricsClear(), which will free any pointers to allocated memory.
636         mDNSPlatformMemZero(&q->metrics, sizeof(q->metrics));
637 #endif
638         mDNS_StopQuery_internal(m, q);                              // Stop old query
639         AssignDomainName(&q->qname, &rr->rdata->u.name);            // Update qname
640         q->qnamehash = DomainNameHashValue(&q->qname);              // and namehash
641         // If a unicast query results in a CNAME that points to a .local, we need to re-try
642         // this as unicast. Setting the mDNSInterface_Unicast tells mDNS_StartQuery_internal
643         // to try this as unicast query even though it is a .local name
644         if (!mDNSOpaque16IsZero(q->TargetQID) && IsLocalDomain(&q->qname))
645         {
646             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
647                    "[R%d->Q%d] AnswerQuestionByFollowingCNAME: Resolving a .local CNAME %p " PRI_DM_NAME " (" PUB_S ") Record " PRI_S,
648                    q->request_id, mDNSVal16(q->TargetQID), q, DM_NAME_PARAM(&q->qname), DNSTypeName(q->qtype), RRDisplayString(m, rr));
649             q->IsUnicastDotLocal = mDNStrue;
650         }
651         q->CNAMEReferrals += 1;                                     // Increment value before calling mDNS_StartQuery_internal
652         const mDNSu32 c = q->CNAMEReferrals;                        // Stash a copy of the new q->CNAMEReferrals value
653         mDNS_StartQuery_internal(m, q);                             // start new query
654         // Record how many times we've done this. We need to do this *after* mDNS_StartQuery_internal,
655         // because mDNS_StartQuery_internal re-initializes CNAMEReferrals to zero
656         q->CNAMEReferrals = c;
657 #if MDNSRESPONDER_SUPPORTS(APPLE, METRICS)
658         metrics.expiredAnswerState  = q->metrics.expiredAnswerState; //  We want the newly initialized state for this value
659         metrics.dnsOverTCPState     = q->metrics.dnsOverTCPState;    //  We want the newly initialized state for this value
660         q->metrics = metrics;
661 #endif
662         if (sock)
663         {
664             // If our new query is a duplicate, then it can't have a socket of its own, so we have to close the one we saved.
665             if (q->DuplicateOf) mDNSPlatformUDPClose(sock);
666             else
667             {
668                 // Transplant the old socket into the new question, and copy the query ID across too.
669                 // No need to close the old q->LocalSocket value because it won't have been created yet (they're made lazily on-demand).
670                 q->LocalSocket = sock;
671                 q->TargetQID = id;
672             }
673         }
674     }
675 }
676 
677 #ifdef USE_LIBIDN
678 
679 #include <unicode/uidna.h>
680 
681 // #define DEBUG_PUNYCODE 1
682 
PunycodeConvert(const mDNSu8 * const src,mDNSu8 * const dst,const mDNSu8 * const end)683 mDNSlocal mDNSu8 *PunycodeConvert(const mDNSu8 *const src, mDNSu8 *const dst, const mDNSu8 *const end)
684 {
685     UErrorCode errorCode = U_ZERO_ERROR;
686     UIDNAInfo info = UIDNA_INFO_INITIALIZER;
687     UIDNA *uts46 = uidna_openUTS46(UIDNA_USE_STD3_RULES|UIDNA_NONTRANSITIONAL_TO_UNICODE, &errorCode);
688     int32_t len = uidna_nameToASCII_UTF8(uts46, (const char *)src+1, src[0], (char *)dst+1, (int32_t)(end-(dst+1)), &info, &errorCode);
689     uidna_close(uts46);
690     #if DEBUG_PUNYCODE
691     if (errorCode) LogMsg("uidna_nameToASCII_UTF8(%##s) failed errorCode %d", src, errorCode);
692     if (info.errors) LogMsg("uidna_nameToASCII_UTF8(%##s) failed info.errors 0x%08X", src, info.errors);
693     if (len > MAX_DOMAIN_LABEL) LogMsg("uidna_nameToASCII_UTF8(%##s) result too long %d", src, len);
694     #endif
695     if (errorCode || info.errors || len > MAX_DOMAIN_LABEL) return mDNSNULL;
696     *dst = len;
697     return(dst + 1 + len);
698 }
699 
IsHighASCIILabel(const mDNSu8 * d)700 mDNSlocal mDNSBool IsHighASCIILabel(const mDNSu8 *d)
701 {
702     int i;
703     for (i=1; i<=d[0]; i++) if (d[i] & 0x80) return mDNStrue;
704     return mDNSfalse;
705 }
706 
FindLastHighASCIILabel(const domainname * const d)707 mDNSlocal const mDNSu8 *FindLastHighASCIILabel(const domainname *const d)
708 {
709     const mDNSu8 *ptr = d->c;
710     const mDNSu8 *ans = mDNSNULL;
711     while (ptr[0])
712     {
713         const mDNSu8 *const next = ptr + 1 + ptr[0];
714         if (ptr[0] > MAX_DOMAIN_LABEL || next >= d->c + MAX_DOMAIN_NAME) return mDNSNULL;
715         if (IsHighASCIILabel(ptr)) ans = ptr;
716         ptr = next;
717     }
718     return ans;
719 }
720 
PerformNextPunycodeConversion(const DNSQuestion * const q,domainname * const newname)721 mDNSlocal mDNSBool PerformNextPunycodeConversion(const DNSQuestion *const q, domainname *const newname)
722 {
723     const mDNSu8 *h = FindLastHighASCIILabel(&q->qname);
724     #if DEBUG_PUNYCODE
725     LogMsg("PerformNextPunycodeConversion: %##s (%s) Last High-ASCII Label %##s", q->qname.c, DNSTypeName(q->qtype), h);
726     #endif
727     if (!h) return mDNSfalse;  // There are no high-ascii labels to convert
728 
729     mDNSu8 *const dst = PunycodeConvert(h, newname->c + (h - q->qname.c), newname->c + MAX_DOMAIN_NAME);
730     if (!dst)
731         return mDNSfalse;  // The label was not convertible to Punycode
732     else
733     {
734         // If Punycode conversion of final eligible label was successful, copy the rest of the domainname
735         const mDNSu8 *const src = h + 1 + h[0];
736         const mDNSu8 remainder  = DomainNameLength((domainname*)src);
737         if (dst + remainder > newname->c + MAX_DOMAIN_NAME) return mDNSfalse;  // Name too long -- cannot be converted to Punycode
738 
739         mDNSPlatformMemCopy(newname->c, q->qname.c, (mDNSu32)(h - q->qname.c));  // Fill in the leading part
740         mDNSPlatformMemCopy(dst, src, remainder);                     // Fill in the trailing part
741         #if DEBUG_PUNYCODE
742         LogMsg("PerformNextPunycodeConversion: %##s converted to %##s", q->qname.c, newname->c);
743         #endif
744         return mDNStrue;
745     }
746 }
747 
748 #endif // USE_LIBIDN
749 
750 // For a single given DNSQuestion pointed to by CurrentQuestion, deliver an add/remove result for the single given AuthRecord
751 // Note: All the callers should use the m->CurrentQuestion to see if the question is still valid or not
AnswerLocalQuestionWithLocalAuthRecord(mDNS * const m,AuthRecord * rr,QC_result AddRecord)752 mDNSlocal void AnswerLocalQuestionWithLocalAuthRecord(mDNS *const m, AuthRecord *rr, QC_result AddRecord)
753 {
754     DNSQuestion *q = m->CurrentQuestion;
755     mDNSBool followcname;
756 
757     if (!q)
758     {
759         LogMsg("AnswerLocalQuestionWithLocalAuthRecord: ERROR!! CurrentQuestion NULL while answering with %s", ARDisplayString(m, rr));
760         return;
761     }
762 
763     followcname = FollowCNAME(q, &rr->resrec, AddRecord);
764 
765     // We should not be delivering results for record types Unregistered, Deregistering, and (unverified) Unique
766     if (!(rr->resrec.RecordType & kDNSRecordTypeActiveMask))
767     {
768         LogMsg("AnswerLocalQuestionWithLocalAuthRecord: *NOT* delivering %s event for local record type %X %s",
769                AddRecord ? "Add" : "Rmv", rr->resrec.RecordType, ARDisplayString(m, rr));
770         return;
771     }
772 
773     // Indicate that we've given at least one positive answer for this record, so we should be prepared to send a goodbye for it
774     if (AddRecord) rr->AnsweredLocalQ = mDNStrue;
775     mDNS_DropLockBeforeCallback();      // Allow client to legally make mDNS API calls from the callback
776     if (q->QuestionCallback && !q->NoAnswer)
777     {
778         q->CurrentAnswers += AddRecord ? 1 : -1;
779         if (UniqueLocalOnlyRecord(rr))
780         {
781             if (!followcname || q->ReturnIntermed)
782             {
783                 // Don't send this packet on the wire as we answered from /etc/hosts
784                 q->ThisQInterval = 0;
785                 q->LOAddressAnswers += AddRecord ? 1 : -1;
786                 q->QuestionCallback(m, q, &rr->resrec, AddRecord);
787             }
788             mDNS_ReclaimLockAfterCallback();    // Decrement mDNS_reentrancy to block mDNS API calls again
789             // The callback above could have caused the question to stop. Detect that
790             // using m->CurrentQuestion
791             if (followcname && m->CurrentQuestion == q)
792                 AnswerQuestionByFollowingCNAME(m, q, &rr->resrec);
793             return;
794         }
795         else
796         {
797             q->QuestionCallback(m, q, &rr->resrec, AddRecord);
798         }
799     }
800     mDNS_ReclaimLockAfterCallback();    // Decrement mDNS_reentrancy to block mDNS API calls again
801 }
802 
AnswerInterfaceAnyQuestionsWithLocalAuthRecord(mDNS * const m,AuthRecord * ar,QC_result AddRecord)803 mDNSlocal void AnswerInterfaceAnyQuestionsWithLocalAuthRecord(mDNS *const m, AuthRecord *ar, QC_result AddRecord)
804 {
805     if (m->CurrentQuestion)
806         LogMsg("AnswerInterfaceAnyQuestionsWithLocalAuthRecord: ERROR m->CurrentQuestion already set: %##s (%s)",
807                m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
808     m->CurrentQuestion = m->Questions;
809     while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
810     {
811         mDNSBool answered;
812         DNSQuestion *q = m->CurrentQuestion;
813         if (RRAny(ar))
814             answered = AuthRecordAnswersQuestion(ar, q);
815         else
816             answered = LocalOnlyRecordAnswersQuestion(ar, q);
817         if (answered)
818             AnswerLocalQuestionWithLocalAuthRecord(m, ar, AddRecord);       // MUST NOT dereference q again
819         if (m->CurrentQuestion == q)    // If m->CurrentQuestion was not auto-advanced, do it ourselves now
820             m->CurrentQuestion = q->next;
821     }
822     m->CurrentQuestion = mDNSNULL;
823 }
824 
825 // When a new local AuthRecord is created or deleted, AnswerAllLocalQuestionsWithLocalAuthRecord()
826 // delivers the appropriate add/remove events to listening questions:
827 // 1. It runs though all our LocalOnlyQuestions delivering answers as appropriate,
828 //    stopping if it reaches a NewLocalOnlyQuestion -- brand-new questions are handled by AnswerNewLocalOnlyQuestion().
829 // 2. If the AuthRecord is marked mDNSInterface_LocalOnly or mDNSInterface_P2P, then it also runs though
830 //    our main question list, delivering answers to mDNSInterface_Any questions as appropriate,
831 //    stopping if it reaches a NewQuestion -- brand-new questions are handled by AnswerNewQuestion().
832 //
833 // AnswerAllLocalQuestionsWithLocalAuthRecord is used by the m->NewLocalRecords loop in mDNS_Execute(),
834 // and by mDNS_Deregister_internal()
835 
AnswerAllLocalQuestionsWithLocalAuthRecord(mDNS * const m,AuthRecord * ar,QC_result AddRecord)836 mDNSlocal void AnswerAllLocalQuestionsWithLocalAuthRecord(mDNS *const m, AuthRecord *ar, QC_result AddRecord)
837 {
838     if (m->CurrentQuestion)
839         LogMsg("AnswerAllLocalQuestionsWithLocalAuthRecord ERROR m->CurrentQuestion already set: %##s (%s)",
840                m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
841 
842     m->CurrentQuestion = m->LocalOnlyQuestions;
843     while (m->CurrentQuestion && m->CurrentQuestion != m->NewLocalOnlyQuestions)
844     {
845         mDNSBool answered;
846         DNSQuestion *q = m->CurrentQuestion;
847         // We are called with both LocalOnly/P2P record or a regular AuthRecord
848         if (RRAny(ar))
849             answered = AuthRecordAnswersQuestion(ar, q);
850         else
851             answered = LocalOnlyRecordAnswersQuestion(ar, q);
852         if (answered)
853             AnswerLocalQuestionWithLocalAuthRecord(m, ar, AddRecord);           // MUST NOT dereference q again
854         if (m->CurrentQuestion == q)    // If m->CurrentQuestion was not auto-advanced, do it ourselves now
855             m->CurrentQuestion = q->next;
856     }
857 
858     m->CurrentQuestion = mDNSNULL;
859 
860     // If this AuthRecord is marked LocalOnly or P2P, then we want to deliver it to all local 'mDNSInterface_Any' questions
861     if (ar->ARType == AuthRecordLocalOnly || ar->ARType == AuthRecordP2P)
862         AnswerInterfaceAnyQuestionsWithLocalAuthRecord(m, ar, AddRecord);
863 
864 }
865 
866 // ***************************************************************************
867 #if COMPILER_LIKES_PRAGMA_MARK
868 #pragma mark -
869 #pragma mark - Resource Record Utility Functions
870 #endif
871 
872 #define RRTypeIsAddressType(T) ((T) == kDNSType_A || (T) == kDNSType_AAAA)
873 
ResourceRecordIsValidAnswer(const AuthRecord * const rr)874 mDNSlocal mDNSBool ResourceRecordIsValidAnswer(const AuthRecord *const rr)
875 {
876     if ((rr->resrec.RecordType & kDNSRecordTypeActiveMask) &&
877         ((rr->Additional1 == mDNSNULL) || (rr->Additional1->resrec.RecordType & kDNSRecordTypeActiveMask)) &&
878         ((rr->Additional2 == mDNSNULL) || (rr->Additional2->resrec.RecordType & kDNSRecordTypeActiveMask)) &&
879         ((rr->DependentOn == mDNSNULL) || (rr->DependentOn->resrec.RecordType & kDNSRecordTypeActiveMask)))
880     {
881         return mDNStrue;
882     }
883     else
884     {
885         return mDNSfalse;
886     }
887 }
888 
IsInterfaceValidForAuthRecord(const AuthRecord * const rr,const mDNSInterfaceID InterfaceID)889 mDNSlocal mDNSBool IsInterfaceValidForAuthRecord(const AuthRecord *const rr, const mDNSInterfaceID InterfaceID)
890 {
891     if (rr->resrec.InterfaceID == mDNSInterface_Any)
892     {
893         return mDNSPlatformValidRecordForInterface(rr, InterfaceID);
894     }
895     else
896     {
897         return ((rr->resrec.InterfaceID == InterfaceID) ? mDNStrue : mDNSfalse);
898     }
899 }
900 
ResourceRecordIsValidInterfaceAnswer(const AuthRecord * const rr,const mDNSInterfaceID interfaceID)901 mDNSlocal mDNSBool ResourceRecordIsValidInterfaceAnswer(const AuthRecord *const rr, const mDNSInterfaceID interfaceID)
902 {
903     return ((IsInterfaceValidForAuthRecord(rr, interfaceID) && ResourceRecordIsValidAnswer(rr)) ? mDNStrue : mDNSfalse);
904 }
905 
906 #define DefaultProbeCountForTypeUnique ((mDNSu8)3)
907 #define DefaultProbeCountForRecordType(X)      ((X) == kDNSRecordTypeUnique ? DefaultProbeCountForTypeUnique : (mDNSu8)0)
908 
909 // Parameters for handling probing conflicts
910 #define kMaxAllowedMCastProbingConflicts 1                     // Maximum number of conflicts to allow from mcast messages.
911 #define kProbingConflictPauseDuration    mDNSPlatformOneSecond // Duration of probing pause after an allowed mcast conflict.
912 
913 // See RFC 6762: "8.3 Announcing"
914 // "The Multicast DNS responder MUST send at least two unsolicited responses, one second apart."
915 // Send 4, which is really 8 since we send on both IPv4 and IPv6.
916 #define InitialAnnounceCount ((mDNSu8)4)
917 
918 // For goodbye packets we set the count to 3, and for wakeups we set it to 18
919 // (which will be up to 15 wakeup attempts over the course of 30 seconds,
920 // and then if the machine fails to wake, 3 goodbye packets).
921 #define GoodbyeCount ((mDNSu8)3)
922 #define WakeupCount ((mDNSu8)18)
923 #define MAX_PROBE_RESTARTS ((mDNSu8)20)
924 #define MAX_GHOST_TIME ((mDNSs32)((60*60*24*7)*mDNSPlatformOneSecond))  //  One week
925 
926 // Number of wakeups we send if WakeOnResolve is set in the question
927 #define InitialWakeOnResolveCount ((mDNSu8)3)
928 
929 // Note that the announce intervals use exponential backoff, doubling each time. The probe intervals do not.
930 // This means that because the announce interval is doubled after sending the first packet, the first
931 // observed on-the-wire inter-packet interval between announcements is actually one second.
932 // The half-second value here may be thought of as a conceptual (non-existent) half-second delay *before* the first packet is sent.
933 #define DefaultProbeIntervalForTypeUnique (mDNSPlatformOneSecond/4)
934 #define DefaultAnnounceIntervalForTypeShared (mDNSPlatformOneSecond/2)
935 #define DefaultAnnounceIntervalForTypeUnique (mDNSPlatformOneSecond/2)
936 
937 #define DefaultAPIntervalForRecordType(X)  ((X) &kDNSRecordTypeActiveSharedMask ? DefaultAnnounceIntervalForTypeShared : \
938                                             (X) &kDNSRecordTypeUnique           ? DefaultProbeIntervalForTypeUnique    : \
939                                             (X) &kDNSRecordTypeActiveUniqueMask ? DefaultAnnounceIntervalForTypeUnique : 0)
940 
941 #define TimeToAnnounceThisRecord(RR,time) ((RR)->AnnounceCount && (time) - ((RR)->LastAPTime + (RR)->ThisAPInterval) >= 0)
942 #define TicksTTL(RR) ((mDNSs32)(RR)->resrec.rroriginalttl * mDNSPlatformOneSecond)
943 #define RRExpireTime(RR) ((RR)->TimeRcvd + TicksTTL(RR))
944 
945 // Adjustment factor to avoid race condition (used for unicast cache entries) :
946 // 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.
947 // If we do our normal refresh at 80% of the TTL, our local caching server will return 20 seconds, so we'll do another
948 // 80% refresh after 16 seconds, and then the server will return 4 seconds, and so on, in the fashion of Zeno's paradox.
949 // To avoid this, we extend the record's effective TTL to give it a little extra grace period.
950 // We adjust the 100 second TTL to 127. This means that when we do our 80% query after 102 seconds,
951 // the cached copy at our local caching server will already have expired, so the server will be forced
952 // to fetch a fresh copy from the authoritative server, and then return a fresh record with the full TTL of 3600 seconds.
953 
954 #define RRAdjustTTL(ttl) ((ttl) + ((ttl)/4) + 2)
955 #define RRUnadjustedTTL(ttl) ((((ttl) - 2) * 4) / 5)
956 
957 #define MaxUnansweredQueries 4
958 
959 // SameResourceRecordSignature returns true if two resources records have the same name, type, and class, and may be sent
960 // (or were received) on the same interface (i.e. if *both* records specify an interface, then it has to match).
961 // TTL and rdata may differ.
962 // This is used for cache flush management:
963 // When sending a unique record, all other records matching "SameResourceRecordSignature" must also be sent
964 // When receiving a unique record, all old cache records matching "SameResourceRecordSignature" are flushed
965 
966 // SameResourceRecordNameClassInterface is functionally the same as SameResourceRecordSignature, except rrtype does not have to match
967 
968 #define SameResourceRecordSignature(A,B) (A)->resrec.rrtype == (B)->resrec.rrtype && SameResourceRecordNameClassInterface((A),(B))
969 
SameResourceRecordNameClassInterface(const AuthRecord * const r1,const AuthRecord * const r2)970 mDNSlocal mDNSBool SameResourceRecordNameClassInterface(const AuthRecord *const r1, const AuthRecord *const r2)
971 {
972     if (!r1) { LogMsg("SameResourceRecordSignature ERROR: r1 is NULL"); return(mDNSfalse); }
973     if (!r2) { LogMsg("SameResourceRecordSignature ERROR: r2 is NULL"); return(mDNSfalse); }
974     if (r1->resrec.InterfaceID &&
975         r2->resrec.InterfaceID &&
976         r1->resrec.InterfaceID != r2->resrec.InterfaceID) return(mDNSfalse);
977     return (mDNSBool)(
978                r1->resrec.rrclass  == r2->resrec.rrclass &&
979                r1->resrec.namehash == r2->resrec.namehash &&
980                SameDomainName(r1->resrec.name, r2->resrec.name));
981 }
982 
983 // PacketRRMatchesSignature behaves as SameResourceRecordSignature, except that types may differ if our
984 // authoratative record is unique (as opposed to shared). For unique records, we are supposed to have
985 // complete ownership of *all* types for this name, so *any* record type with the same name is a conflict.
986 // In addition, when probing we send our questions with the wildcard type kDNSQType_ANY,
987 // so a response of any type should match, even if it is not actually the type the client plans to use.
988 
989 // For now, to make it easier to avoid false conflicts, we treat SPS Proxy records like shared records,
990 // and require the rrtypes to match for the rdata to be considered potentially conflicting
PacketRRMatchesSignature(const CacheRecord * const pktrr,const AuthRecord * const authrr)991 mDNSlocal mDNSBool PacketRRMatchesSignature(const CacheRecord *const pktrr, const AuthRecord *const authrr)
992 {
993     if (!pktrr)  { LogMsg("PacketRRMatchesSignature ERROR: pktrr is NULL"); return(mDNSfalse); }
994     if (!authrr) { LogMsg("PacketRRMatchesSignature ERROR: authrr is NULL"); return(mDNSfalse); }
995     if (pktrr->resrec.InterfaceID &&
996         authrr->resrec.InterfaceID &&
997         pktrr->resrec.InterfaceID != authrr->resrec.InterfaceID) return(mDNSfalse);
998     if (!(authrr->resrec.RecordType & kDNSRecordTypeUniqueMask) || authrr->WakeUp.HMAC.l[0])
999         if (pktrr->resrec.rrtype != authrr->resrec.rrtype) return(mDNSfalse);
1000     if ((authrr->resrec.InterfaceID == mDNSInterface_Any) &&
1001         !mDNSPlatformValidRecordForInterface(authrr, pktrr->resrec.InterfaceID)) return(mDNSfalse);
1002     return (mDNSBool)(
1003                pktrr->resrec.rrclass == authrr->resrec.rrclass &&
1004                pktrr->resrec.namehash == authrr->resrec.namehash &&
1005                SameDomainName(pktrr->resrec.name, authrr->resrec.name));
1006 }
1007 
1008 // CacheRecord *ka is the CacheRecord from the known answer list in the query.
1009 // This is the information that the requester believes to be correct.
1010 // AuthRecord *rr is the answer we are proposing to give, if not suppressed.
1011 // This is the information that we believe to be correct.
1012 // We've already determined that we plan to give this answer on this interface
1013 // (either the record is non-specific, or it is specific to this interface)
1014 // so now we just need to check the name, type, class, rdata and TTL.
ShouldSuppressKnownAnswer(const CacheRecord * const ka,const AuthRecord * const rr)1015 mDNSlocal mDNSBool ShouldSuppressKnownAnswer(const CacheRecord *const ka, const AuthRecord *const rr)
1016 {
1017     // If RR signature is different, or data is different, then don't suppress our answer
1018     if (!IdenticalResourceRecord(&ka->resrec, &rr->resrec)) return(mDNSfalse);
1019 
1020     // If the requester's indicated TTL is less than half the real TTL,
1021     // we need to give our answer before the requester's copy expires.
1022     // If the requester's indicated TTL is at least half the real TTL,
1023     // then we can suppress our answer this time.
1024     // If the requester's indicated TTL is greater than the TTL we believe,
1025     // then that's okay, and we don't need to do anything about it.
1026     // (If two responders on the network are offering the same information,
1027     // that's okay, and if they are offering the information with different TTLs,
1028     // the one offering the lower TTL should defer to the one offering the higher TTL.)
1029     return (mDNSBool)(ka->resrec.rroriginalttl >= rr->resrec.rroriginalttl / 2);
1030 }
1031 
SetNextAnnounceProbeTime(mDNS * const m,const AuthRecord * const rr)1032 mDNSlocal void SetNextAnnounceProbeTime(mDNS *const m, const AuthRecord *const rr)
1033 {
1034     if (rr->resrec.RecordType == kDNSRecordTypeUnique)
1035     {
1036         if ((rr->LastAPTime + rr->ThisAPInterval) - m->timenow > mDNSPlatformOneSecond * 10)
1037         {
1038             LogMsg("SetNextAnnounceProbeTime: ProbeCount %d Next in %d %s", rr->ProbeCount, (rr->LastAPTime + rr->ThisAPInterval) - m->timenow, ARDisplayString(m, rr));
1039             LogMsg("SetNextAnnounceProbeTime: m->SuppressProbes %d m->timenow %d diff %d", m->SuppressProbes, m->timenow, m->SuppressProbes - m->timenow);
1040         }
1041         if (m->NextScheduledProbe - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
1042             m->NextScheduledProbe = (rr->LastAPTime + rr->ThisAPInterval);
1043         // Some defensive code:
1044         // If (rr->LastAPTime + rr->ThisAPInterval) happens to be far in the past, we don't want to allow
1045         // NextScheduledProbe to be set excessively in the past, because that can cause bad things to happen.
1046         // See: <rdar://problem/7795434> mDNS: Sometimes advertising stops working and record interval is set to zero
1047         if (m->NextScheduledProbe - m->timenow < 0)
1048             m->NextScheduledProbe = m->timenow;
1049     }
1050     else if (rr->AnnounceCount && (ResourceRecordIsValidAnswer(rr) || rr->resrec.RecordType == kDNSRecordTypeDeregistering))
1051     {
1052         if (m->NextScheduledResponse - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
1053             m->NextScheduledResponse = (rr->LastAPTime + rr->ThisAPInterval);
1054     }
1055 }
1056 
InitializeLastAPTime(mDNS * const m,AuthRecord * const rr)1057 mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr)
1058 {
1059     // For reverse-mapping Sleep Proxy PTR records, probe interval is one second
1060     rr->ThisAPInterval = rr->AddressProxy.type ? mDNSPlatformOneSecond : DefaultAPIntervalForRecordType(rr->resrec.RecordType);
1061 
1062     // * If this is a record type that's going to probe, then we use the m->SuppressProbes time.
1063     // * Otherwise, if it's not going to probe, but m->SuppressProbes is set because we have other
1064     //   records that are going to probe, then we delay its first announcement so that it will
1065     //   go out synchronized with the first announcement for the other records that *are* probing.
1066     //   This is a minor performance tweak that helps keep groups of related records synchronized together.
1067     //   The addition of "interval / 2" is to make sure that, in the event that any of the probes are
1068     //   delayed by a few milliseconds, this announcement does not inadvertently go out *before* the probing is complete.
1069     //   When the probing is complete and those records begin to announce, these records will also be picked up and accelerated,
1070     //   because they will meet the criterion of being at least half-way to their scheduled announcement time.
1071     // * If it's not going to probe and m->SuppressProbes is not already set then we should announce immediately.
1072 
1073     if (rr->ProbeCount)
1074     {
1075         rr->ProbingConflictCount = 0;
1076         // If we have no probe suppression time set, or it is in the past, set it now
1077         if (m->SuppressProbes == 0 || m->SuppressProbes - m->timenow < 0)
1078         {
1079             // To allow us to aggregate probes when a group of services are registered together,
1080             // the first probe is delayed by a random delay in the range 1/8 to 1/4 second.
1081             // This means the common-case behaviour is:
1082             // randomized wait; probe
1083             // 1/4 second wait; probe
1084             // 1/4 second wait; probe
1085             // 1/4 second wait; announce (i.e. service is normally announced 7/8 to 1 second after being registered)
1086             m->SuppressProbes = NonZeroTime(m->timenow + DefaultProbeIntervalForTypeUnique/2 + mDNSRandom(DefaultProbeIntervalForTypeUnique/2));
1087 
1088             // If we already have a *probe* scheduled to go out sooner, then use that time to get better aggregation
1089             if (m->SuppressProbes - m->NextScheduledProbe >= 0)
1090                 m->SuppressProbes = NonZeroTime(m->NextScheduledProbe);
1091             if (m->SuppressProbes - m->timenow < 0)     // Make sure we don't set m->SuppressProbes excessively in the past
1092                 m->SuppressProbes = m->timenow;
1093 
1094             // If we already have a *query* scheduled to go out sooner, then use that time to get better aggregation
1095             if (m->SuppressProbes - m->NextScheduledQuery >= 0)
1096                 m->SuppressProbes = NonZeroTime(m->NextScheduledQuery);
1097             if (m->SuppressProbes - m->timenow < 0)     // Make sure we don't set m->SuppressProbes excessively in the past
1098                 m->SuppressProbes = m->timenow;
1099 
1100             // except... don't expect to be able to send before the m->SuppressSending timer fires
1101             if (m->SuppressSending && m->SuppressProbes - m->SuppressSending < 0)
1102                 m->SuppressProbes = NonZeroTime(m->SuppressSending);
1103 
1104             if (m->SuppressProbes - m->timenow > mDNSPlatformOneSecond * 8)
1105             {
1106                 LogMsg("InitializeLastAPTime ERROR m->SuppressProbes %d m->NextScheduledProbe %d m->NextScheduledQuery %d m->SuppressSending %d %d",
1107                        m->SuppressProbes     - m->timenow,
1108                        m->NextScheduledProbe - m->timenow,
1109                        m->NextScheduledQuery - m->timenow,
1110                        m->SuppressSending,
1111                        m->SuppressSending    - m->timenow);
1112                 m->SuppressProbes = NonZeroTime(m->timenow + DefaultProbeIntervalForTypeUnique/2 + mDNSRandom(DefaultProbeIntervalForTypeUnique/2));
1113             }
1114         }
1115         rr->LastAPTime = m->SuppressProbes - rr->ThisAPInterval;
1116     }
1117     // Skip kDNSRecordTypeKnownUnique and kDNSRecordTypeShared records here and set their LastAPTime in the "else" block below so
1118     // that they get announced immediately, otherwise, their announcement would be delayed until the based on the SuppressProbes value.
1119     else if ((rr->resrec.RecordType != kDNSRecordTypeKnownUnique) && (rr->resrec.RecordType != kDNSRecordTypeShared) && m->SuppressProbes && (m->SuppressProbes - m->timenow >= 0))
1120         rr->LastAPTime = m->SuppressProbes - rr->ThisAPInterval + DefaultProbeIntervalForTypeUnique * DefaultProbeCountForTypeUnique + rr->ThisAPInterval / 2;
1121     else
1122         rr->LastAPTime = m->timenow - rr->ThisAPInterval;
1123 
1124     // For reverse-mapping Sleep Proxy PTR records we don't want to start probing instantly -- we
1125     // wait one second to give the client a chance to go to sleep, and then start our ARP/NDP probing.
1126     // After three probes one second apart with no answer, we conclude the client is now sleeping
1127     // and we can begin broadcasting our announcements to take over ownership of that IP address.
1128     // If we don't wait for the client to go to sleep, then when the client sees our ARP Announcements there's a risk
1129     // (depending on the OS and networking stack it's using) that it might interpret it as a conflict and change its IP address.
1130     if (rr->AddressProxy.type)
1131         rr->LastAPTime = m->timenow;
1132 
1133     // Set LastMCTime to now, to inhibit multicast responses
1134     // (no need to send additional multicast responses when we're announcing anyway)
1135     rr->LastMCTime      = m->timenow;
1136     rr->LastMCInterface = mDNSInterfaceMark;
1137 
1138     SetNextAnnounceProbeTime(m, rr);
1139 }
1140 
SetUnicastTargetToHostName(mDNS * const m,AuthRecord * rr)1141 mDNSlocal const domainname *SetUnicastTargetToHostName(mDNS *const m, AuthRecord *rr)
1142 {
1143     const domainname *target;
1144     if (rr->AutoTarget)
1145     {
1146         rr->AutoTarget = Target_AutoHostAndNATMAP;
1147     }
1148 
1149     target = GetServiceTarget(m, rr);
1150     if (!target || target->c[0] == 0)
1151     {
1152         // defer registration until we've got a target
1153         LogInfo("SetUnicastTargetToHostName No target for %s", ARDisplayString(m, rr));
1154         rr->state = regState_NoTarget;
1155         return mDNSNULL;
1156     }
1157     else
1158     {
1159         LogInfo("SetUnicastTargetToHostName target %##s for resource record %s", target->c, ARDisplayString(m,rr));
1160         return target;
1161     }
1162 }
1163 
1164 #if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
AuthRecordIncludesOrIsAWDL(const AuthRecord * const ar)1165 mDNSlocal mDNSBool AuthRecordIncludesOrIsAWDL(const AuthRecord *const ar)
1166 {
1167     return ((AuthRecordIncludesAWDL(ar) || mDNSPlatformInterfaceIsAWDL(ar->resrec.InterfaceID)) ? mDNStrue : mDNSfalse);
1168 }
1169 #endif
1170 
1171 // Right now this only applies to mDNS (.local) services where the target host is always m->MulticastHostname
1172 // Eventually we should unify this with GetServiceTarget() in uDNS.c
SetTargetToHostName(mDNS * const m,AuthRecord * const rr)1173 mDNSlocal void SetTargetToHostName(mDNS *const m, AuthRecord *const rr)
1174 {
1175     domainname *const target = GetRRDomainNameTarget(&rr->resrec);
1176     const domainname *newname;
1177 
1178 #if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
1179     if (AuthRecordIncludesOrIsAWDL(rr))
1180     {
1181         newname = &m->RandomizedHostname;
1182     }
1183     else
1184 #endif
1185     {
1186         newname = &m->MulticastHostname;
1187     }
1188     if (!target) LogInfo("SetTargetToHostName: Don't know how to set the target of rrtype %s", DNSTypeName(rr->resrec.rrtype));
1189 
1190     if (!(rr->ForceMCast || rr->ARType == AuthRecordLocalOnly || rr->ARType == AuthRecordP2P || IsLocalDomain(&rr->namestorage)))
1191     {
1192         const domainname *const n = SetUnicastTargetToHostName(m, rr);
1193         if (n) newname = n;
1194         else { if (target) target->c[0] = 0; SetNewRData(&rr->resrec, mDNSNULL, 0); return; }
1195     }
1196 
1197     if (target && SameDomainName(target, newname))
1198         debugf("SetTargetToHostName: Target of %##s is already %##s", rr->resrec.name->c, target->c);
1199 
1200     if (target && !SameDomainName(target, newname))
1201     {
1202         AssignDomainName(target, newname);
1203         SetNewRData(&rr->resrec, mDNSNULL, 0);      // Update rdlength, rdestimate, rdatahash
1204 
1205         // If we're in the middle of probing this record, we need to start again,
1206         // because changing its rdata may change the outcome of the tie-breaker.
1207         // (If the record type is kDNSRecordTypeUnique (unconfirmed unique) then DefaultProbeCountForRecordType is non-zero.)
1208         rr->ProbeCount     = DefaultProbeCountForRecordType(rr->resrec.RecordType);
1209 
1210         // If we've announced this record, we really should send a goodbye packet for the old rdata before
1211         // changing to the new rdata. However, in practice, we only do SetTargetToHostName for unique records,
1212         // so when we announce them we'll set the kDNSClass_UniqueRRSet and clear any stale data that way.
1213         if (rr->RequireGoodbye && rr->resrec.RecordType == kDNSRecordTypeShared)
1214             debugf("Have announced shared record %##s (%s) at least once: should have sent a goodbye packet before updating",
1215                    rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
1216 
1217         rr->AnnounceCount  = InitialAnnounceCount;
1218         rr->RequireGoodbye = mDNSfalse;
1219         rr->ProbeRestartCount = 0;
1220         InitializeLastAPTime(m, rr);
1221     }
1222 }
1223 
AcknowledgeRecord(mDNS * const m,AuthRecord * const rr)1224 mDNSlocal void AcknowledgeRecord(mDNS *const m, AuthRecord *const rr)
1225 {
1226     if (rr->RecordCallback)
1227     {
1228         // CAUTION: MUST NOT do anything more with rr after calling rr->Callback(), because the client's callback function
1229         // is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc.
1230         rr->Acknowledged = mDNStrue;
1231         mDNS_DropLockBeforeCallback();      // Allow client to legally make mDNS API calls from the callback
1232         rr->RecordCallback(m, rr, mStatus_NoError);
1233         mDNS_ReclaimLockAfterCallback();    // Decrement mDNS_reentrancy to block mDNS API calls again
1234     }
1235 }
1236 
ActivateUnicastRegistration(mDNS * const m,AuthRecord * const rr)1237 mDNSexport void ActivateUnicastRegistration(mDNS *const m, AuthRecord *const rr)
1238 {
1239     // Make sure that we don't activate the SRV record and associated service records, if it is in
1240     // NoTarget state. First time when a service is being instantiated, SRV record may be in NoTarget state.
1241     // We should not activate any of the other reords (PTR, TXT) that are part of the service. When
1242     // the target becomes available, the records will be reregistered.
1243     if (rr->resrec.rrtype != kDNSType_SRV)
1244     {
1245         AuthRecord *srvRR = mDNSNULL;
1246         if (rr->resrec.rrtype == kDNSType_PTR)
1247             srvRR = rr->Additional1;
1248         else if (rr->resrec.rrtype == kDNSType_TXT)
1249             srvRR = rr->DependentOn;
1250         if (srvRR)
1251         {
1252             if (srvRR->resrec.rrtype != kDNSType_SRV)
1253             {
1254                 LogMsg("ActivateUnicastRegistration: ERROR!! Resource record %s wrong, expecting SRV type", ARDisplayString(m, srvRR));
1255             }
1256             else
1257             {
1258                 LogInfo("ActivateUnicastRegistration: Found Service Record %s in state %d for %##s (%s)",
1259                         ARDisplayString(m, srvRR), srvRR->state, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
1260                 rr->state = srvRR->state;
1261             }
1262         }
1263     }
1264 
1265     if (rr->state == regState_NoTarget)
1266     {
1267         LogInfo("ActivateUnicastRegistration record %s in regState_NoTarget, not activating", ARDisplayString(m, rr));
1268         return;
1269     }
1270     // When we wake up from sleep, we call ActivateUnicastRegistration. It is possible that just before we went to sleep,
1271     // the service/record was being deregistered. In that case, we should not try to register again. For the cases where
1272     // the records are deregistered due to e.g., no target for the SRV record, we would have returned from above if it
1273     // was already in NoTarget state. If it was in the process of deregistration but did not complete fully before we went
1274     // 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.
1275     if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
1276     {
1277         LogInfo("ActivateUnicastRegistration: Resource record %s, current state %d, moving to DeregPending", ARDisplayString(m, rr), rr->state);
1278         rr->state = regState_DeregPending;
1279     }
1280     else
1281     {
1282         LogInfo("ActivateUnicastRegistration: Resource record %s, current state %d, moving to Pending", ARDisplayString(m, rr), rr->state);
1283         rr->state = regState_Pending;
1284     }
1285     rr->ProbingConflictCount = 0;
1286     rr->LastConflictPktNum   = 0;
1287     rr->ProbeRestartCount    = 0;
1288     rr->ProbeCount           = 0;
1289     rr->AnnounceCount        = 0;
1290     rr->ThisAPInterval       = INIT_RECORD_REG_INTERVAL;
1291     rr->LastAPTime           = m->timenow - rr->ThisAPInterval;
1292     rr->expire               = 0; // Forget about all the leases, start fresh
1293     rr->uselease             = mDNStrue;
1294     rr->updateid             = zeroID;
1295     rr->SRVChanged           = mDNSfalse;
1296     rr->updateError          = mStatus_NoError;
1297     // RestartRecordGetZoneData calls this function whenever a new interface gets registered with core.
1298     // The records might already be registered with the server and hence could have NAT state.
1299     if (rr->NATinfo.clientContext)
1300     {
1301         mDNS_StopNATOperation_internal(m, &rr->NATinfo);
1302         rr->NATinfo.clientContext = mDNSNULL;
1303     }
1304     if (rr->nta) { CancelGetZoneData(m, rr->nta); rr->nta = mDNSNULL; }
1305     if (rr->tcp) { DisposeTCPConn(rr->tcp);       rr->tcp = mDNSNULL; }
1306     if (m->NextuDNSEvent - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
1307         m->NextuDNSEvent = (rr->LastAPTime + rr->ThisAPInterval);
1308 }
1309 
1310 // Two records qualify to be local duplicates if:
1311 // (a) the RecordTypes are the same, or
1312 // (b) one is Unique and the other Verified
1313 // (c) either is in the process of deregistering
1314 #define RecordLDT(A,B) ((A)->resrec.RecordType == (B)->resrec.RecordType || \
1315                         ((A)->resrec.RecordType | (B)->resrec.RecordType) == (kDNSRecordTypeUnique | kDNSRecordTypeVerified) || \
1316                         ((A)->resrec.RecordType == kDNSRecordTypeDeregistering || (B)->resrec.RecordType == kDNSRecordTypeDeregistering))
1317 
1318 #define RecordIsLocalDuplicate(A,B) \
1319     ((A)->resrec.InterfaceID == (B)->resrec.InterfaceID && RecordLDT((A),(B)) && IdenticalResourceRecord(& (A)->resrec, & (B)->resrec))
1320 
CheckAuthIdenticalRecord(AuthHash * r,AuthRecord * rr)1321 mDNSlocal AuthRecord *CheckAuthIdenticalRecord(AuthHash *r, AuthRecord *rr)
1322 {
1323     const AuthGroup *a;
1324     AuthRecord *rp;
1325 
1326     a = AuthGroupForRecord(r, &rr->resrec);
1327     if (!a) return mDNSNULL;
1328     rp = a->members;
1329     while (rp)
1330     {
1331         if (!RecordIsLocalDuplicate(rp, rr))
1332             rp = rp->next;
1333         else
1334         {
1335             if (rp->resrec.RecordType == kDNSRecordTypeDeregistering)
1336             {
1337                 rp->AnnounceCount = 0;
1338                 rp = rp->next;
1339             }
1340             else return rp;
1341         }
1342     }
1343     return (mDNSNULL);
1344 }
1345 
CheckAuthRecordConflict(AuthHash * r,AuthRecord * rr)1346 mDNSlocal mDNSBool CheckAuthRecordConflict(AuthHash *r, AuthRecord *rr)
1347 {
1348     const AuthGroup *a;
1349     const AuthRecord *rp;
1350 
1351     a = AuthGroupForRecord(r, &rr->resrec);
1352     if (!a) return mDNSfalse;
1353     rp = a->members;
1354     while (rp)
1355     {
1356         const AuthRecord *s1 = rr->RRSet ? rr->RRSet : rr;
1357         const AuthRecord *s2 = rp->RRSet ? rp->RRSet : rp;
1358         if (s1 != s2 && SameResourceRecordSignature(rp, rr) && !IdenticalSameNameRecord(&rp->resrec, &rr->resrec))
1359             return mDNStrue;
1360         else
1361             rp = rp->next;
1362     }
1363     return (mDNSfalse);
1364 }
1365 
1366 // checks to see if "rr" is already present
CheckAuthSameRecord(AuthHash * r,AuthRecord * rr)1367 mDNSlocal AuthRecord *CheckAuthSameRecord(AuthHash *r, AuthRecord *rr)
1368 {
1369     const AuthGroup *a;
1370     AuthRecord *rp;
1371 
1372     a = AuthGroupForRecord(r, &rr->resrec);
1373     if (!a) return mDNSNULL;
1374     rp = a->members;
1375     while (rp)
1376     {
1377         if (rp != rr)
1378             rp = rp->next;
1379         else
1380         {
1381             return rp;
1382         }
1383     }
1384     return (mDNSNULL);
1385 }
1386 
DecrementAutoTargetServices(mDNS * const m,AuthRecord * const rr)1387 mDNSlocal void DecrementAutoTargetServices(mDNS *const m, AuthRecord *const rr)
1388 {
1389     if (RRLocalOnly(rr))
1390     {
1391         // A sanity check, this should be prevented in calling code.
1392         LogInfo("DecrementAutoTargetServices: called for RRLocalOnly() record: %s", ARDisplayString(m, rr));
1393         return;
1394     }
1395 
1396     if (!AuthRecord_uDNS(rr) && (rr->resrec.rrtype == kDNSType_SRV) && (rr->AutoTarget == Target_AutoHost))
1397     {
1398         NetworkInterfaceInfo *intf;
1399 #if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
1400         DeadvertiseFlags flags     = 0; // DeadvertiseFlags for non-AWDL interfaces.
1401         DeadvertiseFlags flagsAWDL = 0; // DeadvertiseFlags for AWDL interfaces.
1402         if (AuthRecordIncludesOrIsAWDL(rr))
1403         {
1404             if (AuthRecordIncludesAWDL(rr))
1405             {
1406                 m->AutoTargetAWDLIncludedCount--;
1407                 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
1408                     "DecrementAutoTargetServices: AutoTargetAWDLIncludedCount %u Record " PRI_S,
1409                     m->AutoTargetAWDLIncludedCount, ARDisplayString(m, rr));
1410                 if (m->AutoTargetAWDLIncludedCount == 0)
1411                 {
1412                     flags |= kDeadvertiseFlag_RandHostname;
1413                     if (m->AutoTargetAWDLOnlyCount == 0) flagsAWDL |= kDeadvertiseFlag_RandHostname;
1414                 }
1415             }
1416             else
1417             {
1418                 m->AutoTargetAWDLOnlyCount--;
1419                 LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
1420                     "DecrementAutoTargetServices: AutoTargetAWDLOnlyCount %u Record " PRI_S,
1421                     m->AutoTargetAWDLOnlyCount, ARDisplayString(m, rr));
1422                 if ((m->AutoTargetAWDLIncludedCount == 0) && (m->AutoTargetAWDLOnlyCount == 0))
1423                 {
1424                     flagsAWDL |= kDeadvertiseFlag_RandHostname;
1425                 }
1426             }
1427             if (flags || flagsAWDL)
1428             {
1429                 for (intf = m->HostInterfaces; intf; intf = intf->next)
1430                 {
1431                     if (!intf->Advertise) continue;
1432                     if (mDNSPlatformInterfaceIsAWDL(intf->InterfaceID))
1433                     {
1434                         if (flagsAWDL) DeadvertiseInterface(m, intf, flagsAWDL);
1435                     }
1436                     else
1437                     {
1438                         if (flags) DeadvertiseInterface(m, intf, flags);
1439                     }
1440                 }
1441             }
1442             if ((m->AutoTargetAWDLIncludedCount == 0) && (m->AutoTargetAWDLOnlyCount == 0))
1443             {
1444                 GetRandomUUIDLocalHostname(&m->RandomizedHostname);
1445             }
1446         }
1447         else
1448 #endif
1449         {
1450             m->AutoTargetServices--;
1451             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
1452                 "DecrementAutoTargetServices: AutoTargetServices %u Record " PRI_S,
1453                 m->AutoTargetServices, ARDisplayString(m, rr));
1454             if (m->AutoTargetServices == 0)
1455             {
1456                 for (intf = m->HostInterfaces; intf; intf = intf->next)
1457                 {
1458                     if (intf->Advertise) DeadvertiseInterface(m, intf, kDeadvertiseFlag_NormalHostname);
1459                 }
1460             }
1461         }
1462     }
1463 
1464 #if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
1465     if (!AuthRecord_uDNS(rr))
1466     {
1467         if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1)
1468             m->NextBonjourDisableTime = NonZeroTime(m->timenow + (BONJOUR_DISABLE_DELAY * mDNSPlatformOneSecond));
1469         m->NumAllInterfaceRecords--;
1470         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
1471             "DecrementAutoTargetServices: NumAllInterfaceRecords %u NumAllInterfaceQuestions %u " PRI_S,
1472             m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, ARDisplayString(m, rr));
1473     }
1474 #endif
1475 }
1476 
AdvertiseNecessaryInterfaceRecords(mDNS * const m)1477 mDNSlocal void AdvertiseNecessaryInterfaceRecords(mDNS *const m)
1478 {
1479     NetworkInterfaceInfo *intf;
1480     for (intf = m->HostInterfaces; intf; intf = intf->next)
1481     {
1482         if (intf->Advertise) AdvertiseInterfaceIfNeeded(m, intf);
1483     }
1484 }
1485 
IncrementAutoTargetServices(mDNS * const m,AuthRecord * const rr)1486 mDNSlocal void IncrementAutoTargetServices(mDNS *const m, AuthRecord *const rr)
1487 {
1488     mDNSBool enablingBonjour = mDNSfalse;
1489 
1490     if (RRLocalOnly(rr))
1491     {
1492         // A sanity check, this should be prevented in calling code.
1493         LogInfo("IncrementAutoTargetServices: called for RRLocalOnly() record: %s", ARDisplayString(m, rr));
1494         return;
1495     }
1496 
1497 #if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
1498     if (!AuthRecord_uDNS(rr))
1499     {
1500         m->NumAllInterfaceRecords++;
1501         LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
1502             "IncrementAutoTargetServices: NumAllInterfaceRecords %u NumAllInterfaceQuestions %u " PRI_S,
1503             m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, ARDisplayString(m, rr));
1504         if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1)
1505         {
1506             m->NextBonjourDisableTime = 0;
1507             if (m->BonjourEnabled == 0)
1508             {
1509                 // Enable Bonjour immediately by scheduling network changed processing where
1510                 // we will join the multicast group on each active interface.
1511                 m->BonjourEnabled = 1;
1512                 enablingBonjour = mDNStrue;
1513                 m->NetworkChanged = m->timenow;
1514             }
1515         }
1516     }
1517 #endif
1518 
1519     if (!AuthRecord_uDNS(rr) && (rr->resrec.rrtype == kDNSType_SRV) && (rr->AutoTarget == Target_AutoHost))
1520     {
1521 #if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
1522         if (AuthRecordIncludesAWDL(rr))
1523         {
1524             m->AutoTargetAWDLIncludedCount++;
1525             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
1526                 "IncrementAutoTargetServices: AutoTargetAWDLIncludedCount %u Record " PRI_S,
1527                 m->AutoTargetAWDLIncludedCount, ARDisplayString(m, rr));
1528         }
1529         else if (mDNSPlatformInterfaceIsAWDL(rr->resrec.InterfaceID))
1530         {
1531             m->AutoTargetAWDLOnlyCount++;
1532             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
1533                 "IncrementAutoTargetServices: AutoTargetAWDLOnlyCount %u Record " PRI_S,
1534                 m->AutoTargetAWDLOnlyCount, ARDisplayString(m, rr));
1535         }
1536         else
1537 #endif
1538         {
1539             m->AutoTargetServices++;
1540             LogRedact(MDNS_LOG_CATEGORY_DEFAULT, MDNS_LOG_INFO,
1541                 "IncrementAutoTargetServices: AutoTargetServices %u Record " PRI_S,
1542                 m->AutoTargetServices, ARDisplayString(m, rr));
1543         }
1544         // If this is the first advertised service and we did not just enable Bonjour above, then
1545         // advertise all the interface records.  If we did enable Bonjour above, the interface records will
1546         // be advertised during the network changed processing scheduled above, so no need
1547         // to do it here.
1548         if (!enablingBonjour) AdvertiseNecessaryInterfaceRecords(m);
1549     }
1550 }
1551 
getKeepaliveRaddr(mDNS * const m,AuthRecord * rr,mDNSAddr * raddr)1552 mDNSlocal void getKeepaliveRaddr(mDNS *const m, AuthRecord *rr, mDNSAddr *raddr)
1553 {
1554     mDNSAddr     laddr = zeroAddr;
1555     mDNSEthAddr  eth = zeroEthAddr;
1556     mDNSIPPort   lport = zeroIPPort;
1557     mDNSIPPort   rport = zeroIPPort;
1558     mDNSu32      timeout = 0;
1559     mDNSu32      seq = 0;
1560     mDNSu32      ack = 0;
1561     mDNSu16      win = 0;
1562 
1563     if (mDNS_KeepaliveRecord(&rr->resrec))
1564     {
1565         mDNS_ExtractKeepaliveInfo(rr, &timeout, &laddr, raddr, &eth, &seq, &ack, &lport, &rport, &win);
1566         if (!timeout || mDNSAddressIsZero(&laddr) || mDNSAddressIsZero(raddr) || mDNSIPPortIsZero(lport) || mDNSIPPortIsZero(rport))
1567         {
1568             LogMsg("getKeepaliveRaddr: not a valid record %s for keepalive %#a:%d %#a:%d", ARDisplayString(m, rr), &laddr, lport.NotAnInteger, raddr, rport.NotAnInteger);
1569             return;
1570         }
1571     }
1572 }
1573 
1574 // Exported so uDNS.c can call this
mDNS_Register_internal(mDNS * const m,AuthRecord * const rr)1575 mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
1576 {
1577     domainname *target = GetRRDomainNameTarget(&rr->resrec);
1578     AuthRecord *r;
1579     AuthRecord **p = &m->ResourceRecords;
1580     AuthRecord **d = &m->DuplicateRecords;
1581 
1582     if ((mDNSs32)rr->resrec.rroriginalttl <= 0)
1583     { LogMsg("mDNS_Register_internal: TTL %X should be 1 - 0x7FFFFFFF %s", rr->resrec.rroriginalttl, ARDisplayString(m, rr)); return(mStatus_BadParamErr); }
1584 
1585     if (!rr->resrec.RecordType)
1586     { LogMsg("mDNS_Register_internal: RecordType must be non-zero %s", ARDisplayString(m, rr)); return(mStatus_BadParamErr); }
1587 
1588     if (m->ShutdownTime)
1589     { LogMsg("mDNS_Register_internal: Shutting down, can't register %s", ARDisplayString(m, rr)); return(mStatus_ServiceNotRunning); }
1590 
1591     if (m->DivertMulticastAdvertisements && !AuthRecord_uDNS(rr))
1592     {
1593         mDNSInterfaceID previousID = rr->resrec.InterfaceID;
1594         if (rr->resrec.InterfaceID == mDNSInterface_Any || rr->resrec.InterfaceID == mDNSInterface_P2P)
1595         {
1596             rr->resrec.InterfaceID = mDNSInterface_LocalOnly;
1597             rr->ARType = AuthRecordLocalOnly;
1598         }
1599         if (rr->resrec.InterfaceID != mDNSInterface_LocalOnly)
1600         {
1601             NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID);
1602             if (intf && !intf->Advertise) { rr->resrec.InterfaceID = mDNSInterface_LocalOnly; rr->ARType = AuthRecordLocalOnly; }
1603         }
1604         if (rr->resrec.InterfaceID != previousID)
1605             LogInfo("mDNS_Register_internal: Diverting record to local-only %s", ARDisplayString(m, rr));
1606     }
1607 
1608     if (RRLocalOnly(rr))
1609     {
1610         if (CheckAuthSameRecord(&m->rrauth, rr))
1611         {
1612             LogMsg("mDNS_Register_internal: ERROR!! Tried to register LocalOnly AuthRecord %p %##s (%s) that's already in the list",
1613                    rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
1614             return(mStatus_AlreadyRegistered);
1615         }
1616     }
1617     else
1618     {
1619         while (*p && *p != rr) p=&(*p)->next;
1620         if (*p)
1621         {
1622             LogMsg("mDNS_Register_internal: ERROR!! Tried to register AuthRecord %p %##s (%s) that's already in the list",
1623                    rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
1624             return(mStatus_AlreadyRegistered);
1625         }
1626     }
1627 
1628     while (*d && *d != rr) d=&(*d)->next;
1629     if (*d)
1630     {
1631         LogMsg("mDNS_Register_internal: ERROR!! Tried to register AuthRecord %p %##s (%s) that's already in the Duplicate list",
1632                rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
1633         return(mStatus_AlreadyRegistered);
1634     }
1635 
1636     if (rr->DependentOn)
1637     {
1638         if (rr->resrec.RecordType == kDNSRecordTypeUnique)
1639             rr->resrec.RecordType =  kDNSRecordTypeVerified;
1640         else if (rr->resrec.RecordType != kDNSRecordTypeKnownUnique)
1641         {
1642             LogMsg("mDNS_Register_internal: ERROR! %##s (%s): rr->DependentOn && RecordType != kDNSRecordTypeUnique or kDNSRecordTypeKnownUnique",
1643                    rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
1644             return(mStatus_Invalid);
1645         }
1646         if (!(rr->DependentOn->resrec.RecordType & (kDNSRecordTypeUnique | kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique)))
1647         {
1648             LogMsg("mDNS_Register_internal: ERROR! %##s (%s): rr->DependentOn->RecordType bad type %X",
1649                    rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->DependentOn->resrec.RecordType);
1650             return(mStatus_Invalid);
1651         }
1652     }
1653 
1654     rr->next = mDNSNULL;
1655 
1656     // Field Group 1: The actual information pertaining to this resource record
1657     // Set up by client prior to call
1658 
1659     // Field Group 2: Persistent metadata for Authoritative Records
1660 //  rr->Additional1       = set to mDNSNULL  in mDNS_SetupResourceRecord; may be overridden by client
1661 //  rr->Additional2       = set to mDNSNULL  in mDNS_SetupResourceRecord; may be overridden by client
1662 //  rr->DependentOn       = set to mDNSNULL  in mDNS_SetupResourceRecord; may be overridden by client
1663 //  rr->RRSet             = set to mDNSNULL  in mDNS_SetupResourceRecord; may be overridden by client
1664 //  rr->Callback          = already set      in mDNS_SetupResourceRecord
1665 //  rr->Context           = already set      in mDNS_SetupResourceRecord
1666 //  rr->RecordType        = already set      in mDNS_SetupResourceRecord
1667 //  rr->HostTarget        = set to mDNSfalse in mDNS_SetupResourceRecord; may be overridden by client
1668 //  rr->AllowRemoteQuery  = set to mDNSfalse in mDNS_SetupResourceRecord; may be overridden by client
1669     // Make sure target is not uninitialized data, or we may crash writing debugging log messages
1670     if (rr->AutoTarget && target) target->c[0] = 0;
1671 
1672     // Field Group 3: Transient state for Authoritative Records
1673     rr->Acknowledged      = mDNSfalse;
1674     rr->ProbeCount        = DefaultProbeCountForRecordType(rr->resrec.RecordType);
1675     rr->ProbeRestartCount = 0;
1676     rr->AnnounceCount     = InitialAnnounceCount;
1677     rr->RequireGoodbye    = mDNSfalse;
1678     rr->AnsweredLocalQ    = mDNSfalse;
1679     rr->IncludeInProbe    = mDNSfalse;
1680     rr->ImmedUnicast      = mDNSfalse;
1681     rr->SendNSECNow       = mDNSNULL;
1682     rr->ImmedAnswer       = mDNSNULL;
1683     rr->ImmedAdditional   = mDNSNULL;
1684     rr->SendRNow          = mDNSNULL;
1685     rr->v4Requester       = zerov4Addr;
1686     rr->v6Requester       = zerov6Addr;
1687     rr->NextResponse      = mDNSNULL;
1688     rr->NR_AnswerTo       = mDNSNULL;
1689     rr->NR_AdditionalTo   = mDNSNULL;
1690     if (!rr->AutoTarget) InitializeLastAPTime(m, rr);
1691 //  rr->LastAPTime        = Set for us in InitializeLastAPTime()
1692 //  rr->LastMCTime        = Set for us in InitializeLastAPTime()
1693 //  rr->LastMCInterface   = Set for us in InitializeLastAPTime()
1694     rr->NewRData          = mDNSNULL;
1695     rr->newrdlength       = 0;
1696     rr->UpdateCallback    = mDNSNULL;
1697     rr->UpdateCredits     = kMaxUpdateCredits;
1698     rr->NextUpdateCredit  = 0;
1699     rr->UpdateBlocked     = 0;
1700 
1701     // For records we're holding as proxy (except reverse-mapping PTR records) two announcements is sufficient
1702     if (rr->WakeUp.HMAC.l[0] && !rr->AddressProxy.type) rr->AnnounceCount = 2;
1703 
1704     // Field Group 4: Transient uDNS state for Authoritative Records
1705     rr->state             = regState_Zero;
1706     rr->uselease          = 0;
1707     rr->expire            = 0;
1708     rr->Private           = 0;
1709     rr->updateid          = zeroID;
1710     rr->updateIntID       = zeroOpaque64;
1711     rr->zone              = rr->resrec.name;
1712     rr->nta               = mDNSNULL;
1713     rr->tcp               = mDNSNULL;
1714     rr->OrigRData         = 0;
1715     rr->OrigRDLen         = 0;
1716     rr->InFlightRData     = 0;
1717     rr->InFlightRDLen     = 0;
1718     rr->QueuedRData       = 0;
1719     rr->QueuedRDLen       = 0;
1720     //mDNSPlatformMemZero(&rr->NATinfo, sizeof(rr->NATinfo));
1721     // We should be recording the actual internal port for this service record here. Once we initiate our NAT mapping
1722     // request we'll subsequently overwrite srv.port with the allocated external NAT port -- potentially multiple
1723     // times with different values if the external NAT port changes during the lifetime of the service registration.
1724     //if (rr->resrec.rrtype == kDNSType_SRV) rr->NATinfo.IntPort = rr->resrec.rdata->u.srv.port;
1725 
1726 //  rr->resrec.interface         = already set in mDNS_SetupResourceRecord
1727 //  rr->resrec.name->c           = MUST be set by client
1728 //  rr->resrec.rrtype            = already set in mDNS_SetupResourceRecord
1729 //  rr->resrec.rrclass           = already set in mDNS_SetupResourceRecord
1730 //  rr->resrec.rroriginalttl     = already set in mDNS_SetupResourceRecord
1731 //  rr->resrec.rdata             = MUST be set by client, unless record type is CNAME or PTR and rr->HostTarget is set
1732 
1733     // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct,
1734     // since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s".
1735     // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here.
1736     if (rr->resrec.rrtype == kDNSType_TXT && rr->resrec.rdlength == 0) { rr->resrec.rdlength = 1; rr->resrec.rdata->u.txt.c[0] = 0; }
1737 
1738     if (rr->AutoTarget)
1739     {
1740         SetTargetToHostName(m, rr); // Also sets rdlength and rdestimate for us, and calls InitializeLastAPTime();
1741 #ifndef UNICAST_DISABLED
1742         // If we have no target record yet, SetTargetToHostName will set rr->state == regState_NoTarget
1743         // 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.
1744         if (rr->state == regState_NoTarget)
1745         {
1746             // Initialize the target so that we don't crash while logging etc.
1747             domainname *tar = GetRRDomainNameTarget(&rr->resrec);
1748             if (tar) tar->c[0] = 0;
1749             LogInfo("mDNS_Register_internal: record %s in NoTarget state", ARDisplayString(m, rr));
1750         }
1751 #endif
1752     }
1753     else
1754     {
1755         rr->resrec.rdlength   = GetRDLength(&rr->resrec, mDNSfalse);
1756         rr->resrec.rdestimate = GetRDLength(&rr->resrec, mDNStrue);
1757     }
1758 
1759     if (!ValidateDomainName(rr->resrec.name))
1760     { LogMsg("Attempt to register record with invalid name: %s", ARDisplayString(m, rr)); return(mStatus_Invalid); }
1761 
1762     // Don't do this until *after* we've set rr->resrec.rdlength
1763     if (!ValidateRData(rr->resrec.rrtype, rr->resrec.rdlength, rr->resrec.rdata))
1764     { LogMsg("Attempt to register record with invalid rdata: %s", ARDisplayString(m, rr)); return(mStatus_Invalid); }
1765 
1766     rr->resrec.namehash   = DomainNameHashValue(rr->resrec.name);
1767     rr->resrec.rdatahash  = target ? DomainNameHashValue(target) : RDataHashValue(&rr->resrec);
1768 
1769     if (RRLocalOnly(rr))
1770     {
1771         // If this is supposed to be unique, make sure we don't have any name conflicts.
1772         // If we found a conflict, we may still want to insert the record in the list but mark it appropriately
1773         // (kDNSRecordTypeDeregistering) so that we deliver RMV events to the application. But this causes more
1774         // complications and not clear whether there are any benefits. See rdar:9304275 for details.
1775         // Hence, just bail out.
1776         // This comment is doesn’t make any sense. -- SC
1777         if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
1778         {
1779             if (CheckAuthRecordConflict(&m->rrauth, rr))
1780             {
1781                 LogInfo("mDNS_Register_internal: Name conflict %s (%p), InterfaceID %p", ARDisplayString(m, rr), rr, rr->resrec.InterfaceID);
1782                 return mStatus_NameConflict;
1783             }
1784         }
1785     }
1786 
1787     // For uDNS records, we don't support duplicate checks at this time.
1788 #ifndef UNICAST_DISABLED
1789     if (AuthRecord_uDNS(rr))
1790     {
1791         if (!m->NewLocalRecords) m->NewLocalRecords = rr;
1792         // When we called SetTargetToHostName, it may have caused mDNS_Register_internal to be re-entered, appending new
1793         // 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.
1794         while (*p) p=&(*p)->next;
1795         *p = rr;
1796         if (rr->resrec.RecordType == kDNSRecordTypeUnique) rr->resrec.RecordType = kDNSRecordTypeVerified;
1797         rr->ProbeCount    = 0;
1798         rr->ProbeRestartCount = 0;
1799         rr->AnnounceCount = 0;
1800         if (rr->state != regState_NoTarget) ActivateUnicastRegistration(m, rr);
1801         return(mStatus_NoError);            // <--- Note: For unicast records, code currently bails out at this point
1802     }
1803 #endif
1804 
1805     // Now that we've finished building our new record, make sure it's not identical to one we already have
1806     if (RRLocalOnly(rr))
1807     {
1808         rr->ProbeCount    = 0;
1809         rr->ProbeRestartCount = 0;
1810         rr->AnnounceCount = 0;
1811         r = CheckAuthIdenticalRecord(&m->rrauth, rr);
1812     }
1813     else
1814     {
1815         for (r = m->ResourceRecords; r; r=r->next)
1816             if (RecordIsLocalDuplicate(r, rr))
1817             {
1818                 if (r->resrec.RecordType == kDNSRecordTypeDeregistering) r->AnnounceCount = 0;
1819                 else break;
1820             }
1821     }
1822 
1823     if (r)
1824     {
1825         LogInfo("mDNS_Register_internal: Adding to duplicate list %s", ARDisplayString(m,rr));
1826         *d = rr;
1827         // If the previous copy of this record is already verified unique,
1828         // then indicate that we should move this record promptly to kDNSRecordTypeUnique state.
1829         // Setting ProbeCount to zero will cause SendQueries() to advance this record to
1830         // kDNSRecordTypeVerified state and call the client callback at the next appropriate time.
1831         if (rr->resrec.RecordType == kDNSRecordTypeUnique && r->resrec.RecordType == kDNSRecordTypeVerified)
1832             rr->ProbeCount = 0;
1833     }
1834     else
1835     {
1836         LogInfo("mDNS_Register_internal: Adding to active record list %s", ARDisplayString(m,rr));
1837         if (RRLocalOnly(rr))
1838         {
1839             AuthGroup *ag;
1840             ag = InsertAuthRecord(m, &m->rrauth, rr);
1841             if (ag && !ag->NewLocalOnlyRecords)
1842             {
1843                 m->NewLocalOnlyRecords = mDNStrue;
1844                 ag->NewLocalOnlyRecords = rr;
1845             }
1846             // No probing for LocalOnly records; acknowledge them right away
1847             if (rr->resrec.RecordType == kDNSRecordTypeUnique) rr->resrec.RecordType = kDNSRecordTypeVerified;
1848             AcknowledgeRecord(m, rr);
1849             return(mStatus_NoError);
1850         }
1851         else
1852         {
1853             if (!m->NewLocalRecords) m->NewLocalRecords = rr;
1854             *p = rr;
1855         }
1856     }
1857 
1858     if (!AuthRecord_uDNS(rr))   // This check is superfluous, given that for unicast records we (currently) bail out above
1859     {
1860         // We have inserted the record in the list. See if we have to advertise the A/AAAA, HINFO, PTR records.
1861         IncrementAutoTargetServices(m, rr);
1862 
1863         // For records that are not going to probe, acknowledge them right away
1864         if (rr->resrec.RecordType != kDNSRecordTypeUnique && rr->resrec.RecordType != kDNSRecordTypeDeregistering)
1865             AcknowledgeRecord(m, rr);
1866 
1867         // Adding a record may affect whether or not we should sleep
1868         mDNS_UpdateAllowSleep(m);
1869     }
1870 
1871     // If this is a non-sleep proxy keepalive record, fetch the MAC address of the remote host.
1872     // This is used by the in-NIC proxy to send the keepalive packets.
1873     if (!rr->WakeUp.HMAC.l[0] && mDNS_KeepaliveRecord(&rr->resrec))
1874     {
1875         mDNSAddr raddr;
1876         // Set the record type to known unique to prevent probing keep alive records.
1877         // Also make sure we do not announce the keepalive records.
1878        rr->resrec.RecordType = kDNSRecordTypeKnownUnique;
1879        rr->AnnounceCount     = 0;
1880        getKeepaliveRaddr(m, rr, &raddr);
1881        // This is an asynchronous call. Once the remote MAC address is available, helper will schedule an
1882        // asynchronous task to update the resource record
1883        mDNSPlatformGetRemoteMacAddr(&raddr);
1884     }
1885 
1886     return(mStatus_NoError);
1887 }
1888 
RecordProbeFailure(mDNS * const m,const AuthRecord * const rr)1889 mDNSlocal void RecordProbeFailure(mDNS *const m, const AuthRecord *const rr)
1890 {
1891     m->ProbeFailTime = m->timenow;
1892     m->NumFailedProbes++;
1893     // If we've had fifteen or more probe failures, rate-limit to one every five seconds.
1894     // If a bunch of hosts have all been configured with the same name, then they'll all
1895     // conflict and run through the same series of names: name-2, name-3, name-4, etc.,
1896     // up to name-10. After that they'll start adding random increments in the range 1-100,
1897     // so they're more likely to branch out in the available namespace and settle on a set of
1898     // unique names quickly. If after five more tries the host is still conflicting, then we
1899     // may have a serious problem, so we start rate-limiting so we don't melt down the network.
1900     if (m->NumFailedProbes >= 15)
1901     {
1902         m->SuppressProbes = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 5);
1903         LogMsg("Excessive name conflicts (%lu) for %##s (%s); rate limiting in effect",
1904                m->NumFailedProbes, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
1905     }
1906 }
1907 
CompleteRDataUpdate(mDNS * const m,AuthRecord * const rr)1908 mDNSlocal void CompleteRDataUpdate(mDNS *const m, AuthRecord *const rr)
1909 {
1910     RData *OldRData = rr->resrec.rdata;
1911     mDNSu16 OldRDLen = rr->resrec.rdlength;
1912     SetNewRData(&rr->resrec, rr->NewRData, rr->newrdlength);    // Update our rdata
1913     rr->NewRData = mDNSNULL;                                    // Clear the NewRData pointer ...
1914     if (rr->UpdateCallback)
1915         rr->UpdateCallback(m, rr, OldRData, OldRDLen);          // ... and let the client know
1916 }
1917 
1918 // Note: mDNS_Deregister_internal can call a user callback, which may change the record list and/or question list.
1919 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
1920 // Exported so uDNS.c can call this
mDNS_Deregister_internal(mDNS * const m,AuthRecord * const rr,mDNS_Dereg_type drt)1921 mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr, mDNS_Dereg_type drt)
1922 {
1923     AuthRecord *r2;
1924     mDNSu8 RecordType = rr->resrec.RecordType;
1925     AuthRecord **p = &m->ResourceRecords;   // Find this record in our list of active records
1926     mDNSBool dupList = mDNSfalse;
1927 
1928     if (RRLocalOnly(rr))
1929     {
1930         AuthGroup *a;
1931         AuthRecord **rp;
1932 
1933         a = AuthGroupForRecord(&m->rrauth, &rr->resrec);
1934         if (!a) return mDNSfalse;
1935         rp = &a->members;
1936         while (*rp && *rp != rr) rp=&(*rp)->next;
1937         p = rp;
1938     }
1939     else
1940     {
1941         while (*p && *p != rr) p=&(*p)->next;
1942     }
1943 
1944     if (*p)
1945     {
1946         // We found our record on the main list. See if there are any duplicates that need special handling.
1947         if (drt == mDNS_Dereg_conflict)     // If this was a conflict, see that all duplicates get the same treatment
1948         {
1949             // Scan for duplicates of rr, and mark them for deregistration at the end of this routine, after we've finished
1950             // deregistering rr. We need to do this scan *before* we give the client the chance to free and reuse the rr memory.
1951             for (r2 = m->DuplicateRecords; r2; r2=r2->next) if (RecordIsLocalDuplicate(r2, rr)) r2->ProbeCount = 0xFF;
1952         }
1953         else
1954         {
1955             // Before we delete the record (and potentially send a goodbye packet)
1956             // first see if we have a record on the duplicate list ready to take over from it.
1957             AuthRecord **d = &m->DuplicateRecords;
1958             while (*d && !RecordIsLocalDuplicate(*d, rr)) d=&(*d)->next;
1959             if (*d)
1960             {
1961                 AuthRecord *dup = *d;
1962                 debugf("mDNS_Register_internal: Duplicate record %p taking over from %p %##s (%s)",
1963                        dup, rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
1964                 *d        = dup->next;      // Cut replacement record from DuplicateRecords list
1965                 if (RRLocalOnly(rr))
1966                 {
1967                     dup->next = mDNSNULL;
1968                     if (!InsertAuthRecord(m, &m->rrauth, dup)) LogMsg("mDNS_Deregister_internal: ERROR!! cannot insert %s", ARDisplayString(m, dup));
1969                 }
1970                 else
1971                 {
1972                     dup->next = rr->next;       // And then...
1973                     rr->next  = dup;            // ... splice it in right after the record we're about to delete
1974                 }
1975                 dup->resrec.RecordType        = rr->resrec.RecordType;
1976                 dup->ProbeCount      = rr->ProbeCount;
1977                 dup->ProbeRestartCount = rr->ProbeRestartCount;
1978                 dup->AnnounceCount   = rr->AnnounceCount;
1979                 dup->RequireGoodbye  = rr->RequireGoodbye;
1980                 dup->AnsweredLocalQ  = rr->AnsweredLocalQ;
1981                 dup->ImmedAnswer     = rr->ImmedAnswer;
1982                 dup->ImmedUnicast    = rr->ImmedUnicast;
1983                 dup->ImmedAdditional = rr->ImmedAdditional;
1984                 dup->v4Requester     = rr->v4Requester;
1985                 dup->v6Requester     = rr->v6Requester;
1986                 dup->ThisAPInterval  = rr->ThisAPInterval;
1987                 dup->LastAPTime      = rr->LastAPTime;
1988                 dup->LastMCTime      = rr->LastMCTime;
1989                 dup->LastMCInterface = rr->LastMCInterface;
1990                 dup->Private         = rr->Private;
1991                 dup->state           = rr->state;
1992                 rr->RequireGoodbye = mDNSfalse;
1993                 rr->AnsweredLocalQ = mDNSfalse;
1994             }
1995         }
1996     }
1997     else
1998     {
1999         // We didn't find our record on the main list; try the DuplicateRecords list instead.
2000         p = &m->DuplicateRecords;
2001         while (*p && *p != rr) p=&(*p)->next;
2002         // If we found our record on the duplicate list, then make sure we don't send a goodbye for it
2003         if (*p)
2004         {
2005             // Duplicate records are not used for sending wakeups or goodbyes. Hence, deregister them
2006             // immediately. When there is a conflict, we deregister all the conflicting duplicate records
2007             // also that have been marked above in this function. In that case, we come here and if we don't
2008             // deregister (unilink from the DuplicateRecords list), we will be recursing infinitely. Hence,
2009             // clear the HMAC which will cause it to deregister. See <rdar://problem/10380988> for
2010             // details.
2011             rr->WakeUp.HMAC    = zeroEthAddr;
2012             rr->RequireGoodbye = mDNSfalse;
2013             rr->resrec.RecordType = kDNSRecordTypeDeregistering;
2014             dupList = mDNStrue;
2015         }
2016         if (*p) debugf("mDNS_Deregister_internal: Deleting DuplicateRecord %p %##s (%s)",
2017                        rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
2018     }
2019 
2020     if (!*p)
2021     {
2022         // No need to log an error message if we already know this is a potentially repeated deregistration
2023         if (drt != mDNS_Dereg_repeat)
2024             LogMsg("mDNS_Deregister_internal: Record %p not found in list %s", rr, ARDisplayString(m,rr));
2025         return(mStatus_BadReferenceErr);
2026     }
2027 
2028     // If this is a shared record and we've announced it at least once,
2029     // we need to retract that announcement before we delete the record
2030 
2031     // If this is a record (including mDNSInterface_LocalOnly records) for which we've given local-only answers then
2032     // it's tempting to just do "AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, QC_rmv)" here, but that would not not be safe.
2033     // The AnswerAllLocalQuestionsWithLocalAuthRecord routine walks the question list invoking client callbacks, using the "m->CurrentQuestion"
2034     // mechanism to cope with the client callback modifying the question list while that's happening.
2035     // However, mDNS_Deregister could have been called from a client callback (e.g. from the domain enumeration callback FoundDomain)
2036     // which means that the "m->CurrentQuestion" mechanism is already in use to protect that list, so we can't use it twice.
2037     // More generally, if we invoke callbacks from within a client callback, then those callbacks could deregister other
2038     // records, thereby invoking yet more callbacks, without limit.
2039     // The solution is to defer delivering the "Remove" events until mDNS_Execute time, just like we do for sending
2040     // actual goodbye packets.
2041 
2042 #ifndef UNICAST_DISABLED
2043     if (AuthRecord_uDNS(rr))
2044     {
2045         if (rr->RequireGoodbye)
2046         {
2047             if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; }
2048             rr->resrec.RecordType    = kDNSRecordTypeDeregistering;
2049             m->LocalRemoveEvents     = mDNStrue;
2050             uDNS_DeregisterRecord(m, rr);
2051             // At this point unconditionally we bail out
2052             // Either uDNS_DeregisterRecord will have completed synchronously, and called CompleteDeregistration,
2053             // which calls us back here with RequireGoodbye set to false, or it will have initiated the deregistration
2054             // process and will complete asynchronously. Either way we don't need to do anything more here.
2055             return(mStatus_NoError);
2056         }
2057         // Sometimes the records don't complete proper deregistration i.e., don't wait for a response
2058         // from the server. In that case, if the records have been part of a group update, clear the
2059         // state here.
2060         rr->updateid = zeroID;
2061 
2062         // We defer cleaning up NAT state only after sending goodbyes. This is important because
2063         // RecordRegistrationGotZoneData guards against creating NAT state if clientContext is non-NULL.
2064         // This happens today when we turn on/off interface where we get multiple network transitions
2065         // and RestartRecordGetZoneData triggers re-registration of the resource records even though
2066         // they may be in Registered state which causes NAT information to be setup multiple times. Defering
2067         // the cleanup here keeps clientContext non-NULL and hence prevents that. Note that cleaning up
2068         // NAT state here takes care of the case where we did not send goodbyes at all.
2069         if (rr->NATinfo.clientContext)
2070         {
2071             mDNS_StopNATOperation_internal(m, &rr->NATinfo);
2072             rr->NATinfo.clientContext = mDNSNULL;
2073         }
2074         if (rr->nta) { CancelGetZoneData(m, rr->nta); rr->nta = mDNSNULL; }
2075         if (rr->tcp) { DisposeTCPConn(rr->tcp);       rr->tcp = mDNSNULL; }
2076     }
2077 #endif // UNICAST_DISABLED
2078 
2079     if      (RecordType == kDNSRecordTypeUnregistered)
2080         LogMsg("mDNS_Deregister_internal: %s already marked kDNSRecordTypeUnregistered", ARDisplayString(m, rr));
2081     else if (RecordType == kDNSRecordTypeDeregistering)
2082     {
2083         LogMsg("mDNS_Deregister_internal: %s already marked kDNSRecordTypeDeregistering", ARDisplayString(m, rr));
2084         return(mStatus_BadReferenceErr);
2085     }
2086 
2087     if (rr->WakeUp.HMAC.l[0] ||
2088         (((RecordType == kDNSRecordTypeShared) || (rr->ARType == AuthRecordLocalOnly)) &&
2089         (rr->RequireGoodbye || rr->AnsweredLocalQ)))
2090     {
2091         verbosedebugf("mDNS_Deregister_internal: Starting deregistration for %s", ARDisplayString(m, rr));
2092         rr->resrec.RecordType    = kDNSRecordTypeDeregistering;
2093         rr->resrec.rroriginalttl = 0;
2094         rr->AnnounceCount        = rr->WakeUp.HMAC.l[0] ? WakeupCount : (drt == mDNS_Dereg_rapid) ? 1 : GoodbyeCount;
2095         rr->ThisAPInterval       = mDNSPlatformOneSecond * 2;
2096         rr->LastAPTime           = m->timenow - rr->ThisAPInterval;
2097         m->LocalRemoveEvents     = mDNStrue;
2098         if (m->NextScheduledResponse - (m->timenow + mDNSPlatformOneSecond/10) >= 0)
2099             m->NextScheduledResponse = (m->timenow + mDNSPlatformOneSecond/10);
2100     }
2101     else
2102     {
2103         if (!dupList && RRLocalOnly(rr))
2104         {
2105             AuthGroup *ag = RemoveAuthRecord(m, &m->rrauth, rr);
2106             if (ag->NewLocalOnlyRecords == rr) ag->NewLocalOnlyRecords = rr->next;
2107         }
2108         else
2109         {
2110             *p = rr->next;                  // Cut this record from the list
2111             if (m->NewLocalRecords == rr) m->NewLocalRecords = rr->next;
2112             DecrementAutoTargetServices(m, rr);
2113         }
2114         // If someone is about to look at this, bump the pointer forward
2115         if (m->CurrentRecord   == rr) m->CurrentRecord   = rr->next;
2116         rr->next = mDNSNULL;
2117 
2118         verbosedebugf("mDNS_Deregister_internal: Deleting record for %s", ARDisplayString(m, rr));
2119         rr->resrec.RecordType = kDNSRecordTypeUnregistered;
2120 
2121         if ((drt == mDNS_Dereg_conflict || drt == mDNS_Dereg_repeat) && RecordType == kDNSRecordTypeShared)
2122             debugf("mDNS_Deregister_internal: Cannot have a conflict on a shared record! %##s (%s)",
2123                    rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
2124 
2125         // If we have an update queued up which never executed, give the client a chance to free that memory
2126         if (rr->NewRData) CompleteRDataUpdate(m, rr);   // Update our rdata, clear the NewRData pointer, and return memory to the client
2127 
2128 
2129         // CAUTION: MUST NOT do anything more with rr after calling rr->Callback(), because the client's callback function
2130         // is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc.
2131         // In this case the likely client action to the mStatus_MemFree message is to free the memory,
2132         // so any attempt to touch rr after this is likely to lead to a crash.
2133         if (drt != mDNS_Dereg_conflict)
2134         {
2135             mDNS_DropLockBeforeCallback();      // Allow client to legally make mDNS API calls from the callback
2136             LogInfo("mDNS_Deregister_internal: callback with mStatus_MemFree for %s", ARDisplayString(m, rr));
2137             if (rr->RecordCallback)
2138                 rr->RecordCallback(m, rr, mStatus_MemFree);         // MUST NOT touch rr after this
2139             mDNS_ReclaimLockAfterCallback();    // Decrement mDNS_reentrancy to block mDNS API calls again
2140         }
2141         else
2142         {
2143             RecordProbeFailure(m, rr);
2144             mDNS_DropLockBeforeCallback();      // Allow client to legally make mDNS API calls from the callback
2145             if (rr->RecordCallback)
2146                 rr->RecordCallback(m, rr, mStatus_NameConflict);    // MUST NOT touch rr after this
2147             mDNS_ReclaimLockAfterCallback();    // Decrement mDNS_reentrancy to block mDNS API calls again
2148             // Now that we've finished deregistering rr, check our DuplicateRecords list for any that we marked previously.
2149             // Note that with all the client callbacks going on, by the time we get here all the
2150             // records we marked may have been explicitly deregistered by the client anyway.
2151             r2 = m->DuplicateRecords;
2152             while (r2)
2153             {
2154                 if (r2->ProbeCount != 0xFF)
2155                 {
2156                     r2 = r2->next;
2157                 }
2158                 else
2159                 {
2160 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
2161                     // See if this record was also registered with any D2D plugins.
2162                     D2D_stop_advertising_record(r2);
2163 #endif
2164                     mDNS_Deregister_internal(m, r2, mDNS_Dereg_conflict);
2165                     // As this is a duplicate record, it will be unlinked from the list
2166                     // immediately
2167                     r2 = m->DuplicateRecords;
2168                 }
2169             }
2170         }
2171     }
2172     mDNS_UpdateAllowSleep(m);
2173     return(mStatus_NoError);
2174 }
2175 
2176 // ***************************************************************************
2177 #if COMPILER_LIKES_PRAGMA_MARK
2178 #pragma mark -
2179 #pragma mark - Packet Sending Functions
2180 #endif
2181 
AddRecordToResponseList(AuthRecord *** nrpp,AuthRecord * rr,AuthRecord * add)2182 mDNSlocal void AddRecordToResponseList(AuthRecord ***nrpp, AuthRecord *rr, AuthRecord *add)
2183 {
2184     if (rr->NextResponse == mDNSNULL && *nrpp != &rr->NextResponse)
2185     {
2186         **nrpp = rr;
2187         // NR_AdditionalTo must point to a record with NR_AnswerTo set (and not NR_AdditionalTo)
2188         // If 'add' does not meet this requirement, then follow its NR_AdditionalTo pointer to a record that does
2189         // The referenced record will definitely be acceptable (by recursive application of this rule)
2190         if (add && add->NR_AdditionalTo) add = add->NR_AdditionalTo;
2191         rr->NR_AdditionalTo = add;
2192         *nrpp = &rr->NextResponse;
2193     }
2194     debugf("AddRecordToResponseList: %##s (%s) already in list", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
2195 }
2196 
AddRRSetAdditionalsToResponseList(mDNS * const m,AuthRecord *** nrpp,AuthRecord * rr,AuthRecord * additional,const mDNSInterfaceID InterfaceID)2197 mDNSlocal void AddRRSetAdditionalsToResponseList(mDNS *const m, AuthRecord ***nrpp, AuthRecord *rr, AuthRecord *additional, const mDNSInterfaceID InterfaceID)
2198 {
2199     AuthRecord *rr2;
2200     if (additional->resrec.RecordType & kDNSRecordTypeUniqueMask)
2201     {
2202         for (rr2 = m->ResourceRecords; rr2; rr2 = rr2->next)
2203         {
2204             if ((rr2->resrec.namehash == additional->resrec.namehash) &&
2205                 (rr2->resrec.rrtype   == additional->resrec.rrtype) &&
2206                 (rr2 != additional) &&
2207                 (rr2->resrec.RecordType & kDNSRecordTypeUniqueMask) &&
2208                 (rr2->resrec.rrclass  == additional->resrec.rrclass) &&
2209                 ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) &&
2210                 SameDomainName(rr2->resrec.name, additional->resrec.name))
2211             {
2212                 AddRecordToResponseList(nrpp, rr2, rr);
2213             }
2214         }
2215     }
2216 }
2217 
AddAdditionalsToResponseList(mDNS * const m,AuthRecord * ResponseRecords,AuthRecord *** nrpp,const mDNSInterfaceID InterfaceID)2218 mDNSlocal void AddAdditionalsToResponseList(mDNS *const m, AuthRecord *ResponseRecords, AuthRecord ***nrpp, const mDNSInterfaceID InterfaceID)
2219 {
2220     AuthRecord  *rr, *rr2;
2221     for (rr=ResponseRecords; rr; rr=rr->NextResponse)           // For each record we plan to put
2222     {
2223         // (Note: This is an "if", not a "while". If we add a record, we'll find it again
2224         // later in the "for" loop, and we will follow further "additional" links then.)
2225         if (rr->Additional1 && ResourceRecordIsValidInterfaceAnswer(rr->Additional1, InterfaceID))
2226         {
2227             AddRecordToResponseList(nrpp, rr->Additional1, rr);
2228             AddRRSetAdditionalsToResponseList(m, nrpp, rr, rr->Additional1, InterfaceID);
2229         }
2230 
2231         if (rr->Additional2 && ResourceRecordIsValidInterfaceAnswer(rr->Additional2, InterfaceID))
2232         {
2233             AddRecordToResponseList(nrpp, rr->Additional2, rr);
2234             AddRRSetAdditionalsToResponseList(m, nrpp, rr, rr->Additional2, InterfaceID);
2235         }
2236 
2237         // For SRV records, automatically add the Address record(s) for the target host
2238         if (rr->resrec.rrtype == kDNSType_SRV)
2239         {
2240             for (rr2=m->ResourceRecords; rr2; rr2=rr2->next)                    // Scan list of resource records
2241                 if (RRTypeIsAddressType(rr2->resrec.rrtype) &&                  // For all address records (A/AAAA) ...
2242                     ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) &&   // ... which are valid for answer ...
2243                     rr->resrec.rdatahash == rr2->resrec.namehash &&         // ... whose name is the name of the SRV target
2244                     SameDomainName(&rr->resrec.rdata->u.srv.target, rr2->resrec.name))
2245                     AddRecordToResponseList(nrpp, rr2, rr);
2246         }
2247         else if (RRTypeIsAddressType(rr->resrec.rrtype))    // For A or AAAA, put counterpart as additional
2248         {
2249             for (rr2=m->ResourceRecords; rr2; rr2=rr2->next)                    // Scan list of resource records
2250                 if (RRTypeIsAddressType(rr2->resrec.rrtype) &&                  // For all address records (A/AAAA) ...
2251                     ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) &&   // ... which are valid for answer ...
2252                     rr->resrec.namehash == rr2->resrec.namehash &&              // ... and have the same name
2253                     SameDomainName(rr->resrec.name, rr2->resrec.name))
2254                     AddRecordToResponseList(nrpp, rr2, rr);
2255         }
2256         else if (rr->resrec.rrtype == kDNSType_PTR)         // For service PTR, see if we want to add DeviceInfo record
2257         {
2258             if (ResourceRecordIsValidInterfaceAnswer(&m->DeviceInfo, InterfaceID) &&
2259                 SameDomainLabel(rr->resrec.rdata->u.name.c, m->DeviceInfo.resrec.name->c))
2260                 AddRecordToResponseList(nrpp, &m->DeviceInfo, rr);
2261         }
2262     }
2263 }
2264 
SendDelayedUnicastResponse(mDNS * const m,const mDNSAddr * const dest,const mDNSInterfaceID InterfaceID)2265 mDNSlocal void SendDelayedUnicastResponse(mDNS *const m, const mDNSAddr *const dest, const mDNSInterfaceID InterfaceID)
2266 {
2267     AuthRecord *rr;
2268     AuthRecord  *ResponseRecords = mDNSNULL;
2269     AuthRecord **nrp             = &ResponseRecords;
2270     NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID);
2271 
2272     // Make a list of all our records that need to be unicast to this destination
2273     for (rr = m->ResourceRecords; rr; rr=rr->next)
2274     {
2275         // If we find we can no longer unicast this answer, clear ImmedUnicast
2276         if (rr->ImmedAnswer == mDNSInterfaceMark               ||
2277             mDNSSameIPv4Address(rr->v4Requester, onesIPv4Addr) ||
2278             mDNSSameIPv6Address(rr->v6Requester, onesIPv6Addr)  )
2279             rr->ImmedUnicast = mDNSfalse;
2280 
2281         if (rr->ImmedUnicast && rr->ImmedAnswer == InterfaceID)
2282         {
2283             if ((dest->type == mDNSAddrType_IPv4 && mDNSSameIPv4Address(rr->v4Requester, dest->ip.v4)) ||
2284                 (dest->type == mDNSAddrType_IPv6 && mDNSSameIPv6Address(rr->v6Requester, dest->ip.v6)))
2285             {
2286                 rr->ImmedAnswer  = mDNSNULL;                // Clear the state fields
2287                 rr->ImmedUnicast = mDNSfalse;
2288                 rr->v4Requester  = zerov4Addr;
2289                 rr->v6Requester  = zerov6Addr;
2290 
2291                 // Only sent records registered for P2P over P2P interfaces
2292                 if (intf && !mDNSPlatformValidRecordForInterface(rr, intf->InterfaceID))
2293                 {
2294                     continue;
2295                 }
2296 
2297                 if (rr->NextResponse == mDNSNULL && nrp != &rr->NextResponse)   // rr->NR_AnswerTo
2298                 {
2299                     rr->NR_AnswerTo = NR_AnswerMulticast;
2300                     *nrp = rr;
2301                     nrp = &rr->NextResponse;
2302                 }
2303             }
2304         }
2305     }
2306 
2307     AddAdditionalsToResponseList(m, ResponseRecords, &nrp, InterfaceID);
2308 
2309     while (ResponseRecords)
2310     {
2311         mDNSu8 *responseptr = m->omsg.data;
2312         mDNSu8 *newptr;
2313         InitializeDNSMessage(&m->omsg.h, zeroID, ResponseFlags);
2314 
2315         // Put answers in the packet
2316         while (ResponseRecords && ResponseRecords->NR_AnswerTo)
2317         {
2318             rr = ResponseRecords;
2319             if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
2320                 rr->resrec.rrclass |= kDNSClass_UniqueRRSet;        // Temporarily set the cache flush bit so PutResourceRecord will set it
2321 
2322             newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAnswers, &rr->resrec);
2323 
2324             rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;           // Make sure to clear cache flush bit back to normal state
2325             if (!newptr && m->omsg.h.numAnswers)
2326             {
2327                 break; // If packet full, send it now
2328             }
2329             if (newptr) responseptr = newptr;
2330             ResponseRecords = rr->NextResponse;
2331             rr->NextResponse    = mDNSNULL;
2332             rr->NR_AnswerTo     = mDNSNULL;
2333             rr->NR_AdditionalTo = mDNSNULL;
2334             rr->RequireGoodbye  = mDNStrue;
2335         }
2336 
2337         // Add additionals, if there's space
2338         while (ResponseRecords && !ResponseRecords->NR_AnswerTo)
2339         {
2340             rr = ResponseRecords;
2341             if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
2342                 rr->resrec.rrclass |= kDNSClass_UniqueRRSet;        // Temporarily set the cache flush bit so PutResourceRecord will set it
2343             newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAdditionals, &rr->resrec);
2344             rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;           // Make sure to clear cache flush bit back to normal state
2345 
2346             if (newptr) responseptr = newptr;
2347             if (newptr && m->omsg.h.numAnswers) rr->RequireGoodbye = mDNStrue;
2348             else if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask) rr->ImmedAnswer = mDNSInterfaceMark;
2349             ResponseRecords = rr->NextResponse;
2350             rr->NextResponse    = mDNSNULL;
2351             rr->NR_AnswerTo     = mDNSNULL;
2352             rr->NR_AdditionalTo = mDNSNULL;
2353         }
2354 
2355         if (m->omsg.h.numAnswers)
2356             mDNSSendDNSMessage(m, &m->omsg, responseptr, InterfaceID, mDNSNULL, mDNSNULL, dest, MulticastDNSPort, mDNSNULL, mDNSfalse);
2357     }
2358 }
2359 
2360 // CompleteDeregistration guarantees that on exit the record will have been cut from the m->ResourceRecords list
2361 // and the client's mStatus_MemFree callback will have been invoked
CompleteDeregistration(mDNS * const m,AuthRecord * rr)2362 mDNSexport void CompleteDeregistration(mDNS *const m, AuthRecord *rr)
2363 {
2364     LogInfo("CompleteDeregistration: called for Resource record %s", ARDisplayString(m, rr));
2365     // Clearing rr->RequireGoodbye signals mDNS_Deregister_internal() that
2366     // it should go ahead and immediately dispose of this registration
2367     rr->resrec.RecordType = kDNSRecordTypeShared;
2368     rr->RequireGoodbye    = mDNSfalse;
2369     rr->WakeUp.HMAC       = zeroEthAddr;
2370     if (rr->AnsweredLocalQ) { AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, QC_rmv); rr->AnsweredLocalQ = mDNSfalse; }
2371     mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);     // Don't touch rr after this
2372 }
2373 
2374 // DiscardDeregistrations is used on shutdown and sleep to discard (forcibly and immediately)
2375 // any deregistering records that remain in the m->ResourceRecords list.
2376 // DiscardDeregistrations calls mDNS_Deregister_internal which can call a user callback,
2377 // which may change the record list and/or question list.
2378 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
DiscardDeregistrations(mDNS * const m)2379 mDNSlocal void DiscardDeregistrations(mDNS *const m)
2380 {
2381     if (m->CurrentRecord)
2382         LogMsg("DiscardDeregistrations ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
2383     m->CurrentRecord = m->ResourceRecords;
2384 
2385     while (m->CurrentRecord)
2386     {
2387         AuthRecord *rr = m->CurrentRecord;
2388         if (!AuthRecord_uDNS(rr) && rr->resrec.RecordType == kDNSRecordTypeDeregistering)
2389             CompleteDeregistration(m, rr);      // Don't touch rr after this
2390         else
2391             m->CurrentRecord = rr->next;
2392     }
2393 }
2394 
GetLabelDecimalValue(const mDNSu8 * const src,mDNSu8 * dst)2395 mDNSlocal mStatus GetLabelDecimalValue(const mDNSu8 *const src, mDNSu8 *dst)
2396 {
2397     int i, val = 0;
2398     if (src[0] < 1 || src[0] > 3) return(mStatus_Invalid);
2399     for (i=1; i<=src[0]; i++)
2400     {
2401         if (src[i] < '0' || src[i] > '9') return(mStatus_Invalid);
2402         val = val * 10 + src[i] - '0';
2403     }
2404     if (val > 255) return(mStatus_Invalid);
2405     *dst = (mDNSu8)val;
2406     return(mStatus_NoError);
2407 }
2408 
GetIPv4FromName(mDNSAddr * const a,const domainname * const name)2409 mDNSlocal mStatus GetIPv4FromName(mDNSAddr *const a, const domainname *const name)
2410 {
2411     int skip = CountLabels(name) - 6;
2412     if (skip < 0) { LogMsg("GetIPFromName: Need six labels in IPv4 reverse mapping name %##s", name); return mStatus_Invalid; }
2413     if (GetLabelDecimalValue(SkipLeadingLabels(name, skip+3)->c, &a->ip.v4.b[0]) ||
2414         GetLabelDecimalValue(SkipLeadingLabels(name, skip+2)->c, &a->ip.v4.b[1]) ||
2415         GetLabelDecimalValue(SkipLeadingLabels(name, skip+1)->c, &a->ip.v4.b[2]) ||
2416         GetLabelDecimalValue(SkipLeadingLabels(name, skip+0)->c, &a->ip.v4.b[3])) return mStatus_Invalid;
2417     a->type = mDNSAddrType_IPv4;
2418     return(mStatus_NoError);
2419 }
2420 
2421 #define HexVal(X) ( ((X) >= '0' && (X) <= '9') ? ((X) - '0'     ) :   \
2422                     ((X) >= 'A' && (X) <= 'F') ? ((X) - 'A' + 10) :   \
2423                     ((X) >= 'a' && (X) <= 'f') ? ((X) - 'a' + 10) : -1)
2424 
GetIPv6FromName(mDNSAddr * const a,const domainname * const name)2425 mDNSlocal mStatus GetIPv6FromName(mDNSAddr *const a, const domainname *const name)
2426 {
2427     int i, h, l;
2428     const domainname *n;
2429