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