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