<rdar://problem/6930335> Sleep Proxy: SPS needs to wake all clients before shutting...
[people/sha0/mDNSResponder.git] / mDNSCore / mDNS.c
1 /* -*- Mode: C; tab-width: 4 -*-
2  *
3  * Copyright (c) 2002-2006 Apple Computer, Inc. All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  * 
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  * 
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * This code is completely 100% portable C. It does not depend on any external header files
18  * from outside the mDNS project -- all the types it expects to find are defined right here.
19  * 
20  * The previous point is very important: This file does not depend on any external
21  * header files. It should compile on *any* platform that has a C compiler, without
22  * making *any* assumptions about availability of so-called "standard" C functions,
23  * routines, or types (which may or may not be present on any given platform).
24
25  * Formatting notes:
26  * This code follows the "Whitesmiths style" C indentation rules. Plenty of discussion
27  * on C indentation can be found on the web, such as <http://www.kafejo.com/komp/1tbs.htm>,
28  * but for the sake of brevity here I will say just this: Curly braces are not syntactially
29  * part of an "if" statement; they are the beginning and ending markers of a compound statement;
30  * therefore common sense dictates that if they are part of a compound statement then they
31  * should be indented to the same level as everything else in that compound statement.
32  * Indenting curly braces at the same level as the "if" implies that curly braces are
33  * part of the "if", which is false. (This is as misleading as people who write "char* x,y;"
34  * thinking that variables x and y are both of type "char*" -- and anyone who doesn't
35  * understand why variable y is not of type "char*" just proves the point that poor code
36  * layout leads people to unfortunate misunderstandings about how the C language really works.)
37  */
38
39 #include "DNSCommon.h"                  // Defines general DNS untility routines
40 #include "uDNS.h"                                               // Defines entry points into unicast-specific routines
41
42 // Disable certain benign warnings with Microsoft compilers
43 #if(defined(_MSC_VER))
44         // Disable "conditional expression is constant" warning for debug macros.
45         // Otherwise, this generates warnings for the perfectly natural construct "while(1)"
46         // If someone knows a variant way of writing "while(1)" that doesn't generate warning messages, please let us know
47         #pragma warning(disable:4127)
48         
49         // Disable "assignment within conditional expression".
50         // Other compilers understand the convention that if you place the assignment expression within an extra pair
51         // of parentheses, this signals to the compiler that you really intended an assignment and no warning is necessary.
52         // The Microsoft compiler doesn't understand this convention, so in the absense of any other way to signal
53         // to the compiler that the assignment is intentional, we have to just turn this warning off completely.
54         #pragma warning(disable:4706)
55 #endif
56
57 // Forward declarations
58 mDNSlocal void BeginSleepProcessing(mDNS *const m);
59 mDNSlocal void RetrySPSRegistrations(mDNS *const m);
60 mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password);
61
62 // ***************************************************************************
63 #if COMPILER_LIKES_PRAGMA_MARK
64 #pragma mark - Program Constants
65 #endif
66
67 #define NO_HINFO 1
68
69
70 // Any records bigger than this are considered 'large' records
71 #define SmallRecordLimit 1024
72
73 #define kMaxUpdateCredits 10
74 #define kUpdateCreditRefreshInterval (mDNSPlatformOneSecond * 6)
75
76 mDNSexport const char *const mDNS_DomainTypeNames[] =
77         {
78          "b._dns-sd._udp.",             // Browse
79         "db._dns-sd._udp.",             // Default Browse
80         "lb._dns-sd._udp.",             // Automatic Browse
81          "r._dns-sd._udp.",             // Registration
82         "dr._dns-sd._udp."              // Default Registration
83         };
84
85 #ifdef UNICAST_DISABLED
86 #define uDNS_IsActiveQuery(q, u) mDNSfalse
87 #endif
88
89 // ***************************************************************************
90 #if COMPILER_LIKES_PRAGMA_MARK
91 #pragma mark -
92 #pragma mark - General Utility Functions
93 #endif
94
95 #define ActiveQuestion(Q) ((Q)->ThisQInterval > 0 && !(Q)->DuplicateOf)
96 #define TimeToSendThisQuestion(Q,time) (ActiveQuestion(Q) && (time) - ((Q)->LastQTime + (Q)->ThisQInterval) >= 0)
97
98 mDNSexport void SetNextQueryTime(mDNS *const m, const DNSQuestion *const q)
99         {
100         if (m->mDNS_busy != m->mDNS_reentrancy+1)
101                 LogMsg("SetNextQueryTime: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
102
103 #if ForceAlerts
104         if (m->mDNS_busy != m->mDNS_reentrancy+1) *(long*)0 = 0;
105 #endif
106
107         if (ActiveQuestion(q))
108                 {
109                 mDNSs32 sendtime = q->LastQTime + q->ThisQInterval;
110
111                 // Don't allow sendtime to be earlier than SuppressStdPort53Queries
112                 if (!mDNSOpaque16IsZero(q->TargetQID) && !q->LongLived && m->SuppressStdPort53Queries && (sendtime - m->SuppressStdPort53Queries < 0))
113                         sendtime = m->SuppressStdPort53Queries;
114
115                 if (m->NextScheduledQuery - sendtime > 0)
116                         m->NextScheduledQuery = sendtime;
117                 }
118         }
119
120 mDNSexport CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name)
121         {
122         CacheGroup *cg;
123         for (cg = m->rrcache_hash[slot]; cg; cg=cg->next)
124                 if (cg->namehash == namehash && SameDomainName(cg->name, name))
125                         break;
126         return(cg);
127         }
128
129 mDNSlocal CacheGroup *CacheGroupForRecord(const mDNS *const m, const mDNSu32 slot, const ResourceRecord *const rr)
130         {
131         return(CacheGroupForName(m, slot, rr->namehash, rr->name));
132         }
133
134 mDNSlocal mDNSBool AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr)
135         {
136         NetworkInterfaceInfo *intf;
137
138         if (addr->type == mDNSAddrType_IPv4)
139                 {
140                 // Normally we resist touching the NotAnInteger fields, but here we're doing tricky bitwise masking so we make an exception
141                 if (mDNSv4AddressIsLinkLocal(&addr->ip.v4)) return(mDNStrue);
142                 for (intf = m->HostInterfaces; intf; intf = intf->next)
143                         if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID && intf->McastTxRx)
144                                 if (((intf->ip.ip.v4.NotAnInteger ^ addr->ip.v4.NotAnInteger) & intf->mask.ip.v4.NotAnInteger) == 0)
145                                         return(mDNStrue);
146                 }
147
148         if (addr->type == mDNSAddrType_IPv6)
149                 {
150                 if (mDNSv6AddressIsLinkLocal(&addr->ip.v4)) return(mDNStrue);
151                 for (intf = m->HostInterfaces; intf; intf = intf->next)
152                         if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID && intf->McastTxRx)
153                                 if ((((intf->ip.ip.v6.l[0] ^ addr->ip.v6.l[0]) & intf->mask.ip.v6.l[0]) == 0) &&
154                                         (((intf->ip.ip.v6.l[1] ^ addr->ip.v6.l[1]) & intf->mask.ip.v6.l[1]) == 0) &&
155                                         (((intf->ip.ip.v6.l[2] ^ addr->ip.v6.l[2]) & intf->mask.ip.v6.l[2]) == 0) &&
156                                         (((intf->ip.ip.v6.l[3] ^ addr->ip.v6.l[3]) & intf->mask.ip.v6.l[3]) == 0))
157                                                 return(mDNStrue);
158                 }
159
160         return(mDNSfalse);
161         }
162
163 mDNSlocal NetworkInterfaceInfo *FirstInterfaceForID(mDNS *const m, const mDNSInterfaceID InterfaceID)
164         {
165         NetworkInterfaceInfo *intf = m->HostInterfaces;
166         while (intf && intf->InterfaceID != InterfaceID) intf = intf->next;
167         return(intf);
168         }
169
170 mDNSexport char *InterfaceNameForID(mDNS *const m, const mDNSInterfaceID InterfaceID)
171         {
172         NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID);
173         return(intf ? intf->ifname : mDNSNULL);
174         }
175
176 // For a single given DNSQuestion, deliver an add/remove result for the single given AuthRecord
177 // Used by AnswerAllLocalQuestionsWithLocalAuthRecord() and AnswerNewLocalOnlyQuestion()
178 mDNSlocal void AnswerLocalQuestionWithLocalAuthRecord(mDNS *const m, DNSQuestion *q, AuthRecord *rr, QC_result AddRecord)
179         {
180         // Indicate that we've given at least one positive answer for this record, so we should be prepared to send a goodbye for it
181         if (AddRecord) rr->AnsweredLocalQ = mDNStrue;
182         mDNS_DropLockBeforeCallback();          // Allow client to legally make mDNS API calls from the callback
183         if (q->QuestionCallback && !q->NoAnswer)
184                 {
185                 q->CurrentAnswers += AddRecord ? 1 : -1;
186                 q->QuestionCallback(m, q, &rr->resrec, AddRecord);
187                 }
188         mDNS_ReclaimLockAfterCallback();        // Decrement mDNS_reentrancy to block mDNS API calls again
189         }
190
191 // When a new local AuthRecord is created or deleted, AnswerAllLocalQuestionsWithLocalAuthRecord() runs though
192 // all our local questions (both LocalOnlyQuestions and mDNSInterface_Any questions) delivering answers to each,
193 // stopping if it reaches a NewLocalOnlyQuestion -- brand-new questions are handled by AnswerNewLocalOnlyQuestion().
194 // If the AuthRecord is marked mDNSInterface_LocalOnly, then we also deliver it to any other questions we have using mDNSInterface_Any.
195 // Used by AnswerForNewLocalRecords() and mDNS_Deregister_internal()
196 mDNSlocal void AnswerAllLocalQuestionsWithLocalAuthRecord(mDNS *const m, AuthRecord *rr, QC_result AddRecord)
197         {
198         if (m->CurrentQuestion)
199                 LogMsg("AnswerAllLocalQuestionsWithLocalAuthRecord ERROR m->CurrentQuestion already set: %##s (%s)",
200                         m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
201
202         m->CurrentQuestion = m->LocalOnlyQuestions;
203         while (m->CurrentQuestion && m->CurrentQuestion != m->NewLocalOnlyQuestions)
204                 {
205                 DNSQuestion *q = m->CurrentQuestion;
206                 m->CurrentQuestion = q->next;
207                 if (ResourceRecordAnswersQuestion(&rr->resrec, q))
208                         AnswerLocalQuestionWithLocalAuthRecord(m, q, rr, AddRecord);                    // MUST NOT dereference q again
209                 }
210
211         // If this AuthRecord is marked LocalOnly, then we want to deliver it to all local 'mDNSInterface_Any' questions
212         if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly)
213                 {
214                 m->CurrentQuestion = m->Questions;
215                 while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
216                         {
217                         DNSQuestion *q = m->CurrentQuestion;
218                         m->CurrentQuestion = q->next;
219                         if (ResourceRecordAnswersQuestion(&rr->resrec, q))
220                                 AnswerLocalQuestionWithLocalAuthRecord(m, q, rr, AddRecord);            // MUST NOT dereference q again
221                         }
222                 }
223
224         m->CurrentQuestion = mDNSNULL;
225         }
226
227 // ***************************************************************************
228 #if COMPILER_LIKES_PRAGMA_MARK
229 #pragma mark -
230 #pragma mark - Resource Record Utility Functions
231 #endif
232
233 #define RRTypeIsAddressType(T) ((T) == kDNSType_A || (T) == kDNSType_AAAA)
234
235 #define ResourceRecordIsValidAnswer(RR) ( ((RR)->             resrec.RecordType & kDNSRecordTypeActiveMask)  && \
236                 ((RR)->Additional1 == mDNSNULL || ((RR)->Additional1->resrec.RecordType & kDNSRecordTypeActiveMask)) && \
237                 ((RR)->Additional2 == mDNSNULL || ((RR)->Additional2->resrec.RecordType & kDNSRecordTypeActiveMask)) && \
238                 ((RR)->DependentOn == mDNSNULL || ((RR)->DependentOn->resrec.RecordType & kDNSRecordTypeActiveMask))  )
239
240 #define ResourceRecordIsValidInterfaceAnswer(RR, INTID) \
241         (ResourceRecordIsValidAnswer(RR) && \
242         ((RR)->resrec.InterfaceID == mDNSInterface_Any || (RR)->resrec.InterfaceID == (INTID)))
243
244 #define DefaultProbeCountForTypeUnique ((mDNSu8)3)
245 #define DefaultProbeCountForRecordType(X)      ((X) == kDNSRecordTypeUnique ? DefaultProbeCountForTypeUnique : (mDNSu8)0)
246
247 #define InitialAnnounceCount ((mDNSu8)8)
248
249 // Note that the announce intervals use exponential backoff, doubling each time. The probe intervals do not.
250 // This means that because the announce interval is doubled after sending the first packet, the first
251 // observed on-the-wire inter-packet interval between announcements is actually one second.
252 // The half-second value here may be thought of as a conceptual (non-existent) half-second delay *before* the first packet is sent.
253 #define DefaultProbeIntervalForTypeUnique (mDNSPlatformOneSecond/4)
254 #define DefaultAnnounceIntervalForTypeShared (mDNSPlatformOneSecond/2)
255 #define DefaultAnnounceIntervalForTypeUnique (mDNSPlatformOneSecond/2)
256
257 #define DefaultAPIntervalForRecordType(X)  ((X) & (kDNSRecordTypeAdvisory | kDNSRecordTypeShared     ) ? DefaultAnnounceIntervalForTypeShared : \
258                                                                                         (X) & (kDNSRecordTypeUnique                              ) ? DefaultProbeIntervalForTypeUnique    : \
259                                                                                         (X) & (kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique) ? DefaultAnnounceIntervalForTypeUnique : 0)
260
261 #define TimeToAnnounceThisRecord(RR,time) ((RR)->AnnounceCount && (time) - ((RR)->LastAPTime + (RR)->ThisAPInterval) >= 0)
262 #define TimeToSendThisRecord(RR,time) ((TimeToAnnounceThisRecord(RR,time) || (RR)->ImmedAnswer) && ResourceRecordIsValidAnswer(RR))
263 #define TicksTTL(RR) ((mDNSs32)(RR)->resrec.rroriginalttl * mDNSPlatformOneSecond)
264 #define RRExpireTime(RR) ((RR)->TimeRcvd + TicksTTL(RR))
265
266 #define MaxUnansweredQueries 4
267
268 // SameResourceRecordSignature returns true if two resources records have the same name, type, and class, and may be sent
269 // (or were received) on the same interface (i.e. if *both* records specify an interface, then it has to match).
270 // TTL and rdata may differ.
271 // This is used for cache flush management:
272 // When sending a unique record, all other records matching "SameResourceRecordSignature" must also be sent
273 // When receiving a unique record, all old cache records matching "SameResourceRecordSignature" are flushed
274
275 // SameResourceRecordNameClassInterface is functionally the same as SameResourceRecordSignature, except rrtype does not have to match
276
277 #define SameResourceRecordSignature(A,B) (A)->resrec.rrtype == (B)->resrec.rrtype && SameResourceRecordNameClassInterface((A),(B))
278
279 mDNSlocal mDNSBool SameResourceRecordNameClassInterface(const AuthRecord *const r1, const AuthRecord *const r2)
280         {
281         if (!r1) { LogMsg("SameResourceRecordSignature ERROR: r1 is NULL"); return(mDNSfalse); }
282         if (!r2) { LogMsg("SameResourceRecordSignature ERROR: r2 is NULL"); return(mDNSfalse); }
283         if (r1->resrec.InterfaceID &&
284                 r2->resrec.InterfaceID &&
285                 r1->resrec.InterfaceID != r2->resrec.InterfaceID) return(mDNSfalse);
286         return(mDNSBool)(
287                 r1->resrec.rrclass  == r2->resrec.rrclass &&
288                 r1->resrec.namehash == r2->resrec.namehash &&
289                 SameDomainName(r1->resrec.name, r2->resrec.name));
290         }
291
292 // PacketRRMatchesSignature behaves as SameResourceRecordSignature, except that types may differ if our
293 // authoratative record is unique (as opposed to shared). For unique records, we are supposed to have
294 // complete ownership of *all* types for this name, so *any* record type with the same name is a conflict.
295 // In addition, when probing we send our questions with the wildcard type kDNSQType_ANY,
296 // so a response of any type should match, even if it is not actually the type the client plans to use.
297
298 // For now, to make it easier to avoid false conflicts, we treat SPS Proxy records like shared records,
299 // and require the rrtypes to match for the rdata to be considered potentially conflicting
300 mDNSlocal mDNSBool PacketRRMatchesSignature(const CacheRecord *const pktrr, const AuthRecord *const authrr)
301         {
302         if (!pktrr)  { LogMsg("PacketRRMatchesSignature ERROR: pktrr is NULL"); return(mDNSfalse); }
303         if (!authrr) { LogMsg("PacketRRMatchesSignature ERROR: authrr is NULL"); return(mDNSfalse); }
304         if (pktrr->resrec.InterfaceID &&
305                 authrr->resrec.InterfaceID &&
306                 pktrr->resrec.InterfaceID != authrr->resrec.InterfaceID) return(mDNSfalse);
307         if (!(authrr->resrec.RecordType & kDNSRecordTypeUniqueMask) || authrr->WakeUp.HMAC.l[0])
308                 if (pktrr->resrec.rrtype != authrr->resrec.rrtype) return(mDNSfalse);
309         return(mDNSBool)(
310                 pktrr->resrec.rrclass == authrr->resrec.rrclass &&
311                 pktrr->resrec.namehash == authrr->resrec.namehash &&
312                 SameDomainName(pktrr->resrec.name, authrr->resrec.name));
313         }
314
315 // CacheRecord *ka is the CacheRecord from the known answer list in the query.
316 // This is the information that the requester believes to be correct.
317 // AuthRecord *rr is the answer we are proposing to give, if not suppressed.
318 // This is the information that we believe to be correct.
319 // We've already determined that we plan to give this answer on this interface
320 // (either the record is non-specific, or it is specific to this interface)
321 // so now we just need to check the name, type, class, rdata and TTL.
322 mDNSlocal mDNSBool ShouldSuppressKnownAnswer(const CacheRecord *const ka, const AuthRecord *const rr)
323         {
324         // If RR signature is different, or data is different, then don't suppress our answer
325         if (!IdenticalResourceRecord(&ka->resrec, &rr->resrec)) return(mDNSfalse);
326         
327         // If the requester's indicated TTL is less than half the real TTL,
328         // we need to give our answer before the requester's copy expires.
329         // If the requester's indicated TTL is at least half the real TTL,
330         // then we can suppress our answer this time.
331         // If the requester's indicated TTL is greater than the TTL we believe,
332         // then that's okay, and we don't need to do anything about it.
333         // (If two responders on the network are offering the same information,
334         // that's okay, and if they are offering the information with different TTLs,
335         // the one offering the lower TTL should defer to the one offering the higher TTL.)
336         return(mDNSBool)(ka->resrec.rroriginalttl >= rr->resrec.rroriginalttl / 2);
337         }
338
339 mDNSlocal void SetNextAnnounceProbeTime(mDNS *const m, const AuthRecord *const rr)
340         {
341         if (rr->resrec.RecordType == kDNSRecordTypeUnique)
342                 {
343                 //LogMsg("ProbeCount %d Next %ld %s", rr->ProbeCount, (rr->LastAPTime + rr->ThisAPInterval) - m->timenow, ARDisplayString(m, rr));
344                 if (m->NextScheduledProbe - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
345                         m->NextScheduledProbe = (rr->LastAPTime + rr->ThisAPInterval);
346                 }
347         else if (rr->AnnounceCount && ResourceRecordIsValidAnswer(rr))
348                 {
349                 if (m->NextScheduledResponse - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
350                         m->NextScheduledResponse = (rr->LastAPTime + rr->ThisAPInterval);
351                 }
352         }
353
354 mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr)
355         {
356         // For reverse-mapping Sleep Proxy PTR records, probe interval is one second
357         rr->ThisAPInterval = rr->AddressProxy.type ? mDNSPlatformOneSecond : DefaultAPIntervalForRecordType(rr->resrec.RecordType);
358
359         // To allow us to aggregate probes when a group of services are registered together,
360         // the first probe is delayed 1/4 second. This means the common-case behaviour is:
361         // 1/4 second wait; probe
362         // 1/4 second wait; probe
363         // 1/4 second wait; probe
364         // 1/4 second wait; announce (i.e. service is normally announced exactly one second after being registered)
365
366         if (rr->ProbeCount)
367                 {
368                 // If we have no probe suppression time set, or it is in the past, set it now
369                 if (m->SuppressProbes == 0 || m->SuppressProbes - m->timenow < 0)
370                         {
371                         m->SuppressProbes = NonZeroTime(m->timenow + DefaultProbeIntervalForTypeUnique);
372                         // If we already have a *probe* scheduled to go out sooner, then use that time to get better aggregation
373                         if (m->SuppressProbes - m->NextScheduledProbe >= 0)
374                                 m->SuppressProbes = m->NextScheduledProbe;
375                         // If we already have a *query* scheduled to go out sooner, then use that time to get better aggregation
376                         if (m->SuppressProbes - m->NextScheduledQuery >= 0)
377                                 m->SuppressProbes = m->NextScheduledQuery;
378                         }
379                 }
380
381         rr->LastAPTime      = m->SuppressProbes - rr->ThisAPInterval;
382         // Set LastMCTime to now, to inhibit multicast responses
383         // (no need to send additional multicast responses when we're announcing anyway)
384         rr->LastMCTime      = m->timenow;
385         rr->LastMCInterface = mDNSInterfaceMark;
386         
387         // If this is a record type that's not going to probe, then delay its first announcement so that
388         // it will go out synchronized with the first announcement for the other records that *are* probing.
389         // This is a minor performance tweak that helps keep groups of related records synchronized together.
390         // The addition of "interval / 2" is to make sure that, in the event that any of the probes are
391         // delayed by a few milliseconds, this announcement does not inadvertently go out *before* the probing is complete.
392         // When the probing is complete and those records begin to announce, these records will also be picked up and accelerated,
393         // because they will meet the criterion of being at least half-way to their scheduled announcement time.
394         if (rr->resrec.RecordType != kDNSRecordTypeUnique)
395                 rr->LastAPTime += DefaultProbeIntervalForTypeUnique * DefaultProbeCountForTypeUnique + rr->ThisAPInterval / 2;
396
397         // The exception is unique records that have already been verified and are just being updated
398         // via mDNS_Update() -- for these we want to announce the new value immediately, without delay.
399         if (rr->resrec.RecordType == kDNSRecordTypeVerified)
400                 rr->LastAPTime = m->timenow - rr->ThisAPInterval;
401
402         // For reverse-mapping Sleep Proxy PTR records we don't want to start probing instantly -- we
403         // wait one second to give the client a chance to go to sleep, and then start our ARP/NDP probing.
404         // After three probes one second apart with no answer, we conclude the client is now sleeping
405         // and we can begin broadcasting our announcements to take over ownership of that IP address.
406         // If we don't wait for the client to go to sleep, then when the client sees our ARP Announcements there's a risk
407         // (depending on the OS and networking stack it's using) that it might interpret it as a conflict and change its IP address.
408         if (rr->AddressProxy.type) rr->LastAPTime = m->timenow;
409
410         // For now, since we don't yet handle IPv6 ND or data packets, we send deletions for our SPS clients' AAAA records
411         if (rr->WakeUp.HMAC.l[0] && rr->resrec.rrtype == kDNSType_AAAA)
412                 rr->LastAPTime = m->timenow - rr->ThisAPInterval + mDNSPlatformOneSecond * 10;
413         
414         SetNextAnnounceProbeTime(m, rr);
415         }
416
417 // Right now this only applies to mDNS (.local) services where the target host is always m->MulticastHostname
418 // Eventually we should unify this with GetServiceTarget() in uDNS.c
419 mDNSlocal void SetTargetToHostName(mDNS *const m, AuthRecord *const rr)
420         {
421         domainname *const target = GetRRDomainNameTarget(&rr->resrec);
422         const domainname *newname = &m->MulticastHostname;
423
424         if (!target) debugf("SetTargetToHostName: Don't know how to set the target of rrtype %d", rr->resrec.rrtype);
425
426         if (!(rr->ForceMCast || rr->resrec.InterfaceID == mDNSInterface_LocalOnly || IsLocalDomain(&rr->namestorage)))
427                 {
428                 const domainname *const n = GetServiceTarget(m, rr);
429                 if (n) newname = n;
430                 }
431
432         if (target && SameDomainName(target, newname))
433                 debugf("SetTargetToHostName: Target of %##s is already %##s", rr->resrec.name->c, target->c);
434         
435         if (target && !SameDomainName(target, newname))
436                 {
437                 AssignDomainName(target, newname);
438                 SetNewRData(&rr->resrec, mDNSNULL, 0);          // Update rdlength, rdestimate, rdatahash
439                 
440                 // If we're in the middle of probing this record, we need to start again,
441                 // because changing its rdata may change the outcome of the tie-breaker.
442                 // (If the record type is kDNSRecordTypeUnique (unconfirmed unique) then DefaultProbeCountForRecordType is non-zero.)
443                 rr->ProbeCount     = DefaultProbeCountForRecordType(rr->resrec.RecordType);
444
445                 // If we've announced this record, we really should send a goodbye packet for the old rdata before
446                 // changing to the new rdata. However, in practice, we only do SetTargetToHostName for unique records,
447                 // so when we announce them we'll set the kDNSClass_UniqueRRSet and clear any stale data that way.
448                 if (rr->RequireGoodbye && rr->resrec.RecordType == kDNSRecordTypeShared)
449                         debugf("Have announced shared record %##s (%s) at least once: should have sent a goodbye packet before updating",
450                                 rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
451
452                 rr->AnnounceCount  = InitialAnnounceCount;
453                 rr->RequireGoodbye = mDNSfalse;
454                 InitializeLastAPTime(m, rr);
455                 }
456         }
457
458 mDNSlocal void AcknowledgeRecord(mDNS *const m, AuthRecord *const rr)
459         {
460         if (rr->RecordCallback)
461                 {
462                 // CAUTION: MUST NOT do anything more with rr after calling rr->Callback(), because the client's callback function
463                 // is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc.
464                 rr->Acknowledged = mDNStrue;
465                 mDNS_DropLockBeforeCallback();          // Allow client to legally make mDNS API calls from the callback
466                 rr->RecordCallback(m, rr, mStatus_NoError);
467                 mDNS_ReclaimLockAfterCallback();        // Decrement mDNS_reentrancy to block mDNS API calls again
468                 }
469         }
470
471 mDNSlocal void ActivateUnicastRegistration(mDNS *const m, AuthRecord *const rr)
472         {
473         rr->ProbeCount     = 0;
474         rr->AnnounceCount  = 0;
475         rr->ThisAPInterval = 5 * mDNSPlatformOneSecond;         // After doubling, first retry will happen after ten seconds
476         rr->LastAPTime     = m->timenow - rr->ThisAPInterval;
477         rr->state = regState_FetchingZoneData;
478         rr->uselease = mDNStrue;
479         }
480
481 // Two records qualify to be local duplicates if the RecordTypes are the same, or if one is Unique and the other Verified
482 #define RecordLDT(A,B) ((A)->resrec.RecordType == (B)->resrec.RecordType || \
483         ((A)->resrec.RecordType | (B)->resrec.RecordType) == (kDNSRecordTypeUnique | kDNSRecordTypeVerified))
484 #define RecordIsLocalDuplicate(A,B) \
485         ((A)->resrec.InterfaceID == (B)->resrec.InterfaceID && RecordLDT((A),(B)) && IdenticalResourceRecord(&(A)->resrec, &(B)->resrec))
486
487 // Exported so uDNS.c can call this
488 mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
489         {
490         domainname *target = GetRRDomainNameTarget(&rr->resrec);
491         AuthRecord *r;
492         AuthRecord **p = &m->ResourceRecords;
493         AuthRecord **d = &m->DuplicateRecords;
494
495         if ((mDNSs32)rr->resrec.rroriginalttl <= 0)
496                 { LogMsg("mDNS_Register_internal: TTL must be 1 - 0x7FFFFFFF %s", ARDisplayString(m, rr)); return(mStatus_BadParamErr); }
497
498         if (!rr->resrec.RecordType)
499                 { LogMsg("mDNS_Register_internal: RecordType must be non-zero %s", ARDisplayString(m, rr)); return(mStatus_BadParamErr); }
500
501         if (m->ShutdownTime)
502                 { LogMsg("mDNS_Register_internal: Shutting down, can't register %s", ARDisplayString(m, rr)); return(mStatus_ServiceNotRunning); }
503         
504         if (m->DivertMulticastAdvertisements && !AuthRecord_uDNS(rr))
505                 {
506                 mDNSInterfaceID previousID = rr->resrec.InterfaceID;
507                 if (rr->resrec.InterfaceID == mDNSInterface_Any) rr->resrec.InterfaceID = mDNSInterface_LocalOnly;
508                 if (rr->resrec.InterfaceID != mDNSInterface_LocalOnly)
509                         {
510                         NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID);
511                         if (intf && !intf->Advertise) rr->resrec.InterfaceID = mDNSInterface_LocalOnly;
512                         }
513                 if (rr->resrec.InterfaceID != previousID)
514                         LogInfo("mDNS_Register_internal: Diverting record to local-only %s", ARDisplayString(m, rr));
515                 }
516
517         while (*p && *p != rr) p=&(*p)->next;
518         while (*d && *d != rr) d=&(*d)->next;
519         if (*d || *p)
520                 {
521                 LogMsg("Error! Tried to register AuthRecord %p %##s (%s) that's already in the list",
522                         rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
523                 return(mStatus_AlreadyRegistered);
524                 }
525
526         if (rr->DependentOn)
527                 {
528                 if (rr->resrec.RecordType == kDNSRecordTypeUnique)
529                         rr->resrec.RecordType =  kDNSRecordTypeVerified;
530                 else
531                         {
532                         LogMsg("mDNS_Register_internal: ERROR! %##s (%s): rr->DependentOn && RecordType != kDNSRecordTypeUnique",
533                                 rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
534                         return(mStatus_Invalid);
535                         }
536                 if (!(rr->DependentOn->resrec.RecordType & (kDNSRecordTypeUnique | kDNSRecordTypeVerified)))
537                         {
538                         LogMsg("mDNS_Register_internal: ERROR! %##s (%s): rr->DependentOn->RecordType bad type %X",
539                                 rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->DependentOn->resrec.RecordType);
540                         return(mStatus_Invalid);
541                         }
542                 }
543
544         // If this resource record is referencing a specific interface, make sure it exists
545         if (rr->resrec.InterfaceID && rr->resrec.InterfaceID != mDNSInterface_LocalOnly)
546                 {
547                 NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID);
548                 if (!intf)
549                         {
550                         debugf("mDNS_Register_internal: Bogus InterfaceID %p in resource record", rr->resrec.InterfaceID);
551                         return(mStatus_BadReferenceErr);
552                         }
553                 }
554
555         rr->next = mDNSNULL;
556
557         // Field Group 1: The actual information pertaining to this resource record
558         // Set up by client prior to call
559
560         // Field Group 2: Persistent metadata for Authoritative Records
561 //      rr->Additional1       = set to mDNSNULL  in mDNS_SetupResourceRecord; may be overridden by client
562 //      rr->Additional2       = set to mDNSNULL  in mDNS_SetupResourceRecord; may be overridden by client
563 //      rr->DependentOn       = set to mDNSNULL  in mDNS_SetupResourceRecord; may be overridden by client
564 //      rr->RRSet             = set to mDNSNULL  in mDNS_SetupResourceRecord; may be overridden by client
565 //      rr->Callback          = already set      in mDNS_SetupResourceRecord
566 //      rr->Context           = already set      in mDNS_SetupResourceRecord
567 //      rr->RecordType        = already set      in mDNS_SetupResourceRecord
568 //      rr->HostTarget        = set to mDNSfalse in mDNS_SetupResourceRecord; may be overridden by client
569 //      rr->AllowRemoteQuery  = set to mDNSfalse in mDNS_SetupResourceRecord; may be overridden by client
570         // Make sure target is not uninitialized data, or we may crash writing debugging log messages
571         if (rr->AutoTarget && target) target->c[0] = 0;
572
573         // Field Group 3: Transient state for Authoritative Records
574         rr->Acknowledged      = mDNSfalse;
575         rr->ProbeCount        = DefaultProbeCountForRecordType(rr->resrec.RecordType);
576         rr->AnnounceCount     = InitialAnnounceCount;
577         rr->RequireGoodbye    = mDNSfalse;
578         rr->AnsweredLocalQ    = mDNSfalse;
579         rr->IncludeInProbe    = mDNSfalse;
580         rr->ImmedUnicast      = mDNSfalse;
581         rr->SendNSECNow       = mDNSNULL;
582         rr->ImmedAnswer       = mDNSNULL;
583         rr->ImmedAdditional   = mDNSNULL;
584         rr->SendRNow          = mDNSNULL;
585         rr->v4Requester       = zerov4Addr;
586         rr->v6Requester       = zerov6Addr;
587         rr->NextResponse      = mDNSNULL;
588         rr->NR_AnswerTo       = mDNSNULL;
589         rr->NR_AdditionalTo   = mDNSNULL;
590         if (!rr->AutoTarget) InitializeLastAPTime(m, rr);
591 //      rr->LastAPTime        = Set for us in InitializeLastAPTime()
592 //      rr->LastMCTime        = Set for us in InitializeLastAPTime()
593 //      rr->LastMCInterface   = Set for us in InitializeLastAPTime()
594         rr->NewRData          = mDNSNULL;
595         rr->newrdlength       = 0;
596         rr->UpdateCallback    = mDNSNULL;
597         rr->UpdateCredits     = kMaxUpdateCredits;
598         rr->NextUpdateCredit  = 0;
599         rr->UpdateBlocked     = 0;
600
601         // For records we're holding as proxy (except reverse-mapping PTR records) two announcements is sufficient
602         if (rr->WakeUp.HMAC.l[0] && !rr->AddressProxy.type) rr->AnnounceCount = 2;
603
604         // Field Group 4: Transient uDNS state for Authoritative Records
605         rr->state             = regState_Zero;
606         rr->uselease          = 0;
607         rr->expire            = 0;
608         rr->Private           = 0;
609         rr->updateid          = zeroID;
610         rr->zone              = rr->resrec.name;
611         rr->UpdateServer      = zeroAddr;
612         rr->UpdatePort        = zeroIPPort;
613         rr->nta               = mDNSNULL;
614         rr->tcp               = mDNSNULL;
615         rr->OrigRData         = 0;
616         rr->OrigRDLen         = 0;
617         rr->InFlightRData     = 0;
618         rr->InFlightRDLen     = 0;
619         rr->QueuedRData       = 0;
620         rr->QueuedRDLen       = 0;
621
622 //      rr->resrec.interface         = already set in mDNS_SetupResourceRecord
623 //      rr->resrec.name->c           = MUST be set by client
624 //      rr->resrec.rrtype            = already set in mDNS_SetupResourceRecord
625 //      rr->resrec.rrclass           = already set in mDNS_SetupResourceRecord
626 //      rr->resrec.rroriginalttl     = already set in mDNS_SetupResourceRecord
627 //      rr->resrec.rdata             = MUST be set by client, unless record type is CNAME or PTR and rr->HostTarget is set
628
629         if (rr->AutoTarget)
630                 SetTargetToHostName(m, rr);     // Also sets rdlength and rdestimate for us, and calls InitializeLastAPTime();
631         else
632                 {
633                 rr->resrec.rdlength   = GetRDLength(&rr->resrec, mDNSfalse);
634                 rr->resrec.rdestimate = GetRDLength(&rr->resrec, mDNStrue);
635                 }
636
637         if (!ValidateDomainName(rr->resrec.name))
638                 { LogMsg("Attempt to register record with invalid name: %s", ARDisplayString(m, rr)); return(mStatus_Invalid); }
639
640         // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct,
641         // since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s".
642         // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here.
643         if (rr->resrec.rrtype == kDNSType_TXT && rr->resrec.rdlength == 0) { rr->resrec.rdlength = 1; rr->resrec.rdata->u.txt.c[0] = 0; }
644
645         // Don't do this until *after* we've set rr->resrec.rdlength
646         if (!ValidateRData(rr->resrec.rrtype, rr->resrec.rdlength, rr->resrec.rdata))
647                 { LogMsg("Attempt to register record with invalid rdata: %s", ARDisplayString(m, rr)); return(mStatus_Invalid); }
648
649         rr->resrec.namehash   = DomainNameHashValue(rr->resrec.name);
650         rr->resrec.rdatahash  = target ? DomainNameHashValue(target) : RDataHashValue(&rr->resrec);
651         
652         if (rr->resrec.InterfaceID == mDNSInterface_LocalOnly)
653                 {
654                 // If this is supposed to be unique, make sure we don't have any name conflicts
655                 if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
656                         {
657                         const AuthRecord *s1 = rr->RRSet ? rr->RRSet : rr;
658                         for (r = m->ResourceRecords; r; r=r->next)
659                                 {
660                                 const AuthRecord *s2 = r->RRSet ? r->RRSet : r;
661                                 if (s1 != s2 && SameResourceRecordSignature(r, rr) && !IdenticalSameNameRecord(&r->resrec, &rr->resrec))
662                                         break;
663                                 }
664                         if (r)  // If we found a conflict, set RecordType = kDNSRecordTypeDeregistering so we'll deliver the callback
665                                 {
666                                 debugf("Name conflict %p %##s (%s)", rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
667                                 rr->resrec.RecordType    = kDNSRecordTypeDeregistering;
668                                 rr->resrec.rroriginalttl = 0;
669                                 rr->ImmedAnswer          = mDNSInterfaceMark;
670                                 m->NextScheduledResponse = m->timenow;
671                                 }
672                         }
673                 }
674
675         // Now that we've finished building our new record, make sure it's not identical to one we already have
676         for (r = m->ResourceRecords; r; r=r->next) if (RecordIsLocalDuplicate(r, rr)) break;
677         
678         if (r)
679                 {
680                 debugf("Adding to duplicate list %p %s", rr, ARDisplayString(m,rr));
681                 *d = rr;
682                 // If the previous copy of this record is already verified unique,
683                 // then indicate that we should move this record promptly to kDNSRecordTypeUnique state.
684                 // Setting ProbeCount to zero will cause SendQueries() to advance this record to
685                 // kDNSRecordTypeVerified state and call the client callback at the next appropriate time.
686                 if (rr->resrec.RecordType == kDNSRecordTypeUnique && r->resrec.RecordType == kDNSRecordTypeVerified)
687                         rr->ProbeCount = 0;
688                 }
689         else
690                 {
691                 debugf("Adding to active record list %p %s", rr, ARDisplayString(m,rr));
692                 if (!m->NewLocalRecords) m->NewLocalRecords = rr;
693                 *p = rr;
694                 }
695
696         if (!AuthRecord_uDNS(rr))
697                 {
698                 // For records that are not going to probe, acknowledge them right away
699                 if (rr->resrec.RecordType != kDNSRecordTypeUnique && rr->resrec.RecordType != kDNSRecordTypeDeregistering)
700                         AcknowledgeRecord(m, rr);
701                 }
702 #ifndef UNICAST_DISABLED
703         else
704                 {
705                 if (rr->resrec.RecordType == kDNSRecordTypeUnique) rr->resrec.RecordType = kDNSRecordTypeVerified;
706                 ActivateUnicastRegistration(m, rr);
707                 }
708 #endif
709         
710         return(mStatus_NoError);
711         }
712
713 mDNSlocal void RecordProbeFailure(mDNS *const m, const AuthRecord *const rr)
714         {
715         m->ProbeFailTime = m->timenow;
716         m->NumFailedProbes++;
717         // If we've had fifteen or more probe failures, rate-limit to one every five seconds.
718         // If a bunch of hosts have all been configured with the same name, then they'll all
719         // conflict and run through the same series of names: name-2, name-3, name-4, etc.,
720         // up to name-10. After that they'll start adding random increments in the range 1-100,
721         // so they're more likely to branch out in the available namespace and settle on a set of
722         // unique names quickly. If after five more tries the host is still conflicting, then we
723         // may have a serious problem, so we start rate-limiting so we don't melt down the network.
724         if (m->NumFailedProbes >= 15)
725                 {
726                 m->SuppressProbes = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 5);
727                 LogMsg("Excessive name conflicts (%lu) for %##s (%s); rate limiting in effect",
728                         m->NumFailedProbes, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
729                 }
730         }
731
732 mDNSlocal void CompleteRDataUpdate(mDNS *const m, AuthRecord *const rr)
733         {
734         RData *OldRData = rr->resrec.rdata;
735         SetNewRData(&rr->resrec, rr->NewRData, rr->newrdlength);        // Update our rdata
736         rr->NewRData = mDNSNULL;                                                                        // Clear the NewRData pointer ...
737         if (rr->UpdateCallback)
738                 rr->UpdateCallback(m, rr, OldRData);                                    // ... and let the client know
739         }
740
741 // Note: mDNS_Deregister_internal can call a user callback, which may change the record list and/or question list.
742 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
743 // Exported so uDNS.c can call this
744 mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr, mDNS_Dereg_type drt)
745         {
746         AuthRecord *r2;
747         mDNSu8 RecordType = rr->resrec.RecordType;
748         AuthRecord **p = &m->ResourceRecords;   // Find this record in our list of active records
749
750         while (*p && *p != rr) p=&(*p)->next;
751
752         if (*p)
753                 {
754                 // We found our record on the main list. See if there are any duplicates that need special handling.
755                 if (drt == mDNS_Dereg_conflict)         // If this was a conflict, see that all duplicates get the same treatment
756                         {
757                         // Scan for duplicates of rr, and mark them for deregistration at the end of this routine, after we've finished
758                         // deregistering rr. We need to do this scan *before* we give the client the chance to free and reuse the rr memory.
759                         for (r2 = m->DuplicateRecords; r2; r2=r2->next) if (RecordIsLocalDuplicate(r2, rr)) r2->ProbeCount = 0xFF;
760                         }
761                 else
762                         {
763                         // Before we delete the record (and potentially send a goodbye packet)
764                         // first see if we have a record on the duplicate list ready to take over from it.
765                         AuthRecord **d = &m->DuplicateRecords;
766                         while (*d && !RecordIsLocalDuplicate(*d, rr)) d=&(*d)->next;
767                         if (*d)
768                                 {
769                                 AuthRecord *dup = *d;
770                                 debugf("Duplicate record %p taking over from %p %##s (%s)",
771                                         dup, rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
772                                 *d        = dup->next;          // Cut replacement record from DuplicateRecords list
773                                 dup->next = rr->next;           // And then...
774                                 rr->next  = dup;                        // ... splice it in right after the record we're about to delete
775                                 dup->resrec.RecordType        = rr->resrec.RecordType;
776                                 dup->ProbeCount      = rr->ProbeCount;
777                                 dup->AnnounceCount   = rr->AnnounceCount;
778                                 dup->RequireGoodbye  = rr->RequireGoodbye;
779                                 dup->AnsweredLocalQ  = rr->AnsweredLocalQ;
780                                 dup->ImmedAnswer     = rr->ImmedAnswer;
781                                 dup->ImmedUnicast    = rr->ImmedUnicast;
782                                 dup->ImmedAdditional = rr->ImmedAdditional;
783                                 dup->v4Requester     = rr->v4Requester;
784                                 dup->v6Requester     = rr->v6Requester;
785                                 dup->ThisAPInterval  = rr->ThisAPInterval;
786                                 dup->LastAPTime      = rr->LastAPTime;
787                                 dup->LastMCTime      = rr->LastMCTime;
788                                 dup->LastMCInterface = rr->LastMCInterface;
789                                 dup->UpdateServer    = rr->UpdateServer;
790                                 dup->UpdatePort      = rr->UpdatePort;
791                                 dup->Private         = rr->Private;
792                                 dup->state           = rr->state;
793                                 rr->RequireGoodbye = mDNSfalse;
794                                 rr->AnsweredLocalQ = mDNSfalse;
795                                 }
796                         }
797                 }
798         else
799                 {
800                 // We didn't find our record on the main list; try the DuplicateRecords list instead.
801                 p = &m->DuplicateRecords;
802                 while (*p && *p != rr) p=&(*p)->next;
803                 // If we found our record on the duplicate list, then make sure we don't send a goodbye for it
804                 if (*p) rr->RequireGoodbye = mDNSfalse;
805                 if (*p) debugf("DNS_Deregister_internal: Deleting DuplicateRecord %p %##s (%s)",
806                         rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
807                 }
808
809         if (!*p)
810                 {
811                 // No need to log an error message if we already know this is a potentially repeated deregistration
812                 if (drt != mDNS_Dereg_repeat)
813                         LogMsg("mDNS_Deregister_internal: Record %p not found in list %s", rr, ARDisplayString(m,rr));
814                 return(mStatus_BadReferenceErr);
815                 }
816
817         if (rr->WakeUp.HMAC.l[0])
818                 {
819                 LogSPS("mDNS_Deregister_internal: Sending wakeup for %.6a %s", &rr->WakeUp.HMAC, ARDisplayString(m, rr));
820                 SendWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.IMAC, &rr->WakeUp.password);
821                 }
822
823         // If this is a shared record and we've announced it at least once,
824         // we need to retract that announcement before we delete the record
825
826         // If this is a record (including mDNSInterface_LocalOnly records) for which we've given local-only answers then
827         // it's tempting to just do "AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNSfalse)" here, but that would not not be safe.
828         // The AnswerAllLocalQuestionsWithLocalAuthRecord routine walks the question list invoking client callbacks, using the "m->CurrentQuestion"
829         // mechanism to cope with the client callback modifying the question list while that's happening.
830         // However, mDNS_Deregister could have been called from a client callback (e.g. from the domain enumeration callback FoundDomain)
831         // which means that the "m->CurrentQuestion" mechanism is already in use to protect that list, so we can't use it twice.
832         // More generally, if we invoke callbacks from within a client callback, then those callbacks could deregister other
833         // records, thereby invoking yet more callbacks, without limit.
834         // The solution is to defer delivering the "Remove" events until mDNS_Execute time, just like we do for sending
835         // actual goodbye packets.
836         
837 #ifndef UNICAST_DISABLED
838         if (AuthRecord_uDNS(rr) && rr->RequireGoodbye)
839                 {
840                 if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; }
841                 rr->resrec.RecordType    = kDNSRecordTypeDeregistering;
842                 uDNS_DeregisterRecord(m, rr);
843                 // At this point unconditionally we bail out
844                 // Either uDNS_DeregisterRecord will have completed synchronously, and called CompleteDeregistration,
845                 // which calls us back here with RequireGoodbye set to false, or it will have initiated the deregistration
846                 // process and will complete asynchronously. Either way we don't need to do anything more here.
847                 return(mStatus_NoError);
848                 }
849 #endif // UNICAST_DISABLED
850
851         if (RecordType == kDNSRecordTypeShared && (rr->RequireGoodbye || rr->AnsweredLocalQ))
852                 {
853                 verbosedebugf("mDNS_Deregister_internal: Sending deregister for %s", ARDisplayString(m, rr));
854                 rr->resrec.RecordType    = kDNSRecordTypeDeregistering;
855                 rr->resrec.rroriginalttl = 0;
856                 rr->ImmedAnswer          = mDNSInterfaceMark;
857                 if (m->NextScheduledResponse - (m->timenow + mDNSPlatformOneSecond/10) >= 0)
858                         m->NextScheduledResponse = (m->timenow + mDNSPlatformOneSecond/10);
859                 }
860         else
861                 {
862                 *p = rr->next;                                  // Cut this record from the list
863                 // If someone is about to look at this, bump the pointer forward
864                 if (m->CurrentRecord   == rr) m->CurrentRecord   = rr->next;
865                 if (m->NewLocalRecords == rr) m->NewLocalRecords = rr->next;
866                 rr->next = mDNSNULL;
867
868                 if      (RecordType == kDNSRecordTypeUnregistered)
869                         LogMsg("mDNS_Deregister_internal: %s already marked kDNSRecordTypeUnregistered", ARDisplayString(m, rr));
870                 else if (RecordType == kDNSRecordTypeDeregistering)
871                         LogMsg("mDNS_Deregister_internal: %s already marked kDNSRecordTypeDeregistering", ARDisplayString(m, rr));
872                 else
873                         {
874                         verbosedebugf("mDNS_Deregister_internal: Deleting record for %s", ARDisplayString(m, rr));
875                         rr->resrec.RecordType = kDNSRecordTypeUnregistered;
876                         }
877
878                 if ((drt == mDNS_Dereg_conflict || drt == mDNS_Dereg_repeat) && RecordType == kDNSRecordTypeShared)
879                         debugf("mDNS_Deregister_internal: Cannot have a conflict on a shared record! %##s (%s)",
880                                 rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
881
882                 // If we have an update queued up which never executed, give the client a chance to free that memory
883                 if (rr->NewRData) CompleteRDataUpdate(m, rr);   // Update our rdata, clear the NewRData pointer, and return memory to the client
884
885                 if (rr->nta) { CancelGetZoneData(m, rr->nta); rr->nta = mDNSNULL; }
886                 if (rr->tcp) { DisposeTCPConn(rr->tcp);       rr->tcp = mDNSNULL; }
887
888                 // CAUTION: MUST NOT do anything more with rr after calling rr->Callback(), because the client's callback function
889                 // is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc.
890                 // In this case the likely client action to the mStatus_MemFree message is to free the memory,
891                 // so any attempt to touch rr after this is likely to lead to a crash.
892                 if (drt != mDNS_Dereg_conflict)
893                         {
894                         mDNS_DropLockBeforeCallback();          // Allow client to legally make mDNS API calls from the callback
895                         if (rr->RecordCallback)
896                                 rr->RecordCallback(m, rr, mStatus_MemFree);                     // MUST NOT touch rr after this
897                         mDNS_ReclaimLockAfterCallback();        // Decrement mDNS_reentrancy to block mDNS API calls again
898                         }
899                 else
900                         {
901                         RecordProbeFailure(m, rr);
902                         mDNS_DropLockBeforeCallback();          // Allow client to legally make mDNS API calls from the callback
903                         if (rr->RecordCallback)
904                                 rr->RecordCallback(m, rr, mStatus_NameConflict);        // MUST NOT touch rr after this
905                         mDNS_ReclaimLockAfterCallback();        // Decrement mDNS_reentrancy to block mDNS API calls again
906                         // Now that we've finished deregistering rr, check our DuplicateRecords list for any that we marked previously.
907                         // Note that with all the client callbacks going on, by the time we get here all the
908                         // records we marked may have been explicitly deregistered by the client anyway.
909                         r2 = m->DuplicateRecords;
910                         while (r2)
911                                 {
912                                 if (r2->ProbeCount != 0xFF) r2 = r2->next;
913                                 else { mDNS_Deregister_internal(m, r2, mDNS_Dereg_conflict); r2 = m->DuplicateRecords; }
914                                 }
915                         }
916                 }
917         return(mStatus_NoError);
918         }
919
920 // ***************************************************************************
921 #if COMPILER_LIKES_PRAGMA_MARK
922 #pragma mark -
923 #pragma mark - Packet Sending Functions
924 #endif
925
926 mDNSlocal void AddRecordToResponseList(AuthRecord ***nrpp, AuthRecord *rr, AuthRecord *add)
927         {
928         if (rr->NextResponse == mDNSNULL && *nrpp != &rr->NextResponse)
929                 {
930                 **nrpp = rr;
931                 // NR_AdditionalTo must point to a record with NR_AnswerTo set (and not NR_AdditionalTo)
932                 // If 'add' does not meet this requirement, then follow its NR_AdditionalTo pointer to a record that does
933                 // The referenced record will definitely be acceptable (by recursive application of this rule)
934                 if (add && add->NR_AdditionalTo) add = add->NR_AdditionalTo;
935                 rr->NR_AdditionalTo = add;
936                 *nrpp = &rr->NextResponse;
937                 }
938         debugf("AddRecordToResponseList: %##s (%s) already in list", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
939         }
940
941 mDNSlocal void AddAdditionalsToResponseList(mDNS *const m, AuthRecord *ResponseRecords, AuthRecord ***nrpp, const mDNSInterfaceID InterfaceID)
942         {
943         AuthRecord  *rr, *rr2;
944         for (rr=ResponseRecords; rr; rr=rr->NextResponse)                       // For each record we plan to put
945                 {
946                 // (Note: This is an "if", not a "while". If we add a record, we'll find it again
947                 // later in the "for" loop, and we will follow further "additional" links then.)
948                 if (rr->Additional1 && ResourceRecordIsValidInterfaceAnswer(rr->Additional1, InterfaceID))
949                         AddRecordToResponseList(nrpp, rr->Additional1, rr);
950
951                 if (rr->Additional2 && ResourceRecordIsValidInterfaceAnswer(rr->Additional2, InterfaceID))
952                         AddRecordToResponseList(nrpp, rr->Additional2, rr);
953
954                 // For SRV records, automatically add the Address record(s) for the target host
955                 if (rr->resrec.rrtype == kDNSType_SRV)
956                         {
957                         for (rr2=m->ResourceRecords; rr2; rr2=rr2->next)                                        // Scan list of resource records
958                                 if (RRTypeIsAddressType(rr2->resrec.rrtype) &&                                  // For all address records (A/AAAA) ...
959                                         ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) &&       // ... which are valid for answer ...
960                                         rr->resrec.rdatahash == rr2->resrec.namehash &&                 // ... whose name is the name of the SRV target
961                                         SameDomainName(&rr->resrec.rdata->u.srv.target, rr2->resrec.name))
962                                         AddRecordToResponseList(nrpp, rr2, rr);
963                         }
964                 else if (RRTypeIsAddressType(rr->resrec.rrtype))        // For A or AAAA, put counterpart as additional
965                         {
966                         for (rr2=m->ResourceRecords; rr2; rr2=rr2->next)                                        // Scan list of resource records
967                                 if (RRTypeIsAddressType(rr2->resrec.rrtype) &&                                  // For all address records (A/AAAA) ...
968                                         ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) &&       // ... which are valid for answer ...
969                                         rr->resrec.namehash == rr2->resrec.namehash &&                          // ... and have the same name
970                                         SameDomainName(rr->resrec.name, rr2->resrec.name))
971                                         AddRecordToResponseList(nrpp, rr2, rr);
972                         }
973                 else if (rr->resrec.rrtype == kDNSType_PTR)                     // For service PTR, see if we want to add DeviceInfo record
974                         {
975                         if (ResourceRecordIsValidInterfaceAnswer(&m->DeviceInfo, InterfaceID) &&
976                                 SameDomainLabel(rr->resrec.rdata->u.name.c, m->DeviceInfo.resrec.name->c))
977                                 AddRecordToResponseList(nrpp, &m->DeviceInfo, rr);
978                         }
979                 }
980         }
981
982 mDNSlocal void SendDelayedUnicastResponse(mDNS *const m, const mDNSAddr *const dest, const mDNSInterfaceID InterfaceID)
983         {
984         AuthRecord *rr;
985         AuthRecord  *ResponseRecords = mDNSNULL;
986         AuthRecord **nrp             = &ResponseRecords;
987
988         // Make a list of all our records that need to be unicast to this destination
989         for (rr = m->ResourceRecords; rr; rr=rr->next)
990                 {
991                 // If we find we can no longer unicast this answer, clear ImmedUnicast
992                 if (rr->ImmedAnswer == mDNSInterfaceMark               ||
993                         mDNSSameIPv4Address(rr->v4Requester, onesIPv4Addr) ||
994                         mDNSSameIPv6Address(rr->v6Requester, onesIPv6Addr)  )
995                         rr->ImmedUnicast = mDNSfalse;
996
997                 if (rr->ImmedUnicast && rr->ImmedAnswer == InterfaceID)
998                         if ((dest->type == mDNSAddrType_IPv4 && mDNSSameIPv4Address(rr->v4Requester, dest->ip.v4)) ||
999                                 (dest->type == mDNSAddrType_IPv6 && mDNSSameIPv6Address(rr->v6Requester, dest->ip.v6)))
1000                                 {
1001                                 rr->ImmedAnswer  = mDNSNULL;                            // Clear the state fields
1002                                 rr->ImmedUnicast = mDNSfalse;
1003                                 rr->v4Requester  = zerov4Addr;
1004                                 rr->v6Requester  = zerov6Addr;
1005                                 if (rr->NextResponse == mDNSNULL && nrp != &rr->NextResponse)   // rr->NR_AnswerTo
1006                                         { rr->NR_AnswerTo = (mDNSu8*)~0; *nrp = rr; nrp = &rr->NextResponse; }
1007                                 }
1008                 }
1009
1010         AddAdditionalsToResponseList(m, ResponseRecords, &nrp, InterfaceID);
1011
1012         while (ResponseRecords)
1013                 {
1014                 mDNSu8 *responseptr = m->omsg.data;
1015                 mDNSu8 *newptr;
1016                 InitializeDNSMessage(&m->omsg.h, zeroID, ResponseFlags);
1017                 
1018                 // Put answers in the packet
1019                 while (ResponseRecords && ResponseRecords->NR_AnswerTo)
1020                         {
1021                         rr = ResponseRecords;
1022                         if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
1023                                 rr->resrec.rrclass |= kDNSClass_UniqueRRSet;            // Temporarily set the cache flush bit so PutResourceRecord will set it
1024                         newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAnswers, &rr->resrec);
1025                         rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;                   // Make sure to clear cache flush bit back to normal state
1026                         if (!newptr && m->omsg.h.numAnswers) break;     // If packet full, send it now
1027                         if (newptr) responseptr = newptr;
1028                         ResponseRecords = rr->NextResponse;
1029                         rr->NextResponse    = mDNSNULL;
1030                         rr->NR_AnswerTo     = mDNSNULL;
1031                         rr->NR_AdditionalTo = mDNSNULL;
1032                         rr->RequireGoodbye  = mDNStrue;
1033                         }
1034                 
1035                 // Add additionals, if there's space
1036                 while (ResponseRecords && !ResponseRecords->NR_AnswerTo)
1037                         {
1038                         rr = ResponseRecords;
1039                         if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
1040                                 rr->resrec.rrclass |= kDNSClass_UniqueRRSet;            // Temporarily set the cache flush bit so PutResourceRecord will set it
1041                         newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAdditionals, &rr->resrec);
1042                         rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;                   // Make sure to clear cache flush bit back to normal state
1043                         
1044                         if (newptr) responseptr = newptr;
1045                         if (newptr && m->omsg.h.numAnswers) rr->RequireGoodbye = mDNStrue;
1046                         else if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask) rr->ImmedAnswer = mDNSInterfaceMark;
1047                         ResponseRecords = rr->NextResponse;
1048                         rr->NextResponse    = mDNSNULL;
1049                         rr->NR_AnswerTo     = mDNSNULL;
1050                         rr->NR_AdditionalTo = mDNSNULL;
1051                         }
1052
1053                 if (m->omsg.h.numAnswers)
1054                         mDNSSendDNSMessage(m, &m->omsg, responseptr, mDNSInterface_Any, mDNSNULL, dest, MulticastDNSPort, mDNSNULL, mDNSNULL);
1055                 }
1056         }
1057
1058 mDNSexport void CompleteDeregistration(mDNS *const m, AuthRecord *rr)
1059         {
1060         // Clearing rr->RequireGoodbye signals mDNS_Deregister_internal() that
1061         // it should go ahead and immediately dispose of this registration
1062         rr->resrec.RecordType = kDNSRecordTypeShared;
1063         rr->RequireGoodbye    = mDNSfalse;
1064         if (rr->AnsweredLocalQ) { AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNSfalse); rr->AnsweredLocalQ = mDNSfalse; }
1065         mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);             // Don't touch rr after this
1066         }
1067
1068 // Note: DiscardDeregistrations calls mDNS_Deregister_internal which can call a user callback, which may change
1069 // the record list and/or question list.
1070 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
1071 mDNSlocal void DiscardDeregistrations(mDNS *const m)
1072         {
1073         if (m->CurrentRecord)
1074                 LogMsg("DiscardDeregistrations ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
1075         m->CurrentRecord = m->ResourceRecords;
1076         
1077         while (m->CurrentRecord)
1078                 {
1079                 AuthRecord *rr = m->CurrentRecord;
1080                 if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
1081                         CompleteDeregistration(m, rr);          // Don't touch rr after this
1082                 else
1083                         m->CurrentRecord = rr->next;
1084                 }
1085         }
1086
1087 mDNSlocal mStatus GetLabelDecimalValue(const mDNSu8 *const src, mDNSu8 *dst)
1088         {
1089         int i, val = 0;
1090         if (src[0] < 1 || src[0] > 3) return(mStatus_Invalid);
1091         for (i=1; i<=src[0]; i++)
1092                 {
1093                 if (src[i] < '0' || src[i] > '9') return(mStatus_Invalid);
1094                 val = val * 10 + src[i] - '0';
1095                 }
1096         if (val > 255) return(mStatus_Invalid);
1097         *dst = (mDNSu8)val;
1098         return(mStatus_NoError);
1099         }
1100
1101 mDNSlocal mStatus GetIPv4FromName(mDNSAddr *const a, const domainname *const name)
1102         {
1103         int skip = CountLabels(name) - 6;
1104         if (skip < 0) { LogMsg("GetIPFromName: Need six labels in IPv4 reverse mapping name %##s", name); return mStatus_Invalid; }
1105         if (GetLabelDecimalValue(SkipLeadingLabels(name, skip+3)->c, &a->ip.v4.b[0]) ||
1106                 GetLabelDecimalValue(SkipLeadingLabels(name, skip+2)->c, &a->ip.v4.b[1]) ||
1107                 GetLabelDecimalValue(SkipLeadingLabels(name, skip+1)->c, &a->ip.v4.b[2]) ||
1108                 GetLabelDecimalValue(SkipLeadingLabels(name, skip+0)->c, &a->ip.v4.b[3])) return mStatus_Invalid;
1109         a->type = mDNSAddrType_IPv4;
1110         return(mStatus_NoError);
1111         }
1112
1113 #define HexVal(X) ( ((X) >= '0' && (X) <= '9') ? ((X) - '0'     ) :   \
1114                                         ((X) >= 'A' && (X) <= 'F') ? ((X) - 'A' + 10) :   \
1115                                         ((X) >= 'a' && (X) <= 'f') ? ((X) - 'a' + 10) : -1)
1116
1117 mDNSlocal mStatus GetIPv6FromName(mDNSAddr *const a, const domainname *const name)
1118         {
1119         int i, h, l;
1120         const domainname *n;
1121
1122         int skip = CountLabels(name) - 34;
1123         if (skip < 0) { LogMsg("GetIPFromName: Need 34 labels in IPv6 reverse mapping name %##s", name); return mStatus_Invalid; }
1124
1125         n = SkipLeadingLabels(name, skip);
1126         for (i=0; i<16; i++)
1127                 {
1128                 if (n->c[0] != 1) return mStatus_Invalid;
1129                 l = HexVal(n->c[1]);
1130                 n = (const domainname *)(n->c + 2);
1131
1132                 if (n->c[0] != 1) return mStatus_Invalid;
1133                 h = HexVal(n->c[1]);
1134                 n = (const domainname *)(n->c + 2);
1135
1136                 if (l<0 || h<0) return mStatus_Invalid;
1137                 a->ip.v6.b[15-i] = (mDNSu8)((h << 4) | l);
1138                 }
1139
1140         a->type = mDNSAddrType_IPv6;
1141         return(mStatus_NoError);
1142         }
1143
1144 mDNSlocal mDNSs32 ReverseMapDomainType(const domainname *const name)
1145         {
1146         int skip = CountLabels(name) - 2;
1147         if (skip >= 0)
1148                 {
1149                 const domainname *suffix = SkipLeadingLabels(name, skip);
1150                 if (SameDomainName(suffix, (const domainname*)"\x7" "in-addr" "\x4" "arpa")) return mDNSAddrType_IPv4;
1151                 if (SameDomainName(suffix, (const domainname*)"\x3" "ip6"     "\x4" "arpa")) return mDNSAddrType_IPv6;
1152                 }
1153         return(mDNSAddrType_None);
1154         }
1155
1156 mDNSlocal void SendARP(mDNS *const m, const mDNSu8 op, const AuthRecord *const rr,
1157         const mDNSu8 *const spa, const mDNSu8 *const tha, const mDNSu8 *const tpa, const mDNSu8 *const dst)
1158         {
1159         int i;
1160         mDNSu8 *ptr = m->omsg.data;
1161         NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID);
1162         if (!intf) { LogMsg("SendARP: No interface with InterfaceID %p found %s", rr->resrec.InterfaceID, ARDisplayString(m,rr)); return; }
1163
1164         // 0x00 Destination address
1165         for (i=0; i<6; i++) *ptr++ = dst[i];
1166
1167         // 0x06 Source address (we just use zero -- driver/hardware will fill in real interface address)
1168         for (i=0; i<6; i++) *ptr++ = 0x0;
1169
1170         // 0x0C ARP Ethertype (0x0806)
1171         *ptr++ = 0x08; *ptr++ = 0x06;
1172
1173         // 0x0E ARP header
1174         *ptr++ = 0x00; *ptr++ = 0x01;   // Hardware address space; Ethernet = 1
1175         *ptr++ = 0x08; *ptr++ = 0x00;   // Protocol address space; IP = 0x0800
1176         *ptr++ = 6;                                             // Hardware address length
1177         *ptr++ = 4;                                             // Protocol address length
1178         *ptr++ = 0x00; *ptr++ = op;             // opcode; Request = 1, Response = 2
1179
1180         // 0x16 Sender hardware address (our MAC address)
1181         for (i=0; i<6; i++) *ptr++ = intf->MAC.b[i];
1182
1183         // 0x1C Sender protocol address
1184         for (i=0; i<4; i++) *ptr++ = spa[i];
1185
1186         // 0x20 Target hardware address
1187         for (i=0; i<6; i++) *ptr++ = tha[i];
1188
1189         // 0x26 Target protocol address
1190         for (i=0; i<4; i++) *ptr++ = tpa[i];
1191
1192         // 0x2A Total ARP Packet length 42 bytes
1193         mDNSPlatformSendRawPacket(m->omsg.data, ptr, rr->resrec.InterfaceID);
1194         }
1195
1196 mDNSlocal void SetupOwnerOpt(const mDNS *const m, const NetworkInterfaceInfo *const intf, rdataOPT *const owner)
1197         {
1198         owner->u.owner.vers     = 0;
1199         owner->u.owner.seq      = m->SleepSeqNum;
1200         owner->u.owner.HMAC     = m->PrimaryMAC;
1201         owner->u.owner.IMAC     = intf->MAC;
1202         owner->u.owner.password = zeroEthAddr;
1203
1204         // Don't try to compute the optlen until *after* we've set up the data fields
1205         // Right now the DNSOpt_Owner_Space macro does not depend on the owner->u.owner being set up correctly, but in the future it might
1206         owner->opt              = kDNSOpt_Owner;
1207         owner->optlen           = DNSOpt_Owner_Space(&m->PrimaryMAC, &intf->MAC) - 4;
1208         }
1209
1210 mDNSlocal void GrantUpdateCredit(AuthRecord *rr)
1211         {
1212         if (++rr->UpdateCredits >= kMaxUpdateCredits) rr->NextUpdateCredit = 0;
1213         else rr->NextUpdateCredit = NonZeroTime(rr->NextUpdateCredit + kUpdateCreditRefreshInterval);
1214         }
1215
1216 // Note about acceleration of announcements to facilitate automatic coalescing of
1217 // multiple independent threads of announcements into a single synchronized thread:
1218 // The announcements in the packet may be at different stages of maturity;
1219 // One-second interval, two-second interval, four-second interval, and so on.
1220 // After we've put in all the announcements that are due, we then consider
1221 // whether there are other nearly-due announcements that are worth accelerating.
1222 // To be eligible for acceleration, a record MUST NOT be older (further along
1223 // its timeline) than the most mature record we've already put in the packet.
1224 // In other words, younger records can have their timelines accelerated to catch up
1225 // with their elder bretheren; this narrows the age gap and helps them eventually get in sync.
1226 // Older records cannot have their timelines accelerated; this would just widen
1227 // the gap between them and their younger bretheren and get them even more out of sync.
1228
1229 // Note: SendResponses calls mDNS_Deregister_internal which can call a user callback, which may change
1230 // the record list and/or question list.
1231 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
1232 mDNSlocal void SendResponses(mDNS *const m)
1233         {
1234         int pktcount = 0;
1235         AuthRecord *rr, *r2;
1236         mDNSs32 maxExistingAnnounceInterval = 0;
1237         const NetworkInterfaceInfo *intf = GetFirstActiveInterface(m->HostInterfaces);
1238
1239         m->NextScheduledResponse = m->timenow + 0x78000000;
1240
1241         if (m->SleepState == SleepState_Transferring) RetrySPSRegistrations(m);
1242
1243         for (rr = m->ResourceRecords; rr; rr=rr->next)
1244                 if (rr->ImmedUnicast)
1245                         {
1246                         mDNSAddr v4 = { mDNSAddrType_IPv4, {{{0}}} };
1247                         mDNSAddr v6 = { mDNSAddrType_IPv6, {{{0}}} };
1248                         v4.ip.v4 = rr->v4Requester;
1249                         v6.ip.v6 = rr->v6Requester;
1250                         if (!mDNSIPv4AddressIsZero(rr->v4Requester)) SendDelayedUnicastResponse(m, &v4, rr->ImmedAnswer);
1251                         if (!mDNSIPv6AddressIsZero(rr->v6Requester)) SendDelayedUnicastResponse(m, &v6, rr->ImmedAnswer);
1252                         if (rr->ImmedUnicast)
1253                                 {
1254                                 LogMsg("SendResponses: ERROR: rr->ImmedUnicast still set: %s", ARDisplayString(m, rr));
1255                                 rr->ImmedUnicast = mDNSfalse;
1256                                 }
1257                         }
1258
1259         // ***
1260         // *** 1. Setup: Set the SendRNow and ImmedAnswer fields to indicate which interface(s) the records need to be sent on
1261         // ***
1262
1263         // Run through our list of records, and decide which ones we're going to announce on all interfaces
1264         for (rr = m->ResourceRecords; rr; rr=rr->next)
1265                 {
1266                 while (rr->NextUpdateCredit && m->timenow - rr->NextUpdateCredit >= 0) GrantUpdateCredit(rr);
1267                 if (TimeToAnnounceThisRecord(rr, m->timenow) && ResourceRecordIsValidAnswer(rr))
1268                         {
1269                         if (rr->AddressProxy.type)
1270                                 {
1271                                 rr->AnnounceCount--;
1272                                 rr->ThisAPInterval *= 2;
1273                                 rr->LastAPTime = m->timenow;
1274                                 if (rr->AddressProxy.type == mDNSAddrType_IPv4)
1275                                         {
1276                                         LogSPS("ARP Announcement %d Capturing traffic for H-MAC %.6a I-MAC %.6a %s",
1277                                                 rr->AnnounceCount, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m,rr));
1278                                         SendARP(m, 1, rr, rr->AddressProxy.ip.v4.b, zeroEthAddr.b, rr->AddressProxy.ip.v4.b, onesEthAddr.b);
1279                                         }
1280                                 else if (rr->AddressProxy.type == mDNSAddrType_IPv6)
1281                                         {
1282                                         //LogSPS("NDP Announcement %d %s", rr->AnnounceCount, ARDisplayString(m,rr));
1283                                         //SendARP(m, 1, rr, rr->AddressProxy.ip.v4.b, zeroEthAddr.b, rr->AddressProxy.ip.v4.b, onesEthAddr.b);
1284                                         }
1285                                 }
1286                         else
1287                                 {
1288                                 rr->ImmedAnswer = mDNSInterfaceMark;            // Send on all interfaces
1289                                 if (maxExistingAnnounceInterval < rr->ThisAPInterval)
1290                                         maxExistingAnnounceInterval = rr->ThisAPInterval;
1291                                 if (rr->UpdateBlocked) rr->UpdateBlocked = 0;
1292                                 }
1293                         }
1294                 }
1295
1296         // Any interface-specific records we're going to send are marked as being sent on all appropriate interfaces (which is just one)
1297         // Eligible records that are more than half-way to their announcement time are accelerated
1298         for (rr = m->ResourceRecords; rr; rr=rr->next)
1299                 if ((rr->resrec.InterfaceID && rr->ImmedAnswer) ||
1300                         (rr->ThisAPInterval <= maxExistingAnnounceInterval &&
1301                         TimeToAnnounceThisRecord(rr, m->timenow + rr->ThisAPInterval/2) &&
1302                         !rr->AddressProxy.type &&                                       // Don't include ARP Annoucements when considering which records to accelerate
1303                         ResourceRecordIsValidAnswer(rr)))
1304                         rr->ImmedAnswer = mDNSInterfaceMark;            // Send on all interfaces
1305
1306         // When sending SRV records (particularly when announcing a new service) automatically add related Address record(s) as additionals
1307         // Note: Currently all address records are interface-specific, so it's safe to set ImmedAdditional to their InterfaceID,
1308         // which will be non-null. If by some chance there is an address record that's not interface-specific (should never happen)
1309         // then all that means is that it won't get sent -- which would not be the end of the world.
1310         for (rr = m->ResourceRecords; rr; rr=rr->next)
1311                 {
1312                 if (rr->ImmedAnswer && rr->resrec.rrtype == kDNSType_SRV)
1313                         for (r2=m->ResourceRecords; r2; r2=r2->next)                            // Scan list of resource records
1314                                 if (RRTypeIsAddressType(r2->resrec.rrtype) &&                   // For all address records (A/AAAA) ...
1315                                         ResourceRecordIsValidAnswer(r2) &&                                      // ... which are valid for answer ...
1316                                         rr->LastMCTime - r2->LastMCTime >= 0 &&                         // ... which we have not sent recently ...
1317                                         rr->resrec.rdatahash == r2->resrec.namehash &&          // ... whose name is the name of the SRV target
1318                                         SameDomainName(&rr->resrec.rdata->u.srv.target, r2->resrec.name) &&
1319                                         (rr->ImmedAnswer == mDNSInterfaceMark || rr->ImmedAnswer == r2->resrec.InterfaceID))
1320                                         r2->ImmedAdditional = r2->resrec.InterfaceID;           // ... then mark this address record for sending too
1321                 // We also make sure we send the DeviceInfo TXT record too, if necessary
1322                 // We check for RecordType == kDNSRecordTypeShared because we don't want to tag the
1323                 // DeviceInfo TXT record onto a goodbye packet (RecordType == kDNSRecordTypeDeregistering).
1324                 if (rr->ImmedAnswer && rr->resrec.RecordType == kDNSRecordTypeShared && rr->resrec.rrtype == kDNSType_PTR)
1325                         if (ResourceRecordIsValidAnswer(&m->DeviceInfo) && SameDomainLabel(rr->resrec.rdata->u.name.c, m->DeviceInfo.resrec.name->c))
1326                                 {
1327                                 if (!m->DeviceInfo.ImmedAnswer) m->DeviceInfo.ImmedAnswer = rr->ImmedAnswer;
1328                                 else                            m->DeviceInfo.ImmedAnswer = mDNSInterfaceMark;
1329                                 }
1330                 }
1331
1332         // If there's a record which is supposed to be unique that we're going to send, then make sure that we give
1333         // the whole RRSet as an atomic unit. That means that if we have any other records with the same name/type/class
1334         // then we need to mark them for sending too. Otherwise, if we set the kDNSClass_UniqueRRSet bit on a
1335         // record, then other RRSet members that have not been sent recently will get flushed out of client caches.
1336         // -- If a record is marked to be sent on a certain interface, make sure the whole set is marked to be sent on that interface
1337         // -- If any record is marked to be sent on all interfaces, make sure the whole set is marked to be sent on all interfaces
1338         for (rr = m->ResourceRecords; rr; rr=rr->next)
1339                 if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
1340                         {
1341                         if (rr->ImmedAnswer)                    // If we're sending this as answer, see that its whole RRSet is similarly marked
1342                                 {
1343                                 for (r2 = m->ResourceRecords; r2; r2=r2->next)
1344                                         if (ResourceRecordIsValidAnswer(r2))
1345                                                 if (r2->ImmedAnswer != mDNSInterfaceMark &&
1346                                                         r2->ImmedAnswer != rr->ImmedAnswer && SameResourceRecordSignature(r2, rr))
1347                                                         r2->ImmedAnswer = !r2->ImmedAnswer ? rr->ImmedAnswer : mDNSInterfaceMark;
1348                                 }
1349                         else if (rr->ImmedAdditional)   // If we're sending this as additional, see that its whole RRSet is similarly marked
1350                                 {
1351                                 for (r2 = m->ResourceRecords; r2; r2=r2->next)
1352                                         if (ResourceRecordIsValidAnswer(r2))
1353                                                 if (r2->ImmedAdditional != rr->ImmedAdditional && SameResourceRecordSignature(r2, rr))
1354                                                         r2->ImmedAdditional = rr->ImmedAdditional;
1355                                 }
1356                         }
1357
1358         // Now set SendRNow state appropriately
1359         for (rr = m->ResourceRecords; rr; rr=rr->next)
1360                 {
1361                 if (rr->ImmedAnswer == mDNSInterfaceMark)               // Sending this record on all appropriate interfaces
1362                         {
1363                         rr->SendRNow = !intf ? mDNSNULL : (rr->resrec.InterfaceID) ? rr->resrec.InterfaceID : intf->InterfaceID;
1364                         rr->ImmedAdditional = mDNSNULL;                         // No need to send as additional if sending as answer
1365                         rr->LastMCTime      = m->timenow;
1366                         rr->LastMCInterface = rr->ImmedAnswer;
1367                         // If we're announcing this record, and it's at least half-way to its ordained time, then consider this announcement done
1368                         if (TimeToAnnounceThisRecord(rr, m->timenow + rr->ThisAPInterval/2))
1369                                 {
1370                                 rr->AnnounceCount--;
1371                                 rr->ThisAPInterval *= 2;
1372                                 rr->LastAPTime = m->timenow;
1373                                 debugf("Announcing %##s (%s) %d", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->AnnounceCount);
1374                                 }
1375                         }
1376                 else if (rr->ImmedAnswer)                                               // Else, just respond to a single query on single interface:
1377                         {
1378                         rr->SendRNow        = rr->ImmedAnswer;          // Just respond on that interface
1379                         rr->ImmedAdditional = mDNSNULL;                         // No need to send as additional too
1380                         rr->LastMCTime      = m->timenow;
1381                         rr->LastMCInterface = rr->ImmedAnswer;
1382                         }
1383                 SetNextAnnounceProbeTime(m, rr);
1384                 //if (rr->SendRNow) LogMsg("%-15.4a %s", &rr->v4Requester, ARDisplayString(m, rr));
1385                 }
1386
1387         // ***
1388         // *** 2. Loop through interface list, sending records as appropriate
1389         // ***
1390
1391         while (intf)
1392                 {
1393                 const int OwnerRecordSpace = (m->AnnounceOwner && intf->MAC.l[0]) ? DNSOpt_Header_Space + DNSOpt_Owner_Space(&m->PrimaryMAC, &intf->MAC) : 0;
1394                 int numDereg    = 0;
1395                 int numAnnounce = 0;
1396                 int numAnswer   = 0;
1397                 mDNSu8 *responseptr = m->omsg.data;
1398                 mDNSu8 *newptr;
1399                 InitializeDNSMessage(&m->omsg.h, zeroID, ResponseFlags);
1400         
1401                 // First Pass. Look for:
1402                 // 1. Deregistering records that need to send their goodbye packet
1403                 // 2. Updated records that need to retract their old data
1404                 // 3. Answers and announcements we need to send
1405                 for (rr = m->ResourceRecords; rr; rr=rr->next)
1406                         {
1407                         if (rr->SendRNow == intf->InterfaceID)
1408                                 {
1409                                 newptr = mDNSNULL;
1410                                 if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
1411                                         {
1412                                         newptr = PutRR_OS_TTL(responseptr, &m->omsg.h.numAnswers, &rr->resrec, 0);
1413                                         if (newptr) { responseptr = newptr; numDereg++; }
1414                                         }
1415                                 else if (rr->NewRData && !m->SleepState)                                        // If we have new data for this record
1416                                         {
1417                                         RData *OldRData     = rr->resrec.rdata;
1418                                         mDNSu16 oldrdlength = rr->resrec.rdlength;
1419                                         // See if we should send a courtesy "goodbye" for the old data before we replace it.
1420                                         if (ResourceRecordIsValidAnswer(rr) && rr->RequireGoodbye)
1421                                                 {
1422                                                 newptr = PutRR_OS_TTL(responseptr, &m->omsg.h.numAnswers, &rr->resrec, 0);
1423                                                 if (newptr) { responseptr = newptr; numDereg++; rr->RequireGoodbye = mDNSfalse; }
1424                                                 }
1425                                         // Now try to see if we can fit the update in the same packet (not fatal if we can't)
1426                                         SetNewRData(&rr->resrec, rr->NewRData, rr->newrdlength);
1427                                         if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
1428                                                 rr->resrec.rrclass |= kDNSClass_UniqueRRSet;            // Temporarily set the cache flush bit so PutResourceRecord will set it
1429                                         newptr = PutRR_OS(responseptr, &m->omsg.h.numAnswers, &rr->resrec);
1430                                         rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;                   // Make sure to clear cache flush bit back to normal state
1431                                         if (newptr) { responseptr = newptr; rr->RequireGoodbye = mDNStrue; }
1432                                         SetNewRData(&rr->resrec, OldRData, oldrdlength);
1433                                         }
1434                                 else
1435                                         {
1436                                         mDNSu8 active = (mDNSu8)
1437                                                 (m->SleepState != SleepState_Sleeping || intf->SPSAddr[0].type || intf->SPSAddr[1].type || intf->SPSAddr[2].type);
1438                                         if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
1439                                                 rr->resrec.rrclass |= kDNSClass_UniqueRRSet;            // Temporarily set the cache flush bit so PutResourceRecord will set it
1440                                         newptr = PutRR_OS_TTL(responseptr, &m->omsg.h.numAnswers, &rr->resrec, active ? rr->resrec.rroriginalttl : 0);
1441                                         rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;                   // Make sure to clear cache flush bit back to normal state
1442                                         if (newptr)
1443                                                 {
1444                                                 responseptr = newptr;
1445                                                 rr->RequireGoodbye = active;
1446                                                 if (rr->LastAPTime == m->timenow) numAnnounce++; else numAnswer++;
1447                                                 }
1448
1449                                         // The first time through (pktcount==0), if this record is verified unique
1450                                         // (i.e. typically A, AAAA, SRV and TXT), set the flag to add an NSEC too.
1451                                         if (!pktcount && active && rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->SendNSECNow) rr->SendNSECNow = mDNSInterfaceMark;
1452                                         }
1453
1454                                 if (newptr)             // If succeeded in sending, advance to next interface
1455                                         {
1456                                         // If sending on all interfaces, go to next interface; else we're finished now
1457                                         if (rr->ImmedAnswer == mDNSInterfaceMark && rr->resrec.InterfaceID == mDNSInterface_Any)
1458                                                 rr->SendRNow = GetNextActiveInterfaceID(intf);
1459                                         else
1460                                                 rr->SendRNow = mDNSNULL;
1461                                         }
1462                                 }
1463                         }
1464         
1465                 // Second Pass. Add additional records, if there's space.
1466                 newptr = responseptr;
1467                 for (rr = m->ResourceRecords; rr; rr=rr->next)
1468                         if (rr->ImmedAdditional == intf->InterfaceID)
1469                                 if (ResourceRecordIsValidAnswer(rr))
1470                                         {
1471                                         // If we have at least one answer already in the packet, then plan to add additionals too
1472                                         mDNSBool SendAdditional = (m->omsg.h.numAnswers > 0);
1473                                         
1474                                         // If we're not planning to send any additionals, but this record is a unique one, then
1475                                         // make sure we haven't already sent any other members of its RRSet -- if we have, then they
1476                                         // will have had the cache flush bit set, so now we need to finish the job and send the rest.
1477                                         if (!SendAdditional && (rr->resrec.RecordType & kDNSRecordTypeUniqueMask))
1478                                                 {
1479                                                 const AuthRecord *a;
1480                                                 for (a = m->ResourceRecords; a; a=a->next)
1481                                                         if (a->LastMCTime      == m->timenow &&
1482                                                                 a->LastMCInterface == intf->InterfaceID &&
1483                                                                 SameResourceRecordSignature(a, rr)) { SendAdditional = mDNStrue; break; }
1484                                                 }
1485                                         if (!SendAdditional)                                    // If we don't want to send this after all,
1486                                                 rr->ImmedAdditional = mDNSNULL;         // then cancel its ImmedAdditional field
1487                                         else if (newptr)                                                // Else, try to add it if we can
1488                                                 {
1489                                                 // The first time through (pktcount==0), if this record is verified unique
1490                                                 // (i.e. typically A, AAAA, SRV and TXT), set the flag to add an NSEC too.
1491                                                 if (!pktcount && rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->SendNSECNow) rr->SendNSECNow = mDNSInterfaceMark;
1492
1493                                                 if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
1494                                                         rr->resrec.rrclass |= kDNSClass_UniqueRRSet;    // Temporarily set the cache flush bit so PutResourceRecord will set it
1495                                                 newptr = PutRR_OS(newptr, &m->omsg.h.numAdditionals, &rr->resrec);
1496                                                 rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;           // Make sure to clear cache flush bit back to normal state
1497                                                 if (newptr)
1498                                                         {
1499                                                         responseptr = newptr;
1500                                                         rr->ImmedAdditional = mDNSNULL;
1501                                                         rr->RequireGoodbye = mDNStrue;
1502                                                         // If we successfully put this additional record in the packet, we record LastMCTime & LastMCInterface.
1503                                                         // This matters particularly in the case where we have more than one IPv6 (or IPv4) address, because otherwise,
1504                                                         // when we see our own multicast with the cache flush bit set, if we haven't set LastMCTime, then we'll get
1505                                                         // all concerned and re-announce our record again to make sure it doesn't get flushed from peer caches.
1506                                                         rr->LastMCTime      = m->timenow;
1507                                                         rr->LastMCInterface = intf->InterfaceID;
1508                                                         }
1509                                                 }
1510                                         }
1511
1512                 // Third Pass. Add NSEC records, if there's space.
1513                 for (rr = m->ResourceRecords; rr; rr=rr->next)
1514                         if (rr->SendNSECNow == mDNSInterfaceMark || rr->SendNSECNow == intf->InterfaceID)
1515                                 {
1516                                 AuthRecord nsec;
1517                                 mDNS_SetupResourceRecord(&nsec, mDNSNULL, mDNSInterface_Any, kDNSType_NSEC, rr->resrec.rroriginalttl, kDNSRecordTypeUnique, mDNSNULL, mDNSNULL);
1518                                 nsec.resrec.rrclass |= kDNSClass_UniqueRRSet;
1519                                 AssignDomainName(&nsec.namestorage, rr->resrec.name);
1520                                 mDNSPlatformMemZero(nsec.rdatastorage.u.nsec.bitmap, sizeof(nsec.rdatastorage.u.nsec.bitmap));
1521                                 for (r2 = m->ResourceRecords; r2; r2=r2->next)
1522                                         if (ResourceRecordIsValidAnswer(r2) && SameResourceRecordNameClassInterface(r2, rr))
1523                                                 {
1524                                                 if (r2->resrec.rrtype >= kDNSQType_ANY) { LogMsg("Can't create NSEC for record %s", ARDisplayString(m, r2)); break; }
1525                                                 else nsec.rdatastorage.u.nsec.bitmap[r2->resrec.rrtype >> 3] |= 128 >> (r2->resrec.rrtype & 7);
1526                                                 }
1527                                 newptr = responseptr;
1528                                 if (!r2)        // If we successfully built our NSEC record, add it to the packet now
1529                                         {
1530                                         newptr = PutRR_OS(responseptr, &m->omsg.h.numAdditionals, &nsec.resrec);
1531                                         if (newptr) responseptr = newptr;
1532                                         }
1533
1534                                 // If we successfully put the NSEC record, clear the SendNSECNow flag
1535                                 // If we consider this NSEC optional, then we unconditionally clear the SendNSECNow flag, even if we fail to put this additional record
1536                                 if (newptr || rr->SendNSECNow == mDNSInterfaceMark)
1537                                         {
1538                                         rr->SendNSECNow = mDNSNULL;
1539                                         // Run through remainder of list clearing SendNSECNow flag for all other records which would generate the same NSEC
1540                                         for (r2 = rr->next; r2; r2=r2->next)
1541                                                 if (SameResourceRecordNameClassInterface(r2, rr))
1542                                                         if (r2->SendNSECNow == mDNSInterfaceMark || r2->SendNSECNow == intf->InterfaceID)
1543                                                                 r2->SendNSECNow = mDNSNULL;
1544                                         }
1545                                 }
1546
1547                 if (m->omsg.h.numAnswers || m->omsg.h.numAdditionals)
1548                         {
1549                         // If we have data to send, add OWNER option if necessary, then send packet
1550
1551                         if (OwnerRecordSpace)
1552                                 {
1553                                 AuthRecord opt;
1554                                 mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
1555                                 opt.resrec.rrclass    = NormalMaxDNSMessageData;
1556                                 opt.resrec.rdlength   = sizeof(rdataOPT);       // One option in this OPT record
1557                                 opt.resrec.rdestimate = sizeof(rdataOPT);
1558                                 SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[0]);
1559                                 newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAdditionals, &opt.resrec);
1560                                 if (newptr) { responseptr = newptr; LogSPS("SendResponses put %s", ARDisplayString(m, &opt)); }
1561                                 else LogMsg("SendResponses: How did we fail to have space for the OPT record (%d/%d/%d/%d) %s",
1562                                         m->omsg.h.numQuestions, m->omsg.h.numAnswers, m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt));
1563                                 }
1564
1565                         debugf("SendResponses: Sending %d Deregistration%s, %d Announcement%s, %d Answer%s, %d Additional%s on %p",
1566                                 numDereg,                 numDereg                 == 1 ? "" : "s",
1567                                 numAnnounce,              numAnnounce              == 1 ? "" : "s",
1568                                 numAnswer,                numAnswer                == 1 ? "" : "s",
1569                                 m->omsg.h.numAdditionals, m->omsg.h.numAdditionals == 1 ? "" : "s", intf->InterfaceID);
1570                         if (intf->IPv4Available) mDNSSendDNSMessage(m, &m->omsg, responseptr, intf->InterfaceID, mDNSNULL, &AllDNSLinkGroup_v4, MulticastDNSPort, mDNSNULL, mDNSNULL);
1571                         if (intf->IPv6Available) mDNSSendDNSMessage(m, &m->omsg, responseptr, intf->InterfaceID, mDNSNULL, &AllDNSLinkGroup_v6, MulticastDNSPort, mDNSNULL, mDNSNULL);
1572                         if (!m->SuppressSending) m->SuppressSending = NonZeroTime(m->timenow + (mDNSPlatformOneSecond+9)/10);
1573                         if (++pktcount >= 1000) { LogMsg("SendResponses exceeded loop limit %d: giving up", pktcount); break; }
1574                         // There might be more things to send on this interface, so go around one more time and try again.
1575                         }
1576                 else    // Nothing more to send on this interface; go to next
1577                         {
1578                         const NetworkInterfaceInfo *next = GetFirstActiveInterface(intf->next);
1579                         #if MDNS_DEBUGMSGS && 0
1580                         const char *const msg = next ? "SendResponses: Nothing more on %p; moving to %p" : "SendResponses: Nothing more on %p";
1581                         debugf(msg, intf, next);
1582                         #endif
1583                         intf = next;
1584                         pktcount = 0;           // When we move to a new interface, reset packet count back to zero -- NSEC generation logic uses it
1585                         }
1586                 }
1587
1588         // ***
1589         // *** 3. Cleanup: Now that everything is sent, call client callback functions, and reset state variables
1590         // ***
1591
1592         if (m->CurrentRecord)
1593                 LogMsg("SendResponses ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
1594         m->CurrentRecord = m->ResourceRecords;
1595         while (m->CurrentRecord)
1596                 {
1597                 rr = m->CurrentRecord;
1598                 m->CurrentRecord = rr->next;
1599
1600                 if (rr->SendRNow)
1601                         {
1602                         if (rr->resrec.InterfaceID != mDNSInterface_LocalOnly)
1603                                 LogMsg("SendResponses: No active interface to send: %02X %s", rr->resrec.RecordType, ARDisplayString(m, rr));
1604                         rr->SendRNow = mDNSNULL;
1605                         }
1606
1607                 if (rr->ImmedAnswer)
1608                         {
1609                         if (rr->NewRData) CompleteRDataUpdate(m, rr);   // Update our rdata, clear the NewRData pointer, and return memory to the client
1610         
1611                         if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
1612                                 CompleteDeregistration(m, rr);          // Don't touch rr after this
1613                         else
1614                                 {
1615                                 rr->ImmedAnswer  = mDNSNULL;
1616                                 rr->ImmedUnicast = mDNSfalse;
1617                                 rr->v4Requester  = zerov4Addr;
1618                                 rr->v6Requester  = zerov6Addr;
1619                                 }
1620                         }
1621                 }
1622         verbosedebugf("SendResponses: Next in %ld ticks", m->NextScheduledResponse - m->timenow);
1623         }
1624
1625 // Calling CheckCacheExpiration() is an expensive operation because it has to look at the entire cache,
1626 // so we want to be lazy about how frequently we do it.
1627 // 1. If a cache record is currently referenced by *no* active questions,
1628 //    then we don't mind expiring it up to a minute late (who will know?)
1629 // 2. Else, if a cache record is due for some of its final expiration queries,
1630 //    we'll allow them to be late by up to 2% of the TTL
1631 // 3. Else, if a cache record has completed all its final expiration queries without success,
1632 //    and is expiring, and had an original TTL more than ten seconds, we'll allow it to be one second late
1633 // 4. Else, it is expiring and had an original TTL of ten seconds or less (includes explicit goodbye packets),
1634 //    so allow at most 1/10 second lateness
1635 // 5. For records with rroriginalttl set to zero, that means we really want to delete them immediately
1636 //    (we have a new record with DelayDelivery set, waiting for the old record to go away before we can notify clients).
1637 #define CacheCheckGracePeriod(RR) (                                                   \
1638         ((RR)->DelayDelivery                           ) ? (mDNSPlatformOneSecond/10)   : \
1639         ((RR)->CRActiveQuestion == mDNSNULL            ) ? (60 * mDNSPlatformOneSecond) : \
1640         ((RR)->UnansweredQueries < MaxUnansweredQueries) ? (TicksTTL(rr)/50)            : \
1641         ((RR)->resrec.rroriginalttl > 10               ) ? (mDNSPlatformOneSecond)      : \
1642         ((RR)->resrec.rroriginalttl > 0                ) ? (mDNSPlatformOneSecond/10)   : 0)
1643
1644 // Note: MUST call SetNextCacheCheckTime any time we change:
1645 // rr->TimeRcvd
1646 // rr->resrec.rroriginalttl
1647 // rr->UnansweredQueries
1648 // rr->CRActiveQuestion
1649 // Also, any time we set rr->DelayDelivery we should call SetNextCacheCheckTime to ensure m->NextCacheCheck is set if necessary
1650 // Clearing rr->DelayDelivery does not require a call to SetNextCacheCheckTime
1651 mDNSlocal void SetNextCacheCheckTime(mDNS *const m, CacheRecord *const rr)
1652         {
1653         rr->NextRequiredQuery = RRExpireTime(rr);
1654
1655         // If we have an active question, then see if we want to schedule a refresher query for this record.
1656         // Usually we expect to do four queries, at 80-82%, 85-87%, 90-92% and then 95-97% of the TTL.
1657         if (rr->CRActiveQuestion && rr->UnansweredQueries < MaxUnansweredQueries)
1658                 {
1659                 rr->NextRequiredQuery -= TicksTTL(rr)/20 * (MaxUnansweredQueries - rr->UnansweredQueries);
1660                 rr->NextRequiredQuery += mDNSRandom((mDNSu32)TicksTTL(rr)/50);
1661                 verbosedebugf("SetNextCacheCheckTime: %##s (%s) NextRequiredQuery in %ld sec CacheCheckGracePeriod %d ticks",
1662                         rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype),
1663                         (rr->NextRequiredQuery - m->timenow) / mDNSPlatformOneSecond, CacheCheckGracePeriod(rr));
1664                 }
1665
1666         if (m->NextCacheCheck - (rr->NextRequiredQuery + CacheCheckGracePeriod(rr)) > 0)
1667                 m->NextCacheCheck = (rr->NextRequiredQuery + CacheCheckGracePeriod(rr));
1668         
1669         if (rr->DelayDelivery)
1670                 if (m->NextCacheCheck - rr->DelayDelivery > 0)
1671                         m->NextCacheCheck = rr->DelayDelivery;
1672         }
1673
1674 #define kMinimumReconfirmTime                     ((mDNSu32)mDNSPlatformOneSecond *  5)
1675 #define kDefaultReconfirmTimeForWake              ((mDNSu32)mDNSPlatformOneSecond *  5)
1676 #define kDefaultReconfirmTimeForNoAnswer          ((mDNSu32)mDNSPlatformOneSecond *  5)
1677 #define kDefaultReconfirmTimeForFlappingInterface ((mDNSu32)mDNSPlatformOneSecond * 30)
1678
1679 mDNSlocal mStatus mDNS_Reconfirm_internal(mDNS *const m, CacheRecord *const rr, mDNSu32 interval)
1680         {
1681         if (interval < kMinimumReconfirmTime)
1682                 interval = kMinimumReconfirmTime;
1683         if (interval > 0x10000000)      // Make sure interval doesn't overflow when we multiply by four below
1684                 interval = 0x10000000;
1685
1686         // If the expected expiration time for this record is more than interval+33%, then accelerate its expiration
1687         if (RRExpireTime(rr) - m->timenow > (mDNSs32)((interval * 4) / 3))
1688                 {
1689                 // Add a 33% random amount to the interval, to avoid synchronization between multiple hosts
1690                 // For all the reconfirmations in a given batch, we want to use the same random value
1691                 // so that the reconfirmation questions can be grouped into a single query packet
1692                 if (!m->RandomReconfirmDelay) m->RandomReconfirmDelay = 1 + mDNSRandom(0x3FFFFFFF);
1693                 interval += m->RandomReconfirmDelay % ((interval/3) + 1);
1694                 rr->TimeRcvd          = m->timenow - (mDNSs32)interval * 3;
1695                 rr->resrec.rroriginalttl     = (interval * 4 + mDNSPlatformOneSecond - 1) / mDNSPlatformOneSecond;
1696                 SetNextCacheCheckTime(m, rr);
1697                 }
1698         debugf("mDNS_Reconfirm_internal:%6ld ticks to go for %s %p",
1699                 RRExpireTime(rr) - m->timenow, CRDisplayString(m, rr), rr->CRActiveQuestion);
1700         return(mStatus_NoError);
1701         }
1702
1703 #define MaxQuestionInterval         (3600 * mDNSPlatformOneSecond)
1704
1705 // BuildQuestion puts a question into a DNS Query packet and if successful, updates the value of queryptr.
1706 // It also appends to the list of known answer records that need to be included,
1707 // and updates the forcast for the size of the known answer section.
1708 mDNSlocal mDNSBool BuildQuestion(mDNS *const m, DNSMessage *query, mDNSu8 **queryptr, DNSQuestion *q,
1709         CacheRecord ***kalistptrptr, mDNSu32 *answerforecast)
1710         {
1711         mDNSBool ucast = (q->LargeAnswers || q->RequestUnicast) && m->CanReceiveUnicastOn5353;
1712         mDNSu16 ucbit = (mDNSu16)(ucast ? kDNSQClass_UnicastResponse : 0);
1713         const mDNSu8 *const limit = query->data + NormalMaxDNSMessageData;
1714         mDNSu8 *newptr = putQuestion(query, *queryptr, limit - *answerforecast, &q->qname, q->qtype, (mDNSu16)(q->qclass | ucbit));
1715         if (!newptr)
1716                 {
1717                 debugf("BuildQuestion: No more space in this packet for question %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
1718                 return(mDNSfalse);
1719                 }
1720         else
1721                 {
1722                 mDNSu32 forecast = *answerforecast;
1723                 const mDNSu32 slot = HashSlot(&q->qname);
1724                 const CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
1725                 CacheRecord *rr;
1726                 CacheRecord **ka = *kalistptrptr;       // Make a working copy of the pointer we're going to update
1727
1728                 for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)                         // If we have a resource record in our cache,
1729                         if (rr->resrec.InterfaceID == q->SendQNow &&                                    // received on this interface
1730                                 rr->NextInKAList == mDNSNULL && ka != &rr->NextInKAList &&      // which is not already in the known answer list
1731                                 rr->resrec.rdlength <= SmallRecordLimit &&                                      // which is small enough to sensibly fit in the packet
1732                                 SameNameRecordAnswersQuestion(&rr->resrec, q) &&                        // which answers our question
1733                                 rr->TimeRcvd + TicksTTL(rr)/2 - m->timenow >                            // and its half-way-to-expiry time is at least 1 second away
1734                                                                                                 mDNSPlatformOneSecond)          // (also ensures we never include goodbye records with TTL=1)
1735                                 {
1736                                 *ka = rr;       // Link this record into our known answer chain
1737                                 ka = &rr->NextInKAList;
1738                                 // We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n)
1739                                 forecast += 12 + rr->resrec.rdestimate;
1740                                 // If we're trying to put more than one question in this packet, and it doesn't fit
1741                                 // then undo that last question and try again next time
1742                                 if (query->h.numQuestions > 1 && newptr + forecast >= limit)
1743                                         {
1744                                         debugf("BuildQuestion: Retracting question %##s (%s) new forecast total %d",
1745                                                 q->qname.c, DNSTypeName(q->qtype), newptr + forecast - query->data);
1746                                         query->h.numQuestions--;
1747                                         ka = *kalistptrptr;             // Go back to where we started and retract these answer records
1748                                         while (*ka) { CacheRecord *c = *ka; *ka = mDNSNULL; ka = &c->NextInKAList; }
1749                                         return(mDNSfalse);              // Return false, so we'll try again in the next packet
1750                                         }
1751                                 }
1752
1753                 // Success! Update our state pointers, increment UnansweredQueries as appropriate, and return
1754                 *queryptr        = newptr;                              // Update the packet pointer
1755                 *answerforecast  = forecast;                    // Update the forecast
1756                 *kalistptrptr    = ka;                                  // Update the known answer list pointer
1757                 if (ucast) q->ExpectUnicastResp = NonZeroTime(m->timenow);
1758
1759                 for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)                         // For every resource record in our cache,
1760                         if (rr->resrec.InterfaceID == q->SendQNow &&                                    // received on this interface
1761                                 rr->NextInKAList == mDNSNULL && ka != &rr->NextInKAList &&      // which is not in the known answer list
1762                                 SameNameRecordAnswersQuestion(&rr->resrec, q))                          // which answers our question
1763                                         {
1764                                         rr->UnansweredQueries++;                                                                // indicate that we're expecting a response
1765                                         rr->LastUnansweredTime = m->timenow;
1766                                         SetNextCacheCheckTime(m, rr);
1767                                         }
1768
1769                 return(mDNStrue);
1770                 }
1771         }
1772
1773 // When we have a query looking for a specified name, but there appear to be no answers with
1774 // that name, ReconfirmAntecedents() is called with depth=0 to start the reconfirmation process
1775 // for any records in our cache that reference the given name (e.g. PTR and SRV records).
1776 // For any such cache record we find, we also recursively call ReconfirmAntecedents() for *its* name.
1777 // We increment depth each time we recurse, to guard against possible infinite loops, with a limit of 5.
1778 // A typical reconfirmation scenario might go like this:
1779 // Depth 0: Name "myhost.local" has no address records
1780 // Depth 1: SRV "My Service._example._tcp.local." refers to "myhost.local"; may be stale
1781 // Depth 2: PTR "_example._tcp.local." refers to "My Service"; may be stale
1782 // Depth 3: PTR "_services._dns-sd._udp.local." refers to "_example._tcp.local."; may be stale
1783 // Currently depths 4 and 5 are not expected to occur; if we did get to depth 5 we'd reconfim any records we
1784 // found referring to the given name, but not recursively descend any further reconfirm *their* antecedents.
1785 mDNSlocal void ReconfirmAntecedents(mDNS *const m, const domainname *const name, const mDNSu32 namehash, const int depth)
1786         {
1787         mDNSu32 slot;
1788         CacheGroup *cg;
1789         CacheRecord *cr;
1790         debugf("ReconfirmAntecedents (depth=%d) for %##s", depth, name->c);
1791         FORALL_CACHERECORDS(slot, cg, cr)
1792                 {
1793                 domainname *crtarget = GetRRDomainNameTarget(&cr->resrec);
1794                 if (crtarget && cr->resrec.rdatahash == namehash && SameDomainName(crtarget, name))
1795                         {
1796                         LogInfo("ReconfirmAntecedents: Reconfirming (depth=%d) %s", depth, CRDisplayString(m, cr));
1797                         mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
1798                         if (depth < 5) ReconfirmAntecedents(m, cr->resrec.name, cr->resrec.namehash, depth+1);
1799                         }
1800                 }
1801         }
1802
1803 // If we get no answer for a AAAA query, then before doing an automatic implicit ReconfirmAntecedents
1804 // we check if we have an address record for the same name. If we do have an IPv4 address for a given
1805 // name but not an IPv6 address, that's okay (it just means the device doesn't do IPv6) so the failure
1806 // to get a AAAA response is not grounds to doubt the PTR/SRV chain that lead us to that name.
1807 mDNSlocal const CacheRecord *CacheHasAddressTypeForName(mDNS *const m, const domainname *const name, const mDNSu32 namehash)
1808         {
1809         CacheGroup *const cg = CacheGroupForName(m, HashSlot(name), namehash, name);
1810         const CacheRecord *cr = cg ? cg->members : mDNSNULL;
1811         while (cr && !RRTypeIsAddressType(cr->resrec.rrtype)) cr=cr->next;
1812         return(cr);
1813         }
1814
1815 mDNSlocal const CacheRecord *FindSPSInCache1(mDNS *const m, const DNSQuestion *const q, const CacheRecord *const c0, const CacheRecord *const c1)
1816         {
1817         CacheGroup *const cg = CacheGroupForName(m, HashSlot(&q->qname), q->qnamehash, &q->qname);
1818         const CacheRecord *cr, *bestcr = mDNSNULL;
1819         mDNSu32 bestmetric = 1000000;
1820         for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)
1821                 if (cr->resrec.rrtype == kDNSType_PTR && cr->resrec.rdlength >= 6)                                              // If record is PTR type, with long enough name,
1822                         if (cr != c0 && cr != c1)                                                                                                                       // that's not one we've seen before,
1823                                 if (SameNameRecordAnswersQuestion(&cr->resrec, q))                                                              // and answers our browse query,
1824                                         if (!IdenticalSameNameRecord(&cr->resrec, &m->SPSRecords.RR_PTR.resrec))        // and is not our own advertised service...
1825                                                 {
1826                                                 mDNSu32 metric = SPSMetric(cr->resrec.rdata->u.name.c);
1827                                                 if (bestmetric > metric) { bestmetric = metric; bestcr = cr; }
1828                                                 }
1829         return(bestcr);
1830         }
1831
1832 // Finds the three best Sleep Proxies we currently have in our cache
1833 mDNSexport void FindSPSInCache(mDNS *const m, const DNSQuestion *const q, const CacheRecord *sps[3])
1834         {
1835         sps[0] =                      FindSPSInCache1(m, q, mDNSNULL, mDNSNULL);
1836         sps[1] = !sps[0] ? mDNSNULL : FindSPSInCache1(m, q, sps[0],   mDNSNULL);
1837         sps[2] = !sps[1] ? mDNSNULL : FindSPSInCache1(m, q, sps[0],   sps[1]);
1838         }
1839
1840 // Only DupSuppressInfos newer than the specified 'time' are allowed to remain active
1841 mDNSlocal void ExpireDupSuppressInfo(DupSuppressInfo ds[DupSuppressInfoSize], mDNSs32 time)
1842         {
1843         int i;
1844         for (i=0; i<DupSuppressInfoSize; i++) if (ds[i].Time - time < 0) ds[i].InterfaceID = mDNSNULL;
1845         }
1846
1847 mDNSlocal void ExpireDupSuppressInfoOnInterface(DupSuppressInfo ds[DupSuppressInfoSize], mDNSs32 time, mDNSInterfaceID InterfaceID)
1848         {
1849         int i;
1850         for (i=0; i<DupSuppressInfoSize; i++) if (ds[i].InterfaceID == InterfaceID && ds[i].Time - time < 0) ds[i].InterfaceID = mDNSNULL;
1851         }
1852
1853 mDNSlocal mDNSBool SuppressOnThisInterface(const DupSuppressInfo ds[DupSuppressInfoSize], const NetworkInterfaceInfo * const intf)
1854         {
1855         int i;
1856         mDNSBool v4 = !intf->IPv4Available;             // If this interface doesn't do v4, we don't need to find a v4 duplicate of this query
1857         mDNSBool v6 = !intf->IPv6Available;             // If this interface doesn't do v6, we don't need to find a v6 duplicate of this query
1858         for (i=0; i<DupSuppressInfoSize; i++)
1859                 if (ds[i].InterfaceID == intf->InterfaceID)
1860                         {
1861                         if      (ds[i].Type == mDNSAddrType_IPv4) v4 = mDNStrue;
1862                         else if (ds[i].Type == mDNSAddrType_IPv6) v6 = mDNStrue;
1863                         if (v4 && v6) return(mDNStrue);
1864                         }
1865         return(mDNSfalse);
1866         }
1867
1868 mDNSlocal int RecordDupSuppressInfo(DupSuppressInfo ds[DupSuppressInfoSize], mDNSs32 Time, mDNSInterfaceID InterfaceID, mDNSs32 Type)
1869         {
1870         int i, j;
1871
1872         // See if we have this one in our list somewhere already
1873         for (i=0; i<DupSuppressInfoSize; i++) if (ds[i].InterfaceID == InterfaceID && ds[i].Type == Type) break;
1874
1875         // If not, find a slot we can re-use
1876         if (i >= DupSuppressInfoSize)
1877                 {
1878                 i = 0;
1879                 for (j=1; j<DupSuppressInfoSize && ds[i].InterfaceID; j++)
1880                         if (!ds[j].InterfaceID || ds[j].Time - ds[i].Time < 0)
1881                                 i = j;
1882                 }
1883         
1884         // Record the info about this query we saw
1885         ds[i].Time        = Time;
1886         ds[i].InterfaceID = InterfaceID;
1887         ds[i].Type        = Type;
1888         
1889         return(i);
1890         }
1891
1892 mDNSlocal mDNSBool AccelerateThisQuery(mDNS *const m, DNSQuestion *q)
1893         {
1894         // If more than 90% of the way to the query time, we should unconditionally accelerate it
1895         if (TimeToSendThisQuestion(q, m->timenow + q->ThisQInterval/10))
1896                 return(mDNStrue);
1897
1898         // If half-way to next scheduled query time, only accelerate if it will add less than 512 bytes to the packet
1899         if (TimeToSendThisQuestion(q, m->timenow + q->ThisQInterval/2))
1900                 {
1901                 // We forecast: qname (n) type (2) class (2)
1902                 mDNSu32 forecast = (mDNSu32)DomainNameLength(&q->qname) + 4;
1903                 const mDNSu32 slot = HashSlot(&q->qname);
1904                 const CacheGroup *const cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
1905                 const CacheRecord *rr;
1906                 for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)                         // If we have a resource record in our cache,
1907                         if (rr->resrec.rdlength <= SmallRecordLimit &&                                  // which is small enough to sensibly fit in the packet
1908                                 SameNameRecordAnswersQuestion(&rr->resrec, q) &&                        // which answers our question
1909                                 rr->TimeRcvd + TicksTTL(rr)/2 - m->timenow >= 0 &&                      // and it is less than half-way to expiry
1910                                 rr->NextRequiredQuery - (m->timenow + q->ThisQInterval) > 0)// and we'll ask at least once again before NextRequiredQuery
1911                                 {
1912                                 // We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n)
1913                                 forecast += 12 + rr->resrec.rdestimate;
1914                                 if (forecast >= 512) return(mDNSfalse); // If this would add 512 bytes or more to the packet, don't accelerate
1915                                 }
1916                 return(mDNStrue);
1917                 }
1918
1919         return(mDNSfalse);
1920         }
1921
1922 // How Standard Queries are generated:
1923 // 1. The Question Section contains the question
1924 // 2. The Additional Section contains answers we already know, to suppress duplicate responses
1925
1926 // How Probe Queries are generated:
1927 // 1. The Question Section contains queries for the name we intend to use, with QType=ANY because
1928 // if some other host is already using *any* records with this name, we want to know about it.
1929 // 2. The Authority Section contains the proposed values we intend to use for one or more
1930 // of our records with that name (analogous to the Update section of DNS Update packets)
1931 // because if some other host is probing at the same time, we each want to know what the other is
1932 // planning, in order to apply the tie-breaking rule to see who gets to use the name and who doesn't.
1933
1934 mDNSlocal void SendQueries(mDNS *const m)
1935         {
1936         mDNSu32 slot;
1937         CacheGroup *cg;
1938         CacheRecord *cr;
1939         AuthRecord *ar;
1940         int pktcount = 0;
1941         DNSQuestion *q;
1942         // For explanation of maxExistingQuestionInterval logic, see comments for maxExistingAnnounceInterval
1943         mDNSs32 maxExistingQuestionInterval = 0;
1944         const NetworkInterfaceInfo *intf = GetFirstActiveInterface(m->HostInterfaces);
1945         CacheRecord *KnownAnswerList = mDNSNULL;
1946
1947         // 1. If time for a query, work out what we need to do
1948         if (m->timenow - m->NextScheduledQuery >= 0)
1949                 {
1950                 CacheRecord *rr;
1951
1952                 // We're expecting to send a query anyway, so see if any expiring cache records are close enough
1953                 // to their NextRequiredQuery to be worth batching them together with this one
1954                 FORALL_CACHERECORDS(slot, cg, rr)
1955                         if (rr->CRActiveQuestion && rr->UnansweredQueries < MaxUnansweredQueries)
1956                                 if (m->timenow + TicksTTL(rr)/50 - rr->NextRequiredQuery >= 0)
1957                                         {
1958                                         debugf("Sending %d%% cache expiration query for %s", 80 + 5 * rr->UnansweredQueries, CRDisplayString(m, rr));
1959                                         q = rr->CRActiveQuestion;
1960                                         ExpireDupSuppressInfoOnInterface(q->DupSuppress, m->timenow - TicksTTL(rr)/20, rr->resrec.InterfaceID);
1961                                         // For uDNS queries (TargetQID non-zero) we adjust LastQTime,
1962                                         // and bump UnansweredQueries so that we don't spin trying to send the same cache expiration query repeatedly
1963                                         if      (q->Target.type)                        q->SendQNow = mDNSInterfaceMark;        // If targeted query, mark it
1964                                         else if (!mDNSOpaque16IsZero(q->TargetQID))     { q->LastQTime = m->timenow - q->ThisQInterval; rr->UnansweredQueries++; }
1965                                         else if (q->SendQNow == mDNSNULL)               q->SendQNow = rr->resrec.InterfaceID;
1966                                         else if (q->SendQNow != rr->resrec.InterfaceID) q->SendQNow = mDNSInterfaceMark;
1967                                         }
1968
1969                 if (m->SuppressStdPort53Queries && m->timenow - m->SuppressStdPort53Queries >= 0)
1970                         m->SuppressStdPort53Queries = 0; // If suppression time has passed, clear it
1971                         
1972                 // Scan our list of questions to see which:
1973                 //     *WideArea*  queries need to be sent
1974                 //     *unicast*   queries need to be sent
1975                 //     *multicast* queries we're definitely going to send
1976                 if (m->CurrentQuestion)
1977                         LogMsg("SendQueries ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
1978                 m->CurrentQuestion = m->Questions;
1979                 while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
1980                         {
1981                         q = m->CurrentQuestion;
1982                         if (ActiveQuestion(q) && !mDNSOpaque16IsZero(q->TargetQID)) uDNS_CheckCurrentQuestion(m);
1983                         else if (mDNSOpaque16IsZero(q->TargetQID) && q->Target.type && (q->SendQNow || TimeToSendThisQuestion(q, m->timenow)))
1984                                 {
1985                                 mDNSu8       *qptr        = m->omsg.data;
1986                                 const mDNSu8 *const limit = m->omsg.data + sizeof(m->omsg.data);
1987
1988                                 // If we fail to get a new on-demand socket (should only happen cases of the most extreme resource exhaustion), we'll try again next time
1989                                 if (!q->LocalSocket) q->LocalSocket = mDNSPlatformUDPSocket(m, zeroIPPort);
1990                                 if (q->LocalSocket)
1991                                         {
1992                                         InitializeDNSMessage(&m->omsg.h, q->TargetQID, QueryFlags);
1993                                         qptr = putQuestion(&m->omsg, qptr, limit, &q->qname, q->qtype, q->qclass);
1994                                         mDNSSendDNSMessage(m, &m->omsg, qptr, mDNSInterface_Any, q->LocalSocket, &q->Target, q->TargetPort, mDNSNULL, mDNSNULL);
1995                                         q->ThisQInterval    *= QuestionIntervalStep;
1996                                         }
1997                                 if (q->ThisQInterval > MaxQuestionInterval)
1998                                         q->ThisQInterval = MaxQuestionInterval;
1999                                 q->LastQTime         = m->timenow;
2000                                 q->LastQTxTime       = m->timenow;
2001                                 q->RecentAnswerPkts  = 0;
2002                                 q->SendQNow          = mDNSNULL;
2003                                 q->ExpectUnicastResp = NonZeroTime(m->timenow);
2004                                 }
2005                         else if (mDNSOpaque16IsZero(q->TargetQID) && !q->Target.type && TimeToSendThisQuestion(q, m->timenow))
2006                                 {
2007                                 //LogInfo("Time to send %##s (%s) %d", q->qname.c, DNSTypeName(q->qtype), m->timenow - (q->LastQTime + q->ThisQInterval));
2008                                 q->SendQNow = mDNSInterfaceMark;                // Mark this question for sending on all interfaces
2009                                 if (maxExistingQuestionInterval < q->ThisQInterval)
2010                                         maxExistingQuestionInterval = q->ThisQInterval;
2011                                 }
2012                         // If m->CurrentQuestion wasn't modified out from under us, advance it now
2013                         // We can't do this at the start of the loop because uDNS_CheckCurrentQuestion() depends on having
2014                         // m->CurrentQuestion point to the right question
2015                         if (q == m->CurrentQuestion) m->CurrentQuestion = m->CurrentQuestion->next;
2016                         }
2017                 m->CurrentQuestion = mDNSNULL;
2018
2019                 // Scan our list of questions
2020                 // (a) to see if there are any more that are worth accelerating, and
2021                 // (b) to update the state variables for *all* the questions we're going to send
2022                 // Note: Don't set NextScheduledQuery until here, because uDNS_CheckCurrentQuestion in the loop above can add new questions to the list,
2023                 // which causes NextScheduledQuery to get (incorrectly) set to m->timenow. Setting it here is the right place, because the very
2024                 // next thing we do is scan the list and call SetNextQueryTime() for every question we find, so we know we end up with the right value.
2025                 m->NextScheduledQuery = m->timenow + 0x78000000;
2026                 for (q = m->Questions; q && q != m->NewQuestions; q=q->next)
2027                         {
2028                         if (mDNSOpaque16IsZero(q->TargetQID) && (q->SendQNow ||
2029                                 (!q->Target.type && ActiveQuestion(q) && q->ThisQInterval <= maxExistingQuestionInterval && AccelerateThisQuery(m,q))))
2030                                 {
2031                                 // If at least halfway to next query time, advance to next interval
2032                                 // If less than halfway to next query time, then
2033                                 // treat this as logically a repeat of the last transmission, without advancing the interval
2034                                 if (m->timenow - (q->LastQTime + q->ThisQInterval/2) >= 0)
2035                                         {
2036                                         //LogInfo("Accelerating %##s (%s) %d", q->qname.c, DNSTypeName(q->qtype), m->timenow - (q->LastQTime + q->ThisQInterval));
2037                                         q->SendQNow = mDNSInterfaceMark;        // Mark this question for sending on all interfaces
2038                                         debugf("SendQueries: %##s (%s) next interval %d seconds RequestUnicast = %d",
2039                                                 q->qname.c, DNSTypeName(q->qtype), q->ThisQInterval / InitialQuestionInterval, q->RequestUnicast);
2040                                         q->ThisQInterval *= QuestionIntervalStep;
2041                                         if (q->ThisQInterval > MaxQuestionInterval)
2042                                                 q->ThisQInterval = MaxQuestionInterval;
2043                                         else if (q->CurrentAnswers == 0 && q->ThisQInterval == InitialQuestionInterval * QuestionIntervalStep3 && !q->RequestUnicast &&
2044                                                         !(RRTypeIsAddressType(q->qtype) && CacheHasAddressTypeForName(m, &q->qname, q->qnamehash)))
2045                                                 {
2046                                                 // Generally don't need to log this.
2047                                                 // It's not especially noteworthy if a query finds no results -- this usually happens for domain
2048                                                 // enumeration queries in the LL subdomain (e.g. "db._dns-sd._udp.0.0.254.169.in-addr.arpa")
2049                                                 // and when there simply happen to be no instances of the service the client is looking
2050                                                 // for (e.g. iTunes is set to look for RAOP devices, and the current network has none).
2051                                                 debugf("SendQueries: Zero current answers for %##s (%s); will reconfirm antecedents",
2052                                                         q->qname.c, DNSTypeName(q->qtype));
2053                                                 // Sending third query, and no answers yet; time to begin doubting the source
2054                                                 ReconfirmAntecedents(m, &q->qname, q->qnamehash, 0);
2055                                                 }
2056                                         }
2057
2058                                 // Mark for sending. (If no active interfaces, then don't even try.)
2059                                 q->SendOnAll = (q->SendQNow == mDNSInterfaceMark);
2060                                 if (q->SendOnAll)
2061                                         {
2062                                         q->SendQNow  = !intf ? mDNSNULL : (q->InterfaceID) ? q->InterfaceID : intf->InterfaceID;
2063                                         q->LastQTime = m->timenow;
2064                                         }
2065
2066                                 // If we recorded a duplicate suppression for this question less than half an interval ago,
2067                                 // then we consider it recent enough that we don't need to do an identical query ourselves.
2068                                 ExpireDupSuppressInfo(q->DupSuppress, m->timenow - q->ThisQInterval/2);
2069
2070                                 q->LastQTxTime      = m->timenow;
2071                                 q->RecentAnswerPkts = 0;
2072                                 if (q->RequestUnicast) q->RequestUnicast--;
2073                                 }
2074                         // For all questions (not just the ones we're sending) check what the next scheduled event will be
2075                         SetNextQueryTime(m,q);
2076                         }
2077                 }
2078
2079         // 2. Scan our authoritative RR list to see what probes we might need to send
2080         if (m->timenow - m->NextScheduledProbe >= 0)
2081                 {
2082                 m->NextScheduledProbe = m->timenow + 0x78000000;
2083
2084                 if (m->CurrentRecord)
2085                         LogMsg("SendQueries ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
2086                 m->CurrentRecord = m->ResourceRecords;
2087                 while (m->CurrentRecord)
2088                         {
2089                         AuthRecord *rr = m->CurrentRecord;
2090                         m->CurrentRecord = rr->next;
2091                         if (!AuthRecord_uDNS(rr) && rr->resrec.RecordType == kDNSRecordTypeUnique)      // For all records that are still probing...
2092                                 {
2093                                 // 1. If it's not reached its probe time, just make sure we update m->NextScheduledProbe correctly
2094                                 if (m->timenow - (rr->LastAPTime + rr->ThisAPInterval) < 0)
2095                                         {
2096                                         SetNextAnnounceProbeTime(m, rr);
2097                                         }
2098                                 // 2. else, if it has reached its probe time, mark it for sending and then update m->NextScheduledProbe correctly
2099                                 else if (rr->ProbeCount)
2100                                         {
2101                                         if (rr->AddressProxy.type == mDNSAddrType_IPv4)
2102                                                 {
2103                                                 char *ifname = InterfaceNameForID(m, rr->resrec.InterfaceID);
2104                                                 if (!ifname) ifname = "<NULL InterfaceID>";
2105                                                 LogSPS("SendQueries ARP Probe %d %s %s", rr->ProbeCount, ifname, ARDisplayString(m,rr));
2106                                                 SendARP(m, 1, rr, zerov4Addr.b, zeroEthAddr.b, rr->AddressProxy.ip.v4.b, rr->WakeUp.IMAC.b);
2107                                                 }
2108                                         else if (rr->AddressProxy.type == mDNSAddrType_IPv6)
2109                                                 {
2110                                                 //LogSPS("SendQueries NDP Probe %d %s", rr->ProbeCount, ARDisplayString(m,rr));
2111                                                 //SendARP(m, 1, rr, rr->AddressProxy.ip.v4.b, zeroEthAddr.b, rr->AddressProxy.ip.v4.b, onesEthAddr.b);
2112                                                 }
2113                                         // Mark for sending. (If no active interfaces, then don't even try.)
2114                                         rr->SendRNow   = (!intf || rr->WakeUp.HMAC.l[0]) ? mDNSNULL : rr->resrec.InterfaceID ? rr->resrec.InterfaceID : intf->InterfaceID;
2115                                         rr->LastAPTime = m->timenow;
2116                                         // When we have a late conflict that resets a record to probing state we use a special marker value greater
2117                                         // than DefaultProbeCountForTypeUnique. Here we detect that state and reset rr->ProbeCount back to the right value.
2118                                         if (rr->ProbeCount > DefaultProbeCountForTypeUnique)
2119                                                 rr->ProbeCount = DefaultProbeCountForTypeUnique;
2120                                         rr->ProbeCount--;
2121                                         SetNextAnnounceProbeTime(m, rr);
2122                                         if (rr->ProbeCount == 0)
2123                                                 {
2124                                                 // If this is the last probe for this record, then see if we have any matching records
2125                                                 // on our duplicate list which should similarly have their ProbeCount cleared to zero...
2126                                                 AuthRecord *r2;
2127                                                 for (r2 = m->DuplicateRecords; r2; r2=r2->next)
2128                                                         if (r2->resrec.RecordType == kDNSRecordTypeUnique && RecordIsLocalDuplicate(r2, rr))
2129                                                                 r2->ProbeCount = 0;
2130                                                 // ... then acknowledge this record to the client.
2131                                                 // We do this optimistically, just as we're about to send the third probe.
2132                                                 // This helps clients that both advertise and browse, and want to filter themselves
2133                                                 // from the browse results list, because it helps ensure that the registration
2134                                                 // confirmation will be delivered 1/4 second *before* the browse "add" event.
2135                                                 // A potential downside is that we could deliver a registration confirmation and then find out
2136                                                 // moments later that there's a name conflict, but applications have to be prepared to handle
2137                                                 // late conflicts anyway (e.g. on connection of network cable, etc.), so this is nothing new.
2138                                                 if (!rr->Acknowledged) AcknowledgeRecord(m, rr);
2139                                                 }
2140                                         }
2141                                 // else, if it has now finished probing, move it to state Verified,
2142                                 // and update m->NextScheduledResponse so it will be announced
2143                                 else
2144                                         {
2145                                         if (!rr->Acknowledged) AcknowledgeRecord(m, rr);        // Defensive, just in case it got missed somehow
2146                                         rr->resrec.RecordType     = kDNSRecordTypeVerified;
2147                                         rr->ThisAPInterval = DefaultAnnounceIntervalForTypeUnique;
2148                                         rr->LastAPTime     = m->timenow - DefaultAnnounceIntervalForTypeUnique;
2149                                         SetNextAnnounceProbeTime(m, rr);
2150                                         }
2151                                 }
2152                         }
2153                 m->CurrentRecord = m->DuplicateRecords;
2154                 while (m->CurrentRecord)
2155                         {
2156                         AuthRecord *rr = m->CurrentRecord;
2157                         m->CurrentRecord = rr->next;
2158                         if (rr->resrec.RecordType == kDNSRecordTypeUnique && rr->ProbeCount == 0 && !rr->Acknowledged)
2159                                 AcknowledgeRecord(m, rr);
2160                         }
2161                 }
2162
2163         // 3. Now we know which queries and probes we're sending,
2164         // go through our interface list sending the appropriate queries on each interface
2165         while (intf)
2166                 {
2167                 const int OwnerRecordSpace = (m->AnnounceOwner && intf->MAC.l[0]) ? DNSOpt_Header_Space + DNSOpt_Owner_Space(&m->PrimaryMAC, &intf->MAC) : 0;
2168                 AuthRecord *rr;
2169                 mDNSu8 *queryptr = m->omsg.data;
2170                 InitializeDNSMessage(&m->omsg.h, zeroID, QueryFlags);
2171                 if (KnownAnswerList) verbosedebugf("SendQueries:   KnownAnswerList set... Will continue from previous packet");
2172                 if (!KnownAnswerList)
2173                         {
2174                         // Start a new known-answer list
2175                         CacheRecord **kalistptr = &KnownAnswerList;
2176                         mDNSu32 answerforecast = OwnerRecordSpace;              // We start by assuming we'll need at least enough space to put the Owner Option
2177                         
2178                         // Put query questions in this packet
2179                         for (q = m->Questions; q && q != m->NewQuestions; q=q->next)
2180                                 {
2181                                 if (mDNSOpaque16IsZero(q->TargetQID) && (q->SendQNow == intf->InterfaceID))
2182                                         {
2183                                         debugf("SendQueries: %s question for %##s (%s) at %d forecast total %d",
2184                                                 SuppressOnThisInterface(q->DupSuppress, intf) ? "Suppressing" : "Putting    ",
2185                                                 q->qname.c, DNSTypeName(q->qtype), queryptr - m->omsg.data, queryptr + answerforecast - m->omsg.data);
2186
2187                                         // If we're suppressing this question, or we successfully put it, update its SendQNow state
2188                                         if (SuppressOnThisInterface(q->DupSuppress, intf) ||
2189                                                 BuildQuestion(m, &m->omsg, &queryptr, q, &kalistptr, &answerforecast))
2190                                                         q->SendQNow = (q->InterfaceID || !q->SendOnAll) ? mDNSNULL : GetNextActiveInterfaceID(intf);
2191                                         }
2192                                 }
2193
2194                         // Put probe questions in this packet
2195                         for (rr = m->ResourceRecords; rr; rr=rr->next)
2196                                 if (rr->SendRNow == intf->InterfaceID)
2197                                         {
2198                                         mDNSBool ucast = (rr->ProbeCount >= DefaultProbeCountForTypeUnique-1) && m->CanReceiveUnicastOn5353;
2199                                         mDNSu16 ucbit = (mDNSu16)(ucast ? kDNSQClass_UnicastResponse : 0);
2200                                         const mDNSu8 *const limit = m->omsg.data + (m->omsg.h.numQuestions ? NormalMaxDNSMessageData : AbsoluteMaxDNSMessageData);
2201                                         // We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n)
2202                                         mDNSu32 forecast = answerforecast + 12 + rr->resrec.rdestimate;
2203                                         mDNSu8 *newptr = putQuestion(&m->omsg, queryptr, limit - forecast, rr->resrec.name, kDNSQType_ANY, (mDNSu16)(rr->resrec.rrclass | ucbit));
2204                                         if (newptr)
2205                                                 {
2206                                                 queryptr       = newptr;
2207                                                 answerforecast = forecast;
2208                                                 rr->SendRNow = (rr->resrec.InterfaceID) ? mDNSNULL : GetNextActiveInterfaceID(intf);
2209                                                 rr->IncludeInProbe = mDNStrue;
2210                                                 verbosedebugf("SendQueries:   Put Question %##s (%s) probecount %d",
2211                                                         rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->ProbeCount);
2212                                                 }
2213                                         }
2214                         }
2215
2216                 // Put our known answer list (either new one from this question or questions, or remainder of old one from last time)
2217                 while (KnownAnswerList)
2218                         {
2219                         CacheRecord *ka = KnownAnswerList;
2220                         mDNSu32 SecsSinceRcvd = ((mDNSu32)(m->timenow - ka->TimeRcvd)) / mDNSPlatformOneSecond;
2221                         mDNSu8 *newptr = PutResourceRecordTTLWithLimit(&m->omsg, queryptr, &m->omsg.h.numAnswers,
2222                                 &ka->resrec, ka->resrec.rroriginalttl - SecsSinceRcvd, m->omsg.data + NormalMaxDNSMessageData - OwnerRecordSpace);
2223                         if (newptr)
2224                                 {
2225                                 verbosedebugf("SendQueries:   Put %##s (%s) at %d - %d",
2226                                         ka->resrec.name->c, DNSTypeName(ka->resrec.rrtype), queryptr - m->omsg.data, newptr - m->omsg.data);
2227                                 queryptr = newptr;
2228                                 KnownAnswerList = ka->NextInKAList;
2229                                 ka->NextInKAList = mDNSNULL;
2230                                 }
2231                         else
2232                                 {
2233                                 // If we ran out of space and we have more than one question in the packet, that's an error --
2234                                 // we shouldn't have put more than one question if there was a risk of us running out of space.
2235                                 if (m->omsg.h.numQuestions > 1)
2236                                         LogMsg("SendQueries:   Put %d answers; No more space for known answers", m->omsg.h.numAnswers);
2237                                 m->omsg.h.flags.b[0] |= kDNSFlag0_TC;
2238                                 break;
2239                                 }
2240                         }
2241
2242                 for (rr = m->ResourceRecords; rr; rr=rr->next)
2243                         if (rr->IncludeInProbe)
2244                                 {
2245                                 mDNSu8 *newptr = PutResourceRecord(&m->omsg, queryptr, &m->omsg.h.numAuthorities, &rr->resrec);
2246                                 rr->IncludeInProbe = mDNSfalse;
2247                                 if (newptr) queryptr = newptr;
2248                                 else LogMsg("SendQueries:   How did we fail to have space for the Update record %s", ARDisplayString(m,rr));
2249                                 }
2250
2251                 if (queryptr > m->omsg.data)
2252                         {
2253                         if (OwnerRecordSpace)
2254                                 {
2255                                 AuthRecord opt;
2256                                 mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
2257                                 opt.resrec.rrclass    = NormalMaxDNSMessageData;
2258                                 opt.resrec.rdlength   = sizeof(rdataOPT);       // One option in this OPT record
2259                                 opt.resrec.rdestimate = sizeof(rdataOPT);
2260                                 SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[0]);
2261                                 LogSPS("SendQueries putting %s", ARDisplayString(m, &opt));
2262                                 queryptr = PutResourceRecordTTLWithLimit(&m->omsg, queryptr, &m->omsg.h.numAdditionals,
2263                                         &opt.resrec, opt.resrec.rroriginalttl, m->omsg.data + AbsoluteMaxDNSMessageData);
2264                                 if (!queryptr)
2265                                         LogMsg("SendQueries: How did we fail to have space for the OPT record (%d/%d/%d/%d) %s",
2266                                                 m->omsg.h.numQuestions, m->omsg.h.numAnswers, m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt));
2267                                 if (queryptr > m->omsg.data + NormalMaxDNSMessageData)
2268                                         if (m->omsg.h.numQuestions != 1 || m->omsg.h.numAnswers != 0 || m->omsg.h.numAuthorities != 1 || m->omsg.h.numAdditionals != 1)
2269                                                 LogMsg("SendQueries: Why did we generate oversized packet with OPT record %p %p %p (%d/%d/%d/%d) %s",
2270                                                         m->omsg.data, m->omsg.data + NormalMaxDNSMessageData, queryptr,
2271                                                         m->omsg.h.numQuestions, m->omsg.h.numAnswers, m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt));
2272                                 }
2273
2274                         if ((m->omsg.h.flags.b[0] & kDNSFlag0_TC) && m->omsg.h.numQuestions > 1)
2275                                 LogMsg("SendQueries: Should not have more than one question (%d) in a truncated packet", m->omsg.h.numQuestions);
2276                         debugf("SendQueries:   Sending %d Question%s %d Answer%s %d Update%s on %p",
2277                                 m->omsg.h.numQuestions,   m->omsg.h.numQuestions   == 1 ? "" : "s",
2278                                 m->omsg.h.numAnswers,     m->omsg.h.numAnswers     == 1 ? "" : "s",
2279                                 m->omsg.h.numAuthorities, m->omsg.h.numAuthorities == 1 ? "" : "s", intf->InterfaceID);
2280                         if (intf->IPv4Available) mDNSSendDNSMessage(m, &m->omsg, queryptr, intf->InterfaceID, mDNSNULL, &AllDNSLinkGroup_v4, MulticastDNSPort, mDNSNULL, mDNSNULL);
2281                         if (intf->IPv6Available) mDNSSendDNSMessage(m, &m->omsg, queryptr, intf->InterfaceID, mDNSNULL, &AllDNSLinkGroup_v6, MulticastDNSPort, mDNSNULL, mDNSNULL);
2282                         if (!m->SuppressSending) m->SuppressSending = NonZeroTime(m->timenow + (mDNSPlatformOneSecond+9)/10);
2283                         if (++pktcount >= 1000)
2284                                 { LogMsg("SendQueries exceeded loop limit %d: giving up", pktcount); break; }
2285                         // There might be more records left in the known answer list, or more questions to send
2286                         // on this interface, so go around one more time and try again.
2287                         }
2288                 else    // Nothing more to send on this interface; go to next
2289                         {
2290                         const NetworkInterfaceInfo *next = GetFirstActiveInterface(intf->next);
2291                         #if MDNS_DEBUGMSGS && 0
2292                         const char *const msg = next ? "SendQueries:   Nothing more on %p; moving to %p" : "SendQueries:   Nothing more on %p";
2293                         debugf(msg, intf, next);
2294                         #endif
2295                         intf = next;
2296                         }
2297                 }
2298
2299         // 4. Final housekeeping
2300         
2301         // 4a. Debugging check: Make sure we announced all our records
2302         for (ar = m->ResourceRecords; ar; ar=ar->next)
2303                 if (ar->SendRNow)
2304                         {
2305                         if (ar->resrec.InterfaceID != mDNSInterface_LocalOnly)
2306                                 LogMsg("SendQueries: No active interface to send: %s", ARDisplayString(m, ar));
2307                         ar->SendRNow = mDNSNULL;
2308                         }
2309
2310         // 4b. When we have lingering cache records that we're keeping around for a few seconds in the hope
2311         // that their interface which went away might come back again, the logic will want to send queries
2312         // for those records, but we can't because their interface isn't here any more, so to keep the
2313         // state machine ticking over we just pretend we did so.
2314         // If the interface does not come back in time, the cache record will expire naturally
2315         FORALL_CACHERECORDS(slot, cg, cr)
2316                 if (cr->CRActiveQuestion && cr->UnansweredQueries < MaxUnansweredQueries && m->timenow - cr->NextRequiredQuery >= 0)
2317                         {
2318                         cr->UnansweredQueries++;
2319                         cr->CRActiveQuestion->SendQNow = mDNSNULL;
2320                         SetNextCacheCheckTime(m, cr);
2321                         }
2322
2323         // 4c. Debugging check: Make sure we sent all our planned questions
2324         // Do this AFTER the lingering cache records check above, because that will prevent spurious warnings for questions
2325         // we legitimately couldn't send because the interface is no longer available
2326         for (q = m->Questions; q; q=q->next)
2327                 if (q->SendQNow)
2328                         {
2329                         LogMsg("SendQueries: No active interface to send: %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
2330                         q->SendQNow = mDNSNULL;
2331                         }
2332         }
2333
2334 mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password)
2335         {
2336         int i, j;
2337         mDNSu8 *ptr = m->omsg.data;
2338
2339         if (!InterfaceID) { LogMsg("SendWakeup: No InterfaceID specified"); return; }
2340
2341         // 0x00 Destination address
2342         for (i=0; i<6; i++) *ptr++ = EthAddr->b[i];
2343
2344         // 0x06 Source address (we just use zero -- BPF will fill in real interface address)
2345         for (i=0; i<6; i++) *ptr++ = 0x0;
2346
2347         // 0x0C Ethertype (0x0842)
2348         *ptr++ = 0x08;
2349         *ptr++ = 0x42;
2350
2351         // 0x0E Wakeup sync sequence
2352         for (i=0; i<6; i++) *ptr++ = 0xFF;
2353
2354         // 0x14 Wakeup data
2355         for (j=0; j<16; j++) for (i=0; i<6; i++) *ptr++ = EthAddr->b[i];
2356
2357         // 0x74 Password
2358         for (i=0; i<6; i++) *ptr++ = password->b[i];
2359
2360         mDNSPlatformSendRawPacket(m->omsg.data, ptr, InterfaceID);
2361
2362         // For Ethernet switches that don't flood-foward packets with unknown unicast destination MAC addresses,
2363         // broadcast is the only reliable way to get a wakeup packet to the intended target machine.
2364         // For 802.11 WPA networks, where a sleeping target machine may have missed a broadcast/multicast
2365         // key rotation, unicast is the only way to get a wakeup packet to the intended target machine.
2366         // So, we send one of each, unicast first, then broadcast second.
2367         for (i=0; i<6; i++) m->omsg.data[i] = 0xFF;
2368         mDNSPlatformSendRawPacket(m->omsg.data, ptr, InterfaceID);
2369         }
2370
2371 // ***************************************************************************
2372 #if COMPILER_LIKES_PRAGMA_MARK
2373 #pragma mark -
2374 #pragma mark - RR List Management & Task Management
2375 #endif
2376
2377 // Note: AnswerCurrentQuestionWithResourceRecord can call a user callback, which may change the record list and/or question list.
2378 // Any code walking either list must use the m->CurrentQuestion (and possibly m->CurrentRecord) mechanism to protect against this.
2379 // In fact, to enforce this, the routine will *only* answer the question currently pointed to by m->CurrentQuestion,
2380 // which will be auto-advanced (possibly to NULL) if the client callback cancels the question.
2381 mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheRecord *const rr, const QC_result AddRecord)
2382         {
2383         DNSQuestion *const q = m->CurrentQuestion;
2384         mDNSBool followcname = rr->resrec.RecordType != kDNSRecordTypePacketNegative && AddRecord &&
2385                                                         rr->resrec.rrtype == kDNSType_CNAME && q->qtype != kDNSType_CNAME;
2386         verbosedebugf("AnswerCurrentQuestionWithResourceRecord:%4lu %s TTL %d %s",
2387                 q->CurrentAnswers, AddRecord ? "Add" : "Rmv", rr->resrec.rroriginalttl, CRDisplayString(m, rr));
2388
2389         // Note: Use caution here. In the case of records with rr->DelayDelivery set, AnswerCurrentQuestionWithResourceRecord(... mDNStrue)
2390         // may be called twice, once when the record is received, and again when it's time to notify local clients.
2391         // If any counters or similar are added here, care must be taken to ensure that they are not double-incremented by this.
2392
2393         rr->LastUsed = m->timenow;
2394         if (AddRecord == QC_add && !q->DuplicateOf && rr->CRActiveQuestion != q)
2395                 {
2396                 if (!rr->CRActiveQuestion) m->rrcache_active++; // If not previously active, increment rrcache_active count
2397                 debugf("AnswerCurrentQuestionWithResourceRecord: Updating CRActiveQuestion to %p for cache record %s", q, CRDisplayString(m,rr));
2398                 rr->CRActiveQuestion = q;                                               // We know q is non-null
2399                 SetNextCacheCheckTime(m, rr);
2400                 }
2401
2402         // If this is:
2403         // (a) a no-cache add, where we've already done at least one 'QM' query, or
2404         // (b) a normal add, where we have at least one unique-type answer,
2405         // then there's no need to keep polling the network.
2406         // (If we have an answer in the cache, then we'll automatically ask again in time to stop it expiring.)
2407         // We do this for mDNS questions and uDNS one-shot questions, but not for
2408         // uDNS LongLived questions, because that would mess up our LLQ lease renewal timing.
2409         if ((AddRecord == QC_addnocache && !q->RequestUnicast) ||
2410                 (AddRecord == QC_add && (q->ExpectUnique || (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask))))
2411                 if (ActiveQuestion(q) && (mDNSOpaque16IsZero(q->TargetQID) || !q->LongLived))
2412                         {
2413                         q->LastQTime        = m->timenow;
2414                         q->LastQTxTime      = m->timenow;
2415                         q->RecentAnswerPkts = 0;
2416                         q->ThisQInterval    = MaxQuestionInterval;
2417                         q->RequestUnicast   = mDNSfalse;
2418                         debugf("AnswerCurrentQuestionWithResourceRecord: Set MaxQuestionInterval for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
2419                         }
2420
2421         if (rr->DelayDelivery) return;          // We'll come back later when CacheRecordDeferredAdd() calls us
2422
2423         // Only deliver negative answers if client has explicitly requested them
2424         if (rr->resrec.RecordType == kDNSRecordTypePacketNegative || (q->qtype != kDNSType_NSEC && RRAssertsNonexistence(&rr->resrec, q->qtype)))
2425                 if (!AddRecord || !q->ReturnIntermed) return;
2426
2427         // For CNAME results to non-CNAME questions, only inform the client if they explicitly requested that
2428         if (q->QuestionCallback && !q->NoAnswer && (!followcname || q->ReturnIntermed))
2429                 {
2430                 mDNS_DropLockBeforeCallback();          // Allow client (and us) to legally make mDNS API calls
2431                 if (q->qtype != kDNSType_NSEC && RRAssertsNonexistence(&rr->resrec, q->qtype))
2432                         {
2433                         CacheRecord neg;
2434                         MakeNegativeCacheRecord(m, &neg, &q->qname, q->qnamehash, q->qtype, q->qclass, 1, rr->resrec.InterfaceID, q->qDNSServer);
2435                         q->QuestionCallback(m, q, &neg.resrec, AddRecord);
2436                         }
2437                 else
2438                         q->QuestionCallback(m, q, &rr->resrec, AddRecord);
2439                 mDNS_ReclaimLockAfterCallback();        // Decrement mDNS_reentrancy to block mDNS API calls again
2440                 }
2441         // Note: Proceed with caution here because client callback function is allowed to do anything,
2442         // including starting/stopping queries, registering/deregistering records, etc.
2443
2444         if (followcname && m->CurrentQuestion == q && q->CNAMEReferrals < 10)
2445                 {
2446                 const mDNSu32 c = q->CNAMEReferrals + 1;
2447                 // Right now we just stop and re-use the existing query. If we really wanted to be 100% perfect,
2448                 // and track CNAMEs coming and going, we should really create a subordinate query here,
2449                 // which we would subsequently cancel and retract if the CNAME referral record were removed.
2450                 // In reality this is such a corner case we'll ignore it until someone actually needs it.
2451                 LogInfo("AnswerCurrentQuestionWithResourceRecord: following CNAME referral for %s", CRDisplayString(m, rr));
2452                 
2453                 // If this query is a duplicate of another query, UpdateQuestionDuplicates called from
2454                 // mDNS_StopQuery_internal copies the value of CNAMEReferrals from this query to the other
2455                 // query on the Questions list. By setting the new value before calling mDNS_StopQuery_internal,
2456                 // we ensure that the duplicate question gets a hgigher value and eventually the check for 10 above
2457                 // would be true. Otherwise, the two queries would end up as active questions
2458                 // sending mDNSResponder in an infinite loop e.g., Two queries starting off unique but receives
2459                 // a CNAME response that refers to itself (test IN CNAME test) which makes it a duplicate of
2460                 // one another. This fix now will make sure that stop at the 10th iteration. 
2461                 //
2462                 // Though CNAME records that refer to itself are not added anymore in mDNSCoreReceiveResponse, this fix is
2463                 // still needed to catch the cases where the CNAME referral spans across multiple records with a potential
2464                 // cycle in it which in turn can make multiple queries duplicate of each other
2465                 
2466                 q->CNAMEReferrals = c;                  // Need to set new CNAMEReferrals count *before* stopping the query, in case
2467                                                                                 // stopping the query causes the value to be copied to a duplicate question in the list
2468                 mDNS_StopQuery_internal(m, q);                                                          // Stop old query
2469                 AssignDomainName(&q->qname, &rr->resrec.rdata->u.name);         // Update qname
2470                 q->qnamehash = DomainNameHashValue(&q->qname);                          // and namehash
2471                 mDNS_StartQuery_internal(m, q);                                                         // start new query
2472                 q->CNAMEReferrals = c;                  // Record how many times we've done this
2473                                                                                 // Need to do this *after* mDNS_StartQuery_internal,
2474                                                                                 // because mDNS_StartQuery_internal initializes CNAMEReferrals to zero
2475                 }
2476         }
2477
2478 // New Questions are answered through AnswerNewQuestions. But there may not have been any
2479 // matching cache records for the questions when it is called. There are two possibilities.
2480 //
2481 // 1) There are no cache records
2482 // 2) There are cache records but the DNSServers between question and cache record don't match.
2483 //
2484 // In the case of (1), where there are no cache records and later we add them when we get a response,
2485 // CacheRecordAdd/CacheRecordDeferredAdd will take care of adding the cache and delivering the ADD
2486 // events to the application. If we already have a cache entry, then no ADD events are delivered
2487 // unless the RDATA has changed
2488 //
2489 // In the case of (2) where we had the cache records and did not answer because of the DNSServer mismatch,
2490 // we need to answer them whenever we change the DNSServer.  But we can't do it at the instant the DNSServer
2491 // changes because when we do the callback, the question can get deleted and the calling function would not
2492 // know how to handle it. So, we run this function from mDNS_Execute to handle DNSServer changes on the
2493 // question
2494
2495 mDNSlocal void AnswerQuestionsForDNSServerChanges(mDNS *const m)
2496         {
2497         DNSQuestion *q;
2498         DNSQuestion *qnext;
2499         CacheRecord *rr;
2500         mDNSu32 slot;
2501         CacheGroup *cg;
2502
2503         if (m->CurrentQuestion)
2504                 LogMsg("AnswerQuestionsForDNSServerChanges: ERROR m->CurrentQuestion already set: %##s (%s)",
2505                                 m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
2506
2507         for (q = m->Questions; q && q != m->NewQuestions; q = qnext)
2508                 {
2509                 qnext = q->next;
2510
2511                 // multicast or DNSServers did not change.
2512                 if (mDNSOpaque16IsZero(q->TargetQID)) continue;
2513                 if (!q->deliverAddEvents) continue;
2514
2515                 // We are going to look through the cache for this question since it changed
2516                 // its DNSserver last time. Reset it so that we don't call them again. Calling
2517                 // them again will deliver duplicate events to the application
2518                 q->deliverAddEvents = mDNSfalse;
2519                 m->CurrentQuestion = q;
2520                 slot = HashSlot(&q->qname);
2521                 cg = CacheGroupForName(m, slot, q->qnamehash, &q->qname);
2522                 for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
2523                         {
2524                         if (SameNameRecordAnswersQuestion(&rr->resrec, q))
2525                                 {
2526                                 LogInfo("AnswerQuestionsForDNSServerChanges: Calling AnswerCurrentQuestionWithResourceRecord for question %##s using resource record %s", q->qname.c, CRDisplayString(m, rr));
2527                                 AnswerCurrentQuestionWithResourceRecord(m, rr, QC_add);
2528                                 if (m->CurrentQuestion != q) break;             // If callback deleted q, then we're finished here
2529                                 }
2530                         }
2531                 }
2532                 m->CurrentQuestion = mDNSNULL;
2533         }
2534
2535 mDNSlocal void CacheRecordDeferredAdd(mDNS *const m, CacheRecord *rr)
2536         {
2537         rr->DelayDelivery = 0;          // Note, only need to call SetNextCacheCheckTime() when DelayDelivery is set, not when it's cleared
2538         if (m->CurrentQuestion)
2539                 LogMsg("CacheRecordDeferredAdd ERROR m->CurrentQuestion already set: %##s (%s)",
2540                         m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
2541         m->CurrentQuestion = m->Questions;
2542         while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
2543                 {
2544                 DNSQuestion *q = m->CurrentQuestion;
2545                 if (ResourceRecordAnswersQuestion(&rr->resrec, q))
2546                         AnswerCurrentQuestionWithResourceRecord(m, rr, QC_add);
2547                 if (m->CurrentQuestion == q)    // If m->CurrentQuestion was not auto-advanced, do it ourselves now
2548                         m->CurrentQuestion = q->next;
2549                 }
2550         m->CurrentQuestion = mDNSNULL;
2551         }
2552
2553 mDNSlocal mDNSs32 CheckForSoonToExpireRecords(mDNS *const m, const domainname *const name, const mDNSu32 namehash, const mDNSu32 slot)
2554         {
2555         const mDNSs32 threshhold = m->timenow + mDNSPlatformOneSecond;  // See if there are any records expiring within one second
2556         const mDNSs32 start      = m->timenow - 0x10000000;
2557         mDNSs32 delay = start;
2558         CacheGroup *cg = CacheGroupForName(m, slot, namehash, name);
2559         const CacheRecord *rr;
2560         for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
2561                 if (threshhold - RRExpireTime(rr) >= 0)         // If we have records about to expire within a second
2562                         if (delay - RRExpireTime(rr) < 0)               // then delay until after they've been deleted
2563                                 delay = RRExpireTime(rr);
2564         if (delay - start > 0) return(NonZeroTime(delay));
2565         else return(0);
2566         }
2567
2568 // CacheRecordAdd is only called from mDNSCoreReceiveResponse, *never* directly as a result of a client API call.
2569 // If new questions are created as a result of invoking client callbacks, they will be added to
2570 // the end of the question list, and m->NewQuestions will be set to indicate the first new question.
2571 // rr is a new CacheRecord just received into our cache
2572 // (kDNSRecordTypePacketAns/PacketAnsUnique/PacketAdd/PacketAddUnique).
2573 // Note: CacheRecordAdd calls AnswerCurrentQuestionWithResourceRecord which can call a user callback,
2574 // which may change the record list and/or question list.
2575 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
2576 mDNSlocal void CacheRecordAdd(mDNS *const m, CacheRecord *rr)
2577         {
2578         DNSQuestion *q;
2579
2580         // We stop when we get to NewQuestions -- if we increment their CurrentAnswers/LargeAnswers/UniqueAnswers
2581         // counters here we'll end up double-incrementing them when we do it again in AnswerNewQuestion().
2582         for (q = m->Questions; q && q != m->NewQuestions; q=q->next)
2583                 {
2584                 if (ResourceRecordAnswersQuestion(&rr->resrec, q))
2585                         {
2586                         // If this question is one that's actively sending queries, and it's received ten answers within one
2587                         // second of sending the last query packet, then that indicates some radical network topology change,
2588                         // so reset its exponential backoff back to the start. We must be at least at the eight-second interval
2589                         // to do this. If we're at the four-second interval, or less, there's not much benefit accelerating
2590                         // because we will anyway send another query within a few seconds. The first reset query is sent out
2591                         // randomized over the next four seconds to reduce possible synchronization between machines.
2592                         if (q->LastAnswerPktNum != m->PktNum)
2593                                 {
2594                                 q->LastAnswerPktNum = m->PktNum;
2595                                 if (mDNSOpaque16IsZero(q->TargetQID) && ActiveQuestion(q) && ++q->RecentAnswerPkts >= 10 &&
2596                                         q->ThisQInterval > InitialQuestionInterval * QuestionIntervalStep3 && m->timenow - q->LastQTxTime < mDNSPlatformOneSecond)
2597                                         {
2598                                         LogMsg("CacheRecordAdd: %##s (%s) got immediate answer burst (%d); restarting exponential backoff sequence (%d)",
2599                                                 q->qname.c, DNSTypeName(q->qtype), q->RecentAnswerPkts, q->ThisQInterval);
2600                                         q->LastQTime      = m->timenow - InitialQuestionInterval + (mDNSs32)mDNSRandom((mDNSu32)mDNSPlatformOneSecond*4);
2601                                         q->ThisQInterval  = InitialQuestionInterval;
2602                                         SetNextQueryTime(m,q);
2603                                         }
2604                                 }
2605                         verbosedebugf("CacheRecordAdd %p %##s (%s) %lu",
2606                                 rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->resrec.rroriginalttl);
2607                         q->CurrentAnswers++;
2608                         q->unansweredQueries = 0;
2609                         if (rr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers++;
2610                         if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers++;
2611                         if (q->CurrentAnswers > 4000)
2612                                 {
2613                                 static int msgcount = 0;
2614                                 if (msgcount++ < 10)
2615                                         LogMsg("CacheRecordAdd: %##s (%s) has %d answers; shedding records to resist DOS attack",
2616                                                 q->qname.c, DNSTypeName(q->qtype), q->CurrentAnswers);
2617                                 rr->resrec.rroriginalttl = 0;
2618                                 rr->UnansweredQueries = MaxUnansweredQueries;
2619                                 }
2620                         }
2621                 }
2622
2623         if (!rr->DelayDelivery)
2624                 {
2625                 if (m->CurrentQuestion)
2626                         LogMsg("CacheRecordAdd ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
2627                 m->CurrentQuestion = m->Questions;
2628                 while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
2629                         {
2630                         q = m->CurrentQuestion;
2631                         if (ResourceRecordAnswersQuestion(&rr->resrec, q))
2632                                 AnswerCurrentQuestionWithResourceRecord(m, rr, QC_add);
2633                         if (m->CurrentQuestion == q)    // If m->CurrentQuestion was not auto-advanced, do it ourselves now
2634                                 m->CurrentQuestion = q->next;
2635                         }
2636                 m->CurrentQuestion = mDNSNULL;
2637                 }
2638
2639         SetNextCacheCheckTime(m, rr);
2640         }
2641
2642 // NoCacheAnswer is only called from mDNSCoreReceiveResponse, *never* directly as a result of a client API call.
2643 // If new questions are created as a result of invoking client callbacks, they will be added to
2644 // the end of the question list, and m->NewQuestions will be set to indicate the first new question.
2645 // rr is a new CacheRecord just received from the wire (kDNSRecordTypePacketAns/AnsUnique/Add/AddUnique)
2646 // but we don't have any place to cache it. We'll deliver question 'add' events now, but we won't have any
2647 // way to deliver 'remove' events in future, nor will we be able to include this in known-answer lists,
2648 // so we immediately bump ThisQInterval up to MaxQuestionInterval to avoid pounding the network.
2649 // Note: NoCacheAnswer calls AnswerCurrentQuestionWithResourceRecord which can call a user callback,
2650 // which may change the record list and/or question list.
2651 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
2652 mDNSlocal void NoCacheAnswer(mDNS *const m, CacheRecord *rr)
2653         {
2654         LogMsg("No cache space: Delivering non-cached result for %##s", m->rec.r.resrec.name->c);
2655         if (m->CurrentQuestion)
2656                 LogMsg("NoCacheAnswer ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
2657         m->CurrentQuestion = m->Questions;
2658         // We do this for *all* questions, not stopping when we get to m->NewQuestions,
2659         // since we're not caching the record and we'll get no opportunity to do this later
2660         while (m->CurrentQuestion)
2661                 {
2662                 DNSQuestion *q = m->CurrentQuestion;
2663                 if (ResourceRecordAnswersQuestion(&rr->resrec, q))
2664                         AnswerCurrentQuestionWithResourceRecord(m, rr, QC_addnocache);  // QC_addnocache means "don't expect remove events for this"
2665                 if (m->CurrentQuestion == q)    // If m->CurrentQuestion was not auto-advanced, do it ourselves now
2666                         m->CurrentQuestion = q->next;
2667                 }
2668         m->CurrentQuestion = mDNSNULL;
2669         }
2670
2671 // CacheRecordRmv is only called from CheckCacheExpiration, which is called from mDNS_Execute.
2672 // Note that CacheRecordRmv is *only* called for records that are referenced by at least one active question.
2673 // If new questions are created as a result of invoking client callbacks, they will be added to
2674 // the end of the question list, and m->NewQuestions will be set to indicate the first new question.
2675 // rr is an existing cache CacheRecord that just expired and is being deleted
2676 // (kDNSRecordTypePacketAns/PacketAnsUnique/PacketAdd/PacketAddUnique).
2677 // Note: CacheRecordRmv calls AnswerCurrentQuestionWithResourceRecord which can call a user callback,
2678 // which may change the record list and/or question list.
2679 // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
2680 mDNSlocal void CacheRecordRmv(mDNS *const m, CacheRecord *rr)
2681         {
2682         if (m->CurrentQuestion)
2683                 LogMsg("CacheRecordRmv ERROR m->CurrentQuestion already set: %##s (%s)",
2684                         m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
2685         m->CurrentQuestion = m->Questions;
2686
2687         // We stop when we get to NewQuestions -- for new questions their CurrentAnswers/LargeAnswers/UniqueAnswers counters
2688         // will all still be zero because we haven't yet gone through the cache counting how many answers we have for them.
2689         while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
2690                 {
2691                 DNSQuestion *q = m->CurrentQuestion;
2692                 if (ResourceRecordAnswersQuestion(&rr->resrec, q))
2693                         {
2694                         verbosedebugf("CacheRecordRmv %p %s", rr, CRDisplayString(m, rr));
2695                         q->FlappingInterface1 = mDNSNULL;
2696                         q->FlappingInterface2 = mDNSNULL;
2697                         if (q->CurrentAnswers == 0)
2698                                 LogMsg("CacheRecordRmv ERROR: How can CurrentAnswers already be zero for %p %##s (%s)?",
2699                                         q, q->qname.c, DNSTypeName(q->qtype));
2700                         else
2701                                 {
2702                                 q->CurrentAnswers--;
2703                                 if (rr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers--;
2704                                 if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers--;
2705                                 }
2706                         if (rr->resrec.rdata->MaxRDLength) // Never generate "remove" events for negative results
2707                                 {
2708                                 if (q->CurrentAnswers == 0)
2709                                         {
2710                                         LogInfo("CacheRecordRmv: Last answer for %##s (%s) expired from cache; will reconfirm antecedents",
2711                                                 q->qname.c, DNSTypeName(q->qtype));
2712                                         ReconfirmAntecedents(m, &q->qname, q->qnamehash, 0);
2713                                         }
2714                                 AnswerCurrentQuestionWithResourceRecord(m, rr, QC_rmv);
2715                                 }
2716                         }
2717                 if (m->CurrentQuestion == q)    // If m->CurrentQuestion was not auto-advanced, do it ourselves now
2718                         m->CurrentQuestion = q->next;
2719                 }
2720         m->CurrentQuestion = mDNSNULL;
2721         }
2722
2723 mDNSlocal void ReleaseCacheEntity(mDNS *const m, CacheEntity *e)
2724         {
2725 #if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING >= 1
2726         unsigned int i;
2727         for (i=0; i<sizeof(*e); i++) ((char*)e)[i] = 0xFF;
2728 #endif
2729         e->next = m->rrcache_free;
2730         m->rrcache_free = e;
2731         m->rrcache_totalused--;
2732         }
2733
2734 mDNSlocal void ReleaseCacheGroup(mDNS *const m, CacheGroup **cp)
2735         {
2736         CacheEntity *e = (CacheEntity *)(*cp);
2737         //LogMsg("ReleaseCacheGroup:  Releasing CacheGroup for %p, %##s", (*cp)->name->c, (*cp)->name->c);
2738         if ((*cp)->rrcache_tail != &(*cp)->members)
2739                 LogMsg("ERROR: (*cp)->members == mDNSNULL but (*cp)->rrcache_tail != &(*cp)->members)");
2740         //if ((*cp)->name != (domainname*)((*cp)->namestorage))
2741         //      LogMsg("ReleaseCacheGroup: %##s, %p %p", (*cp)->name->c, (*cp)->name, (domainname*)((*cp)->namestorage));
2742         if ((*cp)->name != (domainname*)((*cp)->namestorage)) mDNSPlatformMemFree((*cp)->name);
2743         (*cp)->name = mDNSNULL;
2744         *cp = (*cp)->next;                      // Cut record from list
2745         ReleaseCacheEntity(m, e);
2746         }
2747
2748 mDNSlocal void ReleaseCacheRecord(mDNS *const m, CacheRecord *r)
2749         {
2750         //LogMsg("ReleaseCacheRecord: Releasing %s", CRDisplayString(m, r));
2751         if (r->resrec.rdata && r->resrec.rdata != (RData*)&r->smallrdatastorage) mDNSPlatformMemFree(r->resrec.rdata);
2752         r->resrec.rdata = mDNSNULL;
2753         ReleaseCacheEntity(m, (CacheEntity *)r);
2754         }
2755
2756 // Note: We want to be careful that we deliver all the CacheRecordRmv calls before delivering
2757 // CacheRecordDeferredAdd calls. The in-order nature of the cache lists ensures that all
2758 // callbacks for old records are delivered before callbacks for newer records.
2759 mDNSlocal void CheckCacheExpiration(mDNS *const m, CacheGroup *const cg)
2760         {
2761         CacheRecord **rp = &cg->members;
2762
2763         if (m->lock_rrcache) { LogMsg("CheckCacheExpiration ERROR! Cache already locked!"); return; }
2764         m->lock_rrcache = 1;
2765
2766         while (*rp)
2767                 {
2768                 CacheRecord *const rr = *rp;
2769                 mDNSs32 event = RRExpireTime(rr);
2770                 if (m->timenow - event >= 0)    // If expired, delete it
2771                         {
2772                         *rp = rr->next;                         // Cut it from the list
2773                         verbosedebugf("CheckCacheExpiration: Deleting%7d %7d %p %s",