1/* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2002-2018 Apple Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * This code is completely 100% portable C. It does not depend on any external header files
18 * from outside the mDNS project -- all the types it expects to find are defined right here.
19 *
20 * The previous point is very important: This file does not depend on any external
21 * header files. It should compile on *any* platform that has a C compiler, without
22 * making *any* assumptions about availability of so-called "standard" C functions,
23 * routines, or types (which may or may not be present on any given platform).
24 */
25
26#include "DNSCommon.h"                  // Defines general DNS utility routines
27#include "uDNS.h"                       // Defines entry points into unicast-specific routines
28#include "nsec.h"
29#include "dnssec.h"
30#include "anonymous.h"
31
32// Disable certain benign warnings with Microsoft compilers
33#if (defined(_MSC_VER))
34// Disable "conditional expression is constant" warning for debug macros.
35// Otherwise, this generates warnings for the perfectly natural construct "while(1)"
36// If someone knows a variant way of writing "while(1)" that doesn't generate warning messages, please let us know
37    #pragma warning(disable:4127)
38
39// Disable "assignment within conditional expression".
40// Other compilers understand the convention that if you place the assignment expression within an extra pair
41// of parentheses, this signals to the compiler that you really intended an assignment and no warning is necessary.
42// The Microsoft compiler doesn't understand this convention, so in the absense of any other way to signal
43// to the compiler that the assignment is intentional, we have to just turn this warning off completely.
44    #pragma warning(disable:4706)
45#endif
46
47#include "dns_sd.h" // for kDNSServiceFlags* definitions
48#include "dns_sd_internal.h"
49
50#if APPLE_OSX_mDNSResponder
51#include <WebFilterDNS/WebFilterDNS.h>
52
53// Delay in seconds before disabling multicast after there are no active queries or registrations.
54#define BONJOUR_DISABLE_DELAY 60
55
56#if !NO_WCF
57WCFConnection *WCFConnectionNew(void) __attribute__((weak_import));
58void WCFConnectionDealloc(WCFConnection* c) __attribute__((weak_import));
59
60// Do we really need to define a macro for "if"?
61#define CHECK_WCF_FUNCTION(X) if (X)
62#endif // ! NO_WCF
63
64#else
65
66#define NO_WCF 1
67#endif // APPLE_OSX_mDNSResponder
68
69#if AWD_METRICS
70#include "Metrics.h"
71#endif
72
73#if USE_DNS64
74#include "DNS64.h"
75#endif
76
77#ifdef UNIT_TEST
78#include "unittest.h"
79#endif
80
81// Forward declarations
82mDNSlocal void BeginSleepProcessing(mDNS *const m);
83mDNSlocal void RetrySPSRegistrations(mDNS *const m);
84mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password, mDNSBool unicastOnly);
85mDNSlocal mDNSBool LocalRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q);
86mDNSlocal void mDNS_PurgeBeforeResolve(mDNS *const m, DNSQuestion *q);
87mDNSlocal void CheckForDNSSECRecords(mDNS *const m, DNSQuestion *q);
88mDNSlocal void mDNS_SendKeepalives(mDNS *const m);
89mDNSlocal void mDNS_ExtractKeepaliveInfo(AuthRecord *ar, mDNSu32 *timeout, mDNSAddr *laddr, mDNSAddr *raddr, mDNSEthAddr *eth,
90                                         mDNSu32 *seq, mDNSu32 *ack, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu16 *win);
91
92mDNSlocal void AdvertiseAllInterfaceRecords(mDNS *const m);
93mDNSlocal void DeadvertiseAllInterfaceRecords(mDNS *const m);
94mDNSlocal void FreeNSECRecords(mDNS *const m, CacheRecord *NSECRecords);
95mDNSlocal void mDNSParseNSEC3Records(mDNS *const m, const DNSMessage *const response, const mDNSu8 *end,
96                                        const mDNSInterfaceID InterfaceID, CacheRecord **NSEC3Records);
97mDNSlocal mDNSu8 *GetValueForMACAddr(mDNSu8 *ptr, mDNSu8 *limit, mDNSEthAddr *eth);
98
99
100// ***************************************************************************
101#if COMPILER_LIKES_PRAGMA_MARK
102#pragma mark - Program Constants
103#endif
104
105// To Turn OFF mDNS_Tracer set MDNS_TRACER to 0 or undef it
106#define MDNS_TRACER 1
107
108#define NO_HINFO 1
109
110// Any records bigger than this are considered 'large' records
111#define SmallRecordLimit 1024
112
113#define kMaxUpdateCredits 10
114#define kUpdateCreditRefreshInterval (mDNSPlatformOneSecond * 6)
115
116// define special NR_AnswerTo values
117#define NR_AnswerMulticast  (mDNSu8*)~0
118#define NR_AnswerUnicast    (mDNSu8*)~1
119
120// Question default timeout values
121#define DEFAULT_MCAST_TIMEOUT       5
122#define DEFAULT_LO_OR_P2P_TIMEOUT   5
123
124// The code (see SendQueries() and BuildQuestion()) needs to have the
125// RequestUnicast value set to a value one greater than the number of times you want the query
126// sent with the "request unicast response" (QU) bit set.
127#define SET_QU_IN_FIRST_QUERY   2
128#define kDefaultRequestUnicastCount SET_QU_IN_FIRST_QUERY
129
130// The time needed to offload records to a sleep proxy after powerd sends the kIOMessageSystemWillSleep notification
131#define DARK_WAKE_DELAY_SLEEP  5
132#define kDarkWakeDelaySleep    (mDNSPlatformOneSecond * DARK_WAKE_DELAY_SLEEP)
133
134// The maximum number of times we delay probing to prevent spurious conflicts due to stale packets
135#define MAX_CONFLICT_PROCESSING_DELAYS 3
136
137// RFC 6762 defines Passive Observation Of Failures (POOF)
138//
139//    A host observes the multicast queries issued by the other hosts on
140//    the network.  One of the major benefits of also sending responses
141//    using multicast is that it allows all hosts to see the responses
142//    (or lack thereof) to those queries.
143//
144//    If a host sees queries, for which a record in its cache would be
145//    expected to be given as an answer in a multicast response, but no
146//    such answer is seen, then the host may take this as an indication
147//    that the record may no longer be valid.
148//
149//    After seeing two or more of these queries, and seeing no multicast
150//    response containing the expected answer within ten seconds, then even
151//    though its TTL may indicate that it is not yet due to expire, that
152//    record SHOULD be flushed from the cache.
153//
154// <https://tools.ietf.org/html/rfc6762#section-10.5>
155
156#define POOF_ENABLED 1
157
158mDNSexport const char *const mDNS_DomainTypeNames[] =
159{
160    "b._dns-sd._udp.",      // Browse
161    "db._dns-sd._udp.",     // Default Browse
162    "lb._dns-sd._udp.",     // Automatic Browse
163    "r._dns-sd._udp.",      // Registration
164    "dr._dns-sd._udp."      // Default Registration
165};
166
167#ifdef UNICAST_DISABLED
168#define uDNS_IsActiveQuery(q, u) mDNSfalse
169#endif
170
171// ***************************************************************************
172#if COMPILER_LIKES_PRAGMA_MARK
173#pragma mark -
174#pragma mark - General Utility Functions
175#endif
176
177// Returns true if this is a  unique, authoritative LocalOnly record that answers questions of type
178// A, AAAA , CNAME, or PTR.  The caller should answer the question with this record and not send out
179// the question on the wire if LocalOnlyRecordAnswersQuestion() also returns true.
180// Main use is to handle /etc/hosts records and the LocalOnly PTR records created for localhost.
181#define UniqueLocalOnlyRecord(rr) ((rr)->ARType == AuthRecordLocalOnly && \
182                                        (rr)->resrec.RecordType & kDNSRecordTypeUniqueMask && \
183                                        ((rr)->resrec.rrtype == kDNSType_A || (rr)->resrec.rrtype == kDNSType_AAAA || \
184                                         (rr)->resrec.rrtype == kDNSType_CNAME || \
185                                         (rr)->resrec.rrtype == kDNSType_PTR))
186
187mDNSlocal void SetNextQueryStopTime(mDNS *const m, const DNSQuestion *const q)
188{
189    mDNS_CheckLock(m);
190
191    if (m->NextScheduledStopTime - q->StopTime > 0)
192        m->NextScheduledStopTime = q->StopTime;
193}
194
195mDNSexport void SetNextQueryTime(mDNS *const m, const DNSQuestion *const q)
196{
197    mDNS_CheckLock(m);
198
199    if (ActiveQuestion(q))
200    {
201        // Depending on whether this is a multicast or unicast question we want to set either:
202        // m->NextScheduledQuery = NextQSendTime(q) or
203        // m->NextuDNSEvent      = NextQSendTime(q)
204        mDNSs32 *const timer = mDNSOpaque16IsZero(q->TargetQID) ? &m->NextScheduledQuery : &m->NextuDNSEvent;
205        if (*timer - NextQSendTime(q) > 0)
206            *timer = NextQSendTime(q);
207    }
208}
209
210mDNSlocal void ReleaseAuthEntity(AuthHash *r, AuthEntity *e)
211{
212#if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING >= 1
213    unsigned int i;
214    for (i=0; i<sizeof(*e); i++) ((char*)e)[i] = 0xFF;
215#endif
216    e->next = r->rrauth_free;
217    r->rrauth_free = e;
218    r->rrauth_totalused--;
219}
220
221mDNSlocal void ReleaseAuthGroup(AuthHash *r, AuthGroup **cp)
222{
223    AuthEntity *e = (AuthEntity *)(*cp);
224    LogMsg("ReleaseAuthGroup:  Releasing AuthGroup %##s", (*cp)->name->c);
225    if ((*cp)->rrauth_tail != &(*cp)->members)
226        LogMsg("ERROR: (*cp)->members == mDNSNULL but (*cp)->rrauth_tail != &(*cp)->members)");
227    if ((*cp)->name != (domainname*)((*cp)->namestorage)) mDNSPlatformMemFree((*cp)->name);
228    (*cp)->name = mDNSNULL;
229    *cp = (*cp)->next;          // Cut record from list
230    ReleaseAuthEntity(r, e);
231}
232
233mDNSlocal AuthEntity *GetAuthEntity(AuthHash *r, const AuthGroup *const PreserveAG)
234{
235    AuthEntity *e = mDNSNULL;
236
237    if (r->rrauth_lock) { LogMsg("GetFreeCacheRR ERROR! Cache already locked!"); return(mDNSNULL); }
238    r->rrauth_lock = 1;
239
240    if (!r->rrauth_free)
241    {
242        // We allocate just one AuthEntity at a time because we need to be able
243        // free them all individually which normally happens when we parse /etc/hosts into
244        // AuthHash where we add the "new" entries and discard (free) the already added
245        // entries. If we allocate as chunks, we can't free them individually.
246        AuthEntity *storage = mDNSPlatformMemAllocate(sizeof(AuthEntity));
247        storage->next = mDNSNULL;
248        r->rrauth_free = storage;
249    }
250
251    // If we still have no free records, recycle all the records we can.
252    // Enumerating the entire auth is moderately expensive, so when we do it, we reclaim all the records we can in one pass.
253    if (!r->rrauth_free)
254    {
255        mDNSu32 oldtotalused = r->rrauth_totalused;
256        mDNSu32 slot;
257        for (slot = 0; slot < AUTH_HASH_SLOTS; slot++)
258        {
259            AuthGroup **cp = &r->rrauth_hash[slot];
260            while (*cp)
261            {
262                if ((*cp)->members || (*cp)==PreserveAG) cp=&(*cp)->next;
263                else ReleaseAuthGroup(r, cp);
264            }
265        }
266        LogInfo("GetAuthEntity: Recycled %d records to reduce auth cache from %d to %d",
267                oldtotalused - r->rrauth_totalused, oldtotalused, r->rrauth_totalused);
268    }
269
270    if (r->rrauth_free) // If there are records in the free list, take one
271    {
272        e = r->rrauth_free;
273        r->rrauth_free = e->next;
274        if (++r->rrauth_totalused >= r->rrauth_report)
275        {
276            LogInfo("RR Auth now using %ld objects", r->rrauth_totalused);
277            if      (r->rrauth_report <  100) r->rrauth_report += 10;
278            else if (r->rrauth_report < 1000) r->rrauth_report += 100;
279            else r->rrauth_report += 1000;
280        }
281        mDNSPlatformMemZero(e, sizeof(*e));
282    }
283
284    r->rrauth_lock = 0;
285
286    return(e);
287}
288
289mDNSexport AuthGroup *AuthGroupForName(AuthHash *r, const mDNSu32 namehash, const domainname *const name)
290{
291    AuthGroup *ag;
292    const mDNSu32 slot = namehash % AUTH_HASH_SLOTS;
293
294    for (ag = r->rrauth_hash[slot]; ag; ag=ag->next)
295        if (ag->namehash == namehash && SameDomainName(ag->name, name))
296            break;
297    return(ag);
298}
299
300mDNSexport AuthGroup *AuthGroupForRecord(AuthHash *r, const ResourceRecord *const rr)
301{
302    return(AuthGroupForName(r, rr->namehash, rr->name));
303}
304
305mDNSlocal AuthGroup *GetAuthGroup(AuthHash *r, const ResourceRecord *const rr)
306{
307    mDNSu16 namelen = DomainNameLength(rr->name);
308    AuthGroup *ag = (AuthGroup*)GetAuthEntity(r, mDNSNULL);
309    const mDNSu32 slot = rr->namehash % AUTH_HASH_SLOTS;
310    if (!ag) { LogMsg("GetAuthGroup: Failed to allocate memory for %##s", rr->name->c); return(mDNSNULL); }
311    ag->next         = r->rrauth_hash[slot];
312    ag->namehash     = rr->namehash;
313    ag->members      = mDNSNULL;
314    ag->rrauth_tail  = &ag->members;
315    ag->NewLocalOnlyRecords = mDNSNULL;
316    if (namelen > sizeof(ag->namestorage))
317        ag->name = mDNSPlatformMemAllocate(namelen);
318    else
319        ag->name = (domainname*)ag->namestorage;
320    if (!ag->name)
321    {
322        LogMsg("GetAuthGroup: Failed to allocate name storage for %##s", rr->name->c);
323        ReleaseAuthEntity(r, (AuthEntity*)ag);
324        return(mDNSNULL);
325    }
326    AssignDomainName(ag->name, rr->name);
327
328    if (AuthGroupForRecord(r, rr)) LogMsg("GetAuthGroup: Already have AuthGroup for %##s", rr->name->c);
329    r->rrauth_hash[slot] = ag;
330    if (AuthGroupForRecord(r, rr) != ag) LogMsg("GetAuthGroup: Not finding AuthGroup for %##s", rr->name->c);
331
332    return(ag);
333}
334
335// Returns the AuthGroup in which the AuthRecord was inserted
336mDNSexport AuthGroup *InsertAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr)
337{
338    AuthGroup *ag;
339
340    (void)m;
341    ag = AuthGroupForRecord(r, &rr->resrec);
342    if (!ag) ag = GetAuthGroup(r, &rr->resrec);   // If we don't have a AuthGroup for this name, make one now
343    if (ag)
344    {
345        *(ag->rrauth_tail) = rr;                // Append this record to tail of cache slot list
346        ag->rrauth_tail = &(rr->next);          // Advance tail pointer
347    }
348    return ag;
349}
350
351mDNSexport AuthGroup *RemoveAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr)
352{
353    AuthGroup *a;
354    AuthRecord **rp;
355
356    a = AuthGroupForRecord(r, &rr->resrec);
357    if (!a) { LogMsg("RemoveAuthRecord: ERROR!! AuthGroup not found for %s", ARDisplayString(m, rr)); return mDNSNULL; }
358    rp = &a->members;
359    while (*rp)
360    {
361        if (*rp != rr)
362            rp=&(*rp)->next;
363        else
364        {
365            // We don't break here, so that we can set the tail below without tracking "prev" pointers
366
367            LogInfo("RemoveAuthRecord: removing auth record %s from table", ARDisplayString(m, rr));
368            *rp = (*rp)->next;          // Cut record from list
369        }
370    }
371    // TBD: If there are no more members, release authgroup ?
372    a->rrauth_tail = rp;
373    return a;
374}
375
376mDNSexport CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 namehash, const domainname *const name)
377{
378    CacheGroup *cg;
379    mDNSu32    slot = HashSlotFromNameHash(namehash);
380    for (cg = m->rrcache_hash[slot]; cg; cg=cg->next)
381        if (cg->namehash == namehash && SameDomainName(cg->name, name))
382            break;
383    return(cg);
384}
385
386mDNSlocal CacheGroup *CacheGroupForRecord(const mDNS *const m, const ResourceRecord *const rr)
387{
388    return(CacheGroupForName(m, rr->namehash, rr->name));
389}
390
391mDNSexport mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr)
392{
393    NetworkInterfaceInfo *intf;
394
395    if (addr->type == mDNSAddrType_IPv4)
396    {
397        // Normally we resist touching the NotAnInteger fields, but here we're doing tricky bitwise masking so we make an exception
398        if (mDNSv4AddressIsLinkLocal(&addr->ip.v4)) return(mDNStrue);
399        for (intf = m->HostInterfaces; intf; intf = intf->next)
400            if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID && intf->McastTxRx)
401                if (((intf->ip.ip.v4.NotAnInteger ^ addr->ip.v4.NotAnInteger) & intf->mask.ip.v4.NotAnInteger) == 0)
402                    return(mDNStrue);
403    }
404
405    if (addr->type == mDNSAddrType_IPv6)
406    {
407        if (mDNSv6AddressIsLinkLocal(&addr->ip.v6)) return(mDNStrue);
408        for (intf = m->HostInterfaces; intf; intf = intf->next)
409            if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID && intf->McastTxRx)
410                if ((((intf->ip.ip.v6.l[0] ^ addr->ip.v6.l[0]) & intf->mask.ip.v6.l[0]) == 0) &&
411                    (((intf->ip.ip.v6.l[1] ^ addr->ip.v6.l[1]) & intf->mask.ip.v6.l[1]) == 0) &&
412                    (((intf->ip.ip.v6.l[2] ^ addr->ip.v6.l[2]) & intf->mask.ip.v6.l[2]) == 0) &&
413                    (((intf->ip.ip.v6.l[3] ^ addr->ip.v6.l[3]) & intf->mask.ip.v6.l[3]) == 0))
414                        return(mDNStrue);
415    }
416
417    return(mDNSfalse);
418}
419
420mDNSlocal NetworkInterfaceInfo *FirstInterfaceForID(mDNS *const m, const mDNSInterfaceID InterfaceID)
421{
422    NetworkInterfaceInfo *intf = m->HostInterfaces;
423    while (intf && intf->InterfaceID != InterfaceID) intf = intf->next;
424    return(intf);
425}
426
427mDNSlocal NetworkInterfaceInfo *FirstIPv4LLInterfaceForID(mDNS *const m, const mDNSInterfaceID InterfaceID)
428{
429    NetworkInterfaceInfo *intf;
430
431    if (!InterfaceID)
432        return mDNSNULL;
433
434    // Note: We don't check for InterfaceActive, as the active interface could be IPv6 and
435    // we still want to find the first IPv4 Link-Local interface
436    for (intf = m->HostInterfaces; intf; intf = intf->next)
437    {
438        if (intf->InterfaceID == InterfaceID &&
439            intf->ip.type == mDNSAddrType_IPv4 && mDNSv4AddressIsLinkLocal(&intf->ip.ip.v4))
440        {
441            debugf("FirstIPv4LLInterfaceForID: found LL interface with address %.4a", &intf->ip.ip.v4);
442            return intf;
443        }
444    }
445    return (mDNSNULL);
446}
447
448mDNSexport char *InterfaceNameForID(mDNS *const m, const mDNSInterfaceID InterfaceID)
449{
450    NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID);
451    return(intf ? intf->ifname : mDNSNULL);
452}
453
454// Caller should hold the lock
455mDNSlocal void GenerateNegativeResponse(mDNS *const m, mDNSInterfaceID InterfaceID, QC_result qc)
456{
457    DNSQuestion *q;
458    if (!m->CurrentQuestion) { LogMsg("GenerateNegativeResponse: ERROR!! CurrentQuestion not set"); return; }
459    q = m->CurrentQuestion;
460    LogInfo("GenerateNegativeResponse: Generating negative response for question %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
461
462    MakeNegativeCacheRecord(m, &m->rec.r, &q->qname, q->qnamehash, q->qtype, q->qclass, 60, InterfaceID, mDNSNULL);
463
464    // We need to force the response through in the following cases
465    //
466    //  a) SuppressUnusable questions that are suppressed
467    //  b) Append search domains and retry the question
468    //
469    // The question may not have set Intermediates in which case we don't deliver negative responses. So, to force
470    // through we use "QC_forceresponse".
471    AnswerCurrentQuestionWithResourceRecord(m, &m->rec.r, qc);
472    if (m->CurrentQuestion == q) { q->ThisQInterval = 0; }              // Deactivate this question
473    // Don't touch the question after this
474    m->rec.r.resrec.RecordType = 0;     // Clear RecordType to show we're not still using it
475}
476
477mDNSexport void AnswerQuestionByFollowingCNAME(mDNS *const m, DNSQuestion *q, ResourceRecord *rr)
478{
479    const mDNSBool selfref = SameDomainName(&q->qname, &rr->rdata->u.name);
480    if (q->CNAMEReferrals >= 10 || selfref)
481    {
482        LogMsg("AnswerQuestionByFollowingCNAME: %p %##s (%s) NOT following CNAME referral %d%s for %s",
483               q, q->qname.c, DNSTypeName(q->qtype), q->CNAMEReferrals, selfref ? " (Self-Referential)" : "", RRDisplayString(m, rr));
484    }
485    else
486    {
487        const mDNSu32 c = q->CNAMEReferrals + 1;        // Stash a copy of the new q->CNAMEReferrals value
488        UDPSocket *sock = q->LocalSocket;
489        mDNSOpaque16 id = q->TargetQID;
490#if AWD_METRICS
491        uDNSMetrics metrics;
492#endif
493
494        q->LocalSocket = mDNSNULL;
495
496        // The SameDomainName check above is to ignore bogus CNAME records that point right back at
497        // themselves. Without that check we can get into a case where we have two duplicate questions,
498        // A and B, and when we stop question A, UpdateQuestionDuplicates copies the value of CNAMEReferrals
499        // from A to B, and then A is re-appended to the end of the list as a duplicate of B (because
500        // the target name is still the same), and then when we stop question B, UpdateQuestionDuplicates
501        // copies the B's value of CNAMEReferrals back to A, and we end up not incrementing CNAMEReferrals
502        // for either of them. This is not a problem for CNAME loops of two or more records because in
503        // those cases the newly re-appended question A has a different target name and therefore cannot be
504        // a duplicate of any other question ('B') which was itself a duplicate of the previous question A.
505
506        // Right now we just stop and re-use the existing query. If we really wanted to be 100% perfect,
507        // and track CNAMEs coming and going, we should really create a subordinate query here,
508        // which we would subsequently cancel and retract if the CNAME referral record were removed.
509        // In reality this is such a corner case we'll ignore it until someone actually needs it.
510
511        LogInfo("AnswerQuestionByFollowingCNAME: %p %##s (%s) following CNAME referral %d for %s",
512                q, q->qname.c, DNSTypeName(q->qtype), q->CNAMEReferrals, RRDisplayString(m, rr));
513
514#if AWD_METRICS
515        if ((q->CNAMEReferrals == 0) && !q->metrics.originalQName)
516        {
517            domainname *    qName;
518            mDNSu16         qNameLen;
519
520            qNameLen = DomainNameLength(&q->qname);
521            if ((qNameLen > 0) && (qNameLen <= MAX_DOMAIN_NAME))
522            {
523                qName = mDNSPlatformMemAllocate(qNameLen);
524                if (qName)
525                {
526                    mDNSPlatformMemCopy(qName->c, q->qname.c, qNameLen);
527                    q->metrics.originalQName = qName;
528                }
529            }
530        }
531        metrics = q->metrics;
532        mDNSPlatformMemZero(&q->metrics, sizeof(q->metrics));
533#endif
534        mDNS_StopQuery_internal(m, q);                              // Stop old query
535        AssignDomainName(&q->qname, &rr->rdata->u.name);            // Update qname
536        q->qnamehash = DomainNameHashValue(&q->qname);              // and namehash
537        // If a unicast query results in a CNAME that points to a .local, we need to re-try
538        // this as unicast. Setting the mDNSInterface_Unicast tells mDNS_StartQuery_internal
539        // to try this as unicast query even though it is a .local name
540        if (!mDNSOpaque16IsZero(q->TargetQID) && IsLocalDomain(&q->qname))
541        {
542            LogInfo("AnswerQuestionByFollowingCNAME: Resolving a .local CNAME %p %##s (%s) Record %s",
543                    q, q->qname.c, DNSTypeName(q->qtype), RRDisplayString(m, rr));
544            q->InterfaceID = mDNSInterface_Unicast;
545        }
546        mDNS_StartQuery_internal(m, q);                             // start new query
547        // Record how many times we've done this. We need to do this *after* mDNS_StartQuery_internal,
548        // because mDNS_StartQuery_internal re-initializes CNAMEReferrals to zero
549        q->CNAMEReferrals = c;
550#if AWD_METRICS
551        metrics.expiredAnswerState = q->metrics.expiredAnswerState; //  We want the newly initialized state for this value
552        q->metrics = metrics;
553#endif
554        if (sock)
555        {
556            // If our new query is a duplicate, then it can't have a socket of its own, so we have to close the one we saved.
557            if (q->DuplicateOf) mDNSPlatformUDPClose(sock);
558            else
559            {
560                // Transplant the old socket into the new question, and copy the query ID across too.
561                // No need to close the old q->LocalSocket value because it won't have been created yet (they're made lazily on-demand).
562                q->LocalSocket = sock;
563                q->TargetQID = id;
564            }
565        }
566    }
567}
568
569#ifdef USE_LIBIDN
570
571#include <unicode/uidna.h>
572
573// #define DEBUG_PUNYCODE 1
574
575mDNSlocal mDNSu8 *PunycodeConvert(const mDNSu8 *const src, mDNSu8 *const dst, const mDNSu8 *const end)
576{
577    UErrorCode errorCode = U_ZERO_ERROR;
578    UIDNAInfo info = UIDNA_INFO_INITIALIZER;
579    UIDNA *uts46 = uidna_openUTS46(UIDNA_USE_STD3_RULES|UIDNA_NONTRANSITIONAL_TO_UNICODE, &errorCode);
580    int32_t len = uidna_nameToASCII_UTF8(uts46, (const char *)src+1, src[0], (char *)dst+1, end-(dst+1), &info, &errorCode);
581    uidna_close(uts46);
582    #if DEBUG_PUNYCODE
583    if (errorCode) LogMsg("uidna_nameToASCII_UTF8(%##s) failed errorCode %d", src, errorCode);
584    if (info.errors) LogMsg("uidna_nameToASCII_UTF8(%##s) failed info.errors 0x%08X", src, info.errors);
585    if (len > MAX_DOMAIN_LABEL) LogMsg("uidna_nameToASCII_UTF8(%##s) result too long %d", src, len);
586    #endif
587    if (errorCode || info.errors || len > MAX_DOMAIN_LABEL) return mDNSNULL;
588    *dst = len;
589    return(dst + 1 + len);
590}
591
592mDNSlocal mDNSBool IsHighASCIILabel(const mDNSu8 *d)
593{
594    int i;
595    for (i=1; i<=d[0]; i++) if (d[i] & 0x80) return mDNStrue;
596    return mDNSfalse;
597}
598
599mDNSlocal const mDNSu8 *FindLastHighASCIILabel(const domainname *const d)
600{
601    const mDNSu8 *ptr = d->c;
602    const mDNSu8 *ans = mDNSNULL;
603    while (ptr[0])
604    {
605        const mDNSu8 *const next = ptr + 1 + ptr[0];
606        if (ptr[0] > MAX_DOMAIN_LABEL || next >= d->c + MAX_DOMAIN_NAME) return mDNSNULL;
607        if (IsHighASCIILabel(ptr)) ans = ptr;
608        ptr = next;
609    }
610    return ans;
611}
612
613mDNSlocal mDNSBool PerformNextPunycodeConversion(const DNSQuestion *const q, domainname *const newname)
614{
615    const mDNSu8 *h = FindLastHighASCIILabel(&q->qname);
616    #if DEBUG_PUNYCODE
617    LogMsg("PerformNextPunycodeConversion: %##s (%s) Last High-ASCII Label %##s", q->qname.c, DNSTypeName(q->qtype), h);
618    #endif
619    if (!h) return mDNSfalse;  // There are no high-ascii labels to convert
620
621    mDNSu8 *const dst = PunycodeConvert(h, newname->c + (h - q->qname.c), newname->c + MAX_DOMAIN_NAME);
622    if (!dst)
623        return mDNSfalse;  // The label was not convertible to Punycode
624    else
625    {
626        // If Punycode conversion of final eligible label was successful, copy the rest of the domainname
627        const mDNSu8 *const src = h + 1 + h[0];
628        const mDNSu8 remainder  = DomainNameLength((domainname*)src);
629        if (dst + remainder > newname->c + MAX_DOMAIN_NAME) return mDNSfalse;  // Name too long -- cannot be converted to Punycode
630
631        mDNSPlatformMemCopy(newname->c, q->qname.c, h - q->qname.c);  // Fill in the leading part
632        mDNSPlatformMemCopy(dst, src, remainder);                     // Fill in the trailing part
633        #if DEBUG_PUNYCODE
634        LogMsg("PerformNextPunycodeConversion: %##s converted to %##s", q->qname.c, newname->c);
635        #endif
636        return mDNStrue;
637    }
638}
639
640#endif // USE_LIBIDN
641
642// For a single given DNSQuestion pointed to by CurrentQuestion, deliver an add/remove result for the single given AuthRecord
643// Note: All the callers should use the m->CurrentQuestion to see if the question is still valid or not
644mDNSlocal void AnswerLocalQuestionWithLocalAuthRecord(mDNS *const m, AuthRecord *rr, QC_result AddRecord)
645{
646    DNSQuestion *q = m->CurrentQuestion;
647    mDNSBool followcname;
648
649    if (!q)
650    {
651        LogMsg("AnswerLocalQuestionWithLocalAuthRecord: ERROR!! CurrentQuestion NULL while answering with %s", ARDisplayString(m, rr));
652        return;
653    }
654
655    followcname = FollowCNAME(q, &rr->resrec, AddRecord);
656
657    // We should not be delivering results for record types Unregistered, Deregistering, and (unverified) Unique
658    if (!(rr->resrec.RecordType & kDNSRecordTypeActiveMask))
659    {
660        LogMsg("AnswerLocalQuestionWithLocalAuthRecord: *NOT* delivering %s event for local record type %X %s",
661               AddRecord ? "Add" : "Rmv", rr->resrec.RecordType, ARDisplayString(m, rr));
662        return;
663    }
664
665    // Indicate that we've given at least one positive answer for this record, so we should be prepared to send a goodbye for it
666    if (AddRecord) rr->AnsweredLocalQ = mDNStrue;
667    mDNS_DropLockBeforeCallback();      // Allow client to legally make mDNS API calls from the callback
668    if (q->QuestionCallback && !q->NoAnswer)
669    {
670        q->CurrentAnswers += AddRecord ? 1 : -1;
671        if (UniqueLocalOnlyRecord(rr))
672        {
673            if (!followcname || q->ReturnIntermed)
674            {
675                // Don't send this packet on the wire as we answered from /etc/hosts
676                q->ThisQInterval = 0;
677                q->LOAddressAnswers += AddRecord ? 1 : -1;
678                q->QuestionCallback(m, q, &rr->resrec, AddRecord);
679            }
680            mDNS_ReclaimLockAfterCallback();    // Decrement mDNS_reentrancy to block mDNS API calls again
681            // The callback above could have caused the question to stop. Detect that
682            // using m->CurrentQuestion
683            if (followcname && m->CurrentQuestion == q)
684                AnswerQuestionByFollowingCNAME(m, q, &rr->resrec);
685            return;
686        }
687        else
688        {
689            q->QuestionCallback(m, q, &rr->resrec, AddRecord);
690        }
691    }
692    mDNS_ReclaimLockAfterCallback();    // Decrement mDNS_reentrancy to block mDNS API calls again
693}
694
695mDNSlocal void AnswerInterfaceAnyQuestionsWithLocalAuthRecord(mDNS *const m, AuthRecord *rr, QC_result AddRecord)
696{
697    if (m->CurrentQuestion)
698        LogMsg("AnswerInterfaceAnyQuestionsWithLocalAuthRecord: ERROR m->CurrentQuestion already set: %##s (%s)",
699               m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
700    m->CurrentQuestion = m->Questions;
701    while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
702    {
703        mDNSBool answered;
704        DNSQuestion *q = m->CurrentQuestion;
705        if (RRAny(rr))
706            answered = ResourceRecordAnswersQuestion(&rr->resrec, q);
707        else
708            answered = LocalOnlyRecordAnswersQuestion(rr, q);
709        if (answered)
710            AnswerLocalQuestionWithLocalAuthRecord(m, rr, AddRecord);       // MUST NOT dereference q again
711        if (m->CurrentQuestion == q)    // If m->CurrentQuestion was not auto-advanced, do it ourselves now
712            m->CurrentQuestion = q->next;
713    }
714    m->CurrentQuestion = mDNSNULL;
715}
716
717// When a new local AuthRecord is created or deleted, AnswerAllLocalQuestionsWithLocalAuthRecord()
718// delivers the appropriate add/remove events to listening questions:
719// 1. It runs though all our LocalOnlyQuestions delivering answers as appropriate,
720//    stopping if it reaches a NewLocalOnlyQuestion -- brand-new questions are handled by AnswerNewLocalOnlyQuestion().
721// 2. If the AuthRecord is marked mDNSInterface_LocalOnly or mDNSInterface_P2P, then it also runs though
722//    our main question list, delivering answers to mDNSInterface_Any questions as appropriate,
723//    stopping if it reaches a NewQuestion -- brand-new questions are handled by AnswerNewQuestion().
724//
725// AnswerAllLocalQuestionsWithLocalAuthRecord is used by the m->NewLocalRecords loop in mDNS_Execute(),
726// and by mDNS_Deregister_internal()
727
728mDNSlocal void AnswerAllLocalQuestionsWithLocalAuthRecord(mDNS *const m, AuthRecord *rr, QC_result AddRecord)
729{
730    if (m->CurrentQuestion)
731        LogMsg("AnswerAllLocalQuestionsWithLocalAuthRecord ERROR m->CurrentQuestion already set: %##s (%s)",
732               m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
733
734    m->CurrentQuestion = m->LocalOnlyQuestions;
735    while (m->CurrentQuestion && m->CurrentQuestion != m->NewLocalOnlyQuestions)
736    {
737        mDNSBool answered;
738        DNSQuestion *q = m->CurrentQuestion;
739        // We are called with both LocalOnly/P2P record or a regular AuthRecord
740        if (RRAny(rr))
741            answered = ResourceRecordAnswersQuestion(&rr->resrec, q);
742        else
743            answered = LocalOnlyRecordAnswersQuestion(rr, q);
744        if (answered)
745            AnswerLocalQuestionWithLocalAuthRecord(m, rr, AddRecord);           // MUST NOT dereference q again
746        if (m->CurrentQuestion == q)    // If m->CurrentQuestion was not auto-advanced, do it ourselves now
747            m->CurrentQuestion = q->next;
748    }
749
750    m->CurrentQuestion = mDNSNULL;
751
752    // If this AuthRecord is marked LocalOnly or P2P, then we want to deliver it to all local 'mDNSInterface_Any' questions
753    if (rr->ARType == AuthRecordLocalOnly || rr->ARType == AuthRecordP2P)
754        AnswerInterfaceAnyQuestionsWithLocalAuthRecord(m, rr, AddRecord);
755
756}
757
758// ***************************************************************************
759#if COMPILER_LIKES_PRAGMA_MARK
760#pragma mark -
761#pragma mark - Resource Record Utility Functions
762#endif
763
764#define RRTypeIsAddressType(T) ((T) == kDNSType_A || (T) == kDNSType_AAAA)
765
766#define ResourceRecordIsValidAnswer(RR) ( ((RR)->resrec.RecordType & kDNSRecordTypeActiveMask)  && \
767                                          ((RR)->Additional1 == mDNSNULL || ((RR)->Additional1->resrec.RecordType & kDNSRecordTypeActiveMask)) && \
768                                          ((RR)->Additional2 == mDNSNULL || ((RR)->Additional2->resrec.RecordType & kDNSRecordTypeActiveMask)) && \
769                                          ((RR)->DependentOn == mDNSNULL || ((RR)->DependentOn->resrec.RecordType & kDNSRecordTypeActiveMask))  )
770
771#define ResourceRecordIsValidInterfaceAnswer(RR, INTID) \
772    (ResourceRecordIsValidAnswer(RR) && \
773     ((RR)->resrec.InterfaceID == mDNSInterface_Any || (RR)->resrec.InterfaceID == (INTID)))
774
775#define DefaultProbeCountForTypeUnique ((mDNSu8)3)
776#define DefaultProbeCountForRecordType(X)      ((X) == kDNSRecordTypeUnique ? DefaultProbeCountForTypeUnique : (mDNSu8)0)
777
778// See RFC 6762: "8.3 Announcing"
779// "The Multicast DNS responder MUST send at least two unsolicited responses, one second apart."
780// Send 4, which is really 8 since we send on both IPv4 and IPv6.
781#define InitialAnnounceCount ((mDNSu8)4)
782
783// For goodbye packets we set the count to 3, and for wakeups we set it to 18
784// (which will be up to 15 wakeup attempts over the course of 30 seconds,
785// and then if the machine fails to wake, 3 goodbye packets).
786#define GoodbyeCount ((mDNSu8)3)
787#define WakeupCount ((mDNSu8)18)
788#define MAX_PROBE_RESTARTS ((mDNSu8)20)
789#define MAX_GHOST_TIME ((mDNSs32)((60*60*24*7)*mDNSPlatformOneSecond))  //  One week
790
791// Number of wakeups we send if WakeOnResolve is set in the question
792#define InitialWakeOnResolveCount ((mDNSu8)3)
793
794// Note that the announce intervals use exponential backoff, doubling each time. The probe intervals do not.
795// This means that because the announce interval is doubled after sending the first packet, the first
796// observed on-the-wire inter-packet interval between announcements is actually one second.
797// The half-second value here may be thought of as a conceptual (non-existent) half-second delay *before* the first packet is sent.
798#define DefaultProbeIntervalForTypeUnique (mDNSPlatformOneSecond/4)
799#define DefaultAnnounceIntervalForTypeShared (mDNSPlatformOneSecond/2)
800#define DefaultAnnounceIntervalForTypeUnique (mDNSPlatformOneSecond/2)
801
802#define DefaultAPIntervalForRecordType(X)  ((X) &kDNSRecordTypeActiveSharedMask ? DefaultAnnounceIntervalForTypeShared : \
803                                            (X) &kDNSRecordTypeUnique           ? DefaultProbeIntervalForTypeUnique    : \
804                                            (X) &kDNSRecordTypeActiveUniqueMask ? DefaultAnnounceIntervalForTypeUnique : 0)
805
806#define TimeToAnnounceThisRecord(RR,time) ((RR)->AnnounceCount && (time) - ((RR)->LastAPTime + (RR)->ThisAPInterval) >= 0)
807#define TicksTTL(RR) ((mDNSs32)(RR)->resrec.rroriginalttl * mDNSPlatformOneSecond)
808#define RRExpireTime(RR) ((RR)->TimeRcvd + TicksTTL(RR))
809
810// Adjustment factor to avoid race condition (used for unicast cache entries) :
811// Suppose real record has TTL of 3600, and our local caching server has held it for 3500 seconds, so it returns an aged TTL of 100.
812// If we do our normal refresh at 80% of the TTL, our local caching server will return 20 seconds, so we'll do another
813// 80% refresh after 16 seconds, and then the server will return 4 seconds, and so on, in the fashion of Zeno's paradox.
814// To avoid this, we extend the record's effective TTL to give it a little extra grace period.
815// We adjust the 100 second TTL to 127. This means that when we do our 80% query at 102 seconds,
816// the cached copy at our local caching server will already have expired, so the server will be forced
817// to fetch a fresh copy from the authoritative server, and then return a fresh record with the full TTL of 3600 seconds.
818
819#define RRAdjustTTL(ttl) ((ttl) + ((ttl)/4) + 2)
820#define RRUnadjustedTTL(ttl) ((((ttl) - 2) * 4) / 5)
821
822#define MaxUnansweredQueries 4
823
824// SameResourceRecordSignature returns true if two resources records have the same name, type, and class, and may be sent
825// (or were received) on the same interface (i.e. if *both* records specify an interface, then it has to match).
826// TTL and rdata may differ.
827// This is used for cache flush management:
828// When sending a unique record, all other records matching "SameResourceRecordSignature" must also be sent
829// When receiving a unique record, all old cache records matching "SameResourceRecordSignature" are flushed
830
831// SameResourceRecordNameClassInterface is functionally the same as SameResourceRecordSignature, except rrtype does not have to match
832
833#define SameResourceRecordSignature(A,B) (A)->resrec.rrtype == (B)->resrec.rrtype && SameResourceRecordNameClassInterface((A),(B))
834
835mDNSlocal mDNSBool SameResourceRecordNameClassInterface(const AuthRecord *const r1, const AuthRecord *const r2)
836{
837    if (!r1) { LogMsg("SameResourceRecordSignature ERROR: r1 is NULL"); return(mDNSfalse); }
838    if (!r2) { LogMsg("SameResourceRecordSignature ERROR: r2 is NULL"); return(mDNSfalse); }
839    if (r1->resrec.InterfaceID &&
840        r2->resrec.InterfaceID &&
841        r1->resrec.InterfaceID != r2->resrec.InterfaceID) return(mDNSfalse);
842    return (mDNSBool)(
843               r1->resrec.rrclass  == r2->resrec.rrclass &&
844               r1->resrec.namehash == r2->resrec.namehash &&
845               SameDomainName(r1->resrec.name, r2->resrec.name));
846}
847
848// PacketRRMatchesSignature behaves as SameResourceRecordSignature, except that types may differ if our
849// authoratative record is unique (as opposed to shared). For unique records, we are supposed to have
850// complete ownership of *all* types for this name, so *any* record type with the same name is a conflict.
851// In addition, when probing we send our questions with the wildcard type kDNSQType_ANY,
852// so a response of any type should match, even if it is not actually the type the client plans to use.
853
854// For now, to make it easier to avoid false conflicts, we treat SPS Proxy records like shared records,
855// and require the rrtypes to match for the rdata to be considered potentially conflicting
856mDNSlocal mDNSBool PacketRRMatchesSignature(const CacheRecord *const pktrr, const AuthRecord *const authrr)
857{
858    if (!pktrr)  { LogMsg("PacketRRMatchesSignature ERROR: pktrr is NULL"); return(mDNSfalse); }
859    if (!authrr) { LogMsg("PacketRRMatchesSignature ERROR: authrr is NULL"); return(mDNSfalse); }
860    if (pktrr->resrec.InterfaceID &&
861        authrr->resrec.InterfaceID &&
862        pktrr->resrec.InterfaceID != authrr->resrec.InterfaceID) return(mDNSfalse);
863    if (!(authrr->resrec.RecordType & kDNSRecordTypeUniqueMask) || authrr->WakeUp.HMAC.l[0])
864        if (pktrr->resrec.rrtype != authrr->resrec.rrtype) return(mDNSfalse);
865    if ((authrr->resrec.InterfaceID == mDNSInterface_Any) &&
866        !mDNSPlatformValidRecordForInterface(authrr, pktrr->resrec.InterfaceID)) return(mDNSfalse);
867    return (mDNSBool)(
868               pktrr->resrec.rrclass == authrr->resrec.rrclass &&
869               pktrr->resrec.namehash == authrr->resrec.namehash &&
870               SameDomainName(pktrr->resrec.name, authrr->resrec.name));
871}
872
873// CacheRecord *ka is the CacheRecord from the known answer list in the query.
874// This is the information that the requester believes to be correct.
875// AuthRecord *rr is the answer we are proposing to give, if not suppressed.
876// This is the information that we believe to be correct.
877// We've already determined that we plan to give this answer on this interface
878// (either the record is non-specific, or it is specific to this interface)
879// so now we just need to check the name, type, class, rdata and TTL.
880mDNSlocal mDNSBool ShouldSuppressKnownAnswer(const CacheRecord *const ka, const AuthRecord *const rr)
881{
882    // If RR signature is different, or data is different, then don't suppress our answer
883    if (!IdenticalResourceRecord(&ka->resrec, &rr->resrec)) return(mDNSfalse);
884
885    // If the requester's indicated TTL is less than half the real TTL,
886    // we need to give our answer before the requester's copy expires.
887    // If the requester's indicated TTL is at least half the real TTL,
888    // then we can suppress our answer this time.
889    // If the requester's indicated TTL is greater than the TTL we believe,
890    // then that's okay, and we don't need to do anything about it.
891    // (If two responders on the network are offering the same information,
892    // that's okay, and if they are offering the information with different TTLs,
893    // the one offering the lower TTL should defer to the one offering the higher TTL.)
894    return (mDNSBool)(ka->resrec.rroriginalttl >= rr->resrec.rroriginalttl / 2);
895}
896
897mDNSlocal void SetNextAnnounceProbeTime(mDNS *const m, const AuthRecord *const rr)
898{
899    if (rr->resrec.RecordType == kDNSRecordTypeUnique)
900    {
901        if ((rr->LastAPTime + rr->ThisAPInterval) - m->timenow > mDNSPlatformOneSecond * 10)
902        {
903            LogMsg("SetNextAnnounceProbeTime: ProbeCount %d Next in %d %s", rr->ProbeCount, (rr->LastAPTime + rr->ThisAPInterval) - m->timenow, ARDisplayString(m, rr));
904            LogMsg("SetNextAnnounceProbeTime: m->SuppressProbes %d m->timenow %d diff %d", m->SuppressProbes, m->timenow, m->SuppressProbes - m->timenow);
905        }
906        if (m->NextScheduledProbe - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
907            m->NextScheduledProbe = (rr->LastAPTime + rr->ThisAPInterval);
908        // Some defensive code:
909        // If (rr->LastAPTime + rr->ThisAPInterval) happens to be far in the past, we don't want to allow
910        // NextScheduledProbe to be set excessively in the past, because that can cause bad things to happen.
911        // See: <rdar://problem/7795434> mDNS: Sometimes advertising stops working and record interval is set to zero
912        if (m->NextScheduledProbe - m->timenow < 0)
913            m->NextScheduledProbe = m->timenow;
914    }
915    else if (rr->AnnounceCount && (ResourceRecordIsValidAnswer(rr) || rr->resrec.RecordType == kDNSRecordTypeDeregistering))
916    {
917        if (m->NextScheduledResponse - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
918            m->NextScheduledResponse = (rr->LastAPTime + rr->ThisAPInterval);
919    }
920}
921
922mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr)
923{
924    // For reverse-mapping Sleep Proxy PTR records, probe interval is one second
925    rr->ThisAPInterval = rr->AddressProxy.type ? mDNSPlatformOneSecond : DefaultAPIntervalForRecordType(rr->resrec.RecordType);
926
927    // * If this is a record type that's going to probe, then we use the m->SuppressProbes time.
928    // * Otherwise, if it's not going to probe, but m->SuppressProbes is set because we have other
929    //   records that are going to probe, then we delay its first announcement so that it will
930    //   go out synchronized with the first announcement for the other records that *are* probing.
931    //   This is a minor performance tweak that helps keep groups of related records synchronized together.
932    //   The addition of "interval / 2" is to make sure that, in the event that any of the probes are
933    //   delayed by a few milliseconds, this announcement does not inadvertently go out *before* the probing is complete.
934    //   When the probing is complete and those records begin to announce, these records will also be picked up and accelerated,
935    //   because they will meet the criterion of being at least half-way to their scheduled announcement time.
936    // * If it's not going to probe and m->SuppressProbes is not already set then we should announce immediately.
937
938    if (rr->ProbeCount)
939    {
940        // If we have no probe suppression time set, or it is in the past, set it now
941        if (m->SuppressProbes == 0 || m->SuppressProbes - m->timenow < 0)
942        {
943            // To allow us to aggregate probes when a group of services are registered together,
944            // the first probe is delayed by a random delay in the range 1/8 to 1/4 second.
945            // This means the common-case behaviour is:
946            // randomized wait; probe
947            // 1/4 second wait; probe
948            // 1/4 second wait; probe
949            // 1/4 second wait; announce (i.e. service is normally announced 7/8 to 1 second after being registered)
950            m->SuppressProbes = NonZeroTime(m->timenow + DefaultProbeIntervalForTypeUnique/2 + mDNSRandom(DefaultProbeIntervalForTypeUnique/2));
951
952            // If we already have a *probe* scheduled to go out sooner, then use that time to get better aggregation
953            if (m->SuppressProbes - m->NextScheduledProbe >= 0)
954                m->SuppressProbes = NonZeroTime(m->NextScheduledProbe);
955            if (m->SuppressProbes - m->timenow < 0)     // Make sure we don't set m->SuppressProbes excessively in the past
956                m->SuppressProbes = m->timenow;
957
958            // If we already have a *query* scheduled to go out sooner, then use that time to get better aggregation
959            if (m->SuppressProbes - m->NextScheduledQuery >= 0)
960                m->SuppressProbes = NonZeroTime(m->NextScheduledQuery);
961            if (m->SuppressProbes - m->timenow < 0)     // Make sure we don't set m->SuppressProbes excessively in the past
962                m->SuppressProbes = m->timenow;
963
964            // except... don't expect to be able to send before the m->SuppressSending timer fires
965            if (m->SuppressSending && m->SuppressProbes - m->SuppressSending < 0)
966                m->SuppressProbes = NonZeroTime(m->SuppressSending);
967
968            if (m->SuppressProbes - m->timenow > mDNSPlatformOneSecond * 8)
969            {
970                LogMsg("InitializeLastAPTime ERROR m->SuppressProbes %d m->NextScheduledProbe %d m->NextScheduledQuery %d m->SuppressSending %d %d",
971                       m->SuppressProbes     - m->timenow,
972                       m->NextScheduledProbe - m->timenow,
973                       m->NextScheduledQuery - m->timenow,
974                       m->SuppressSending,
975                       m->SuppressSending    - m->timenow);
976                m->SuppressProbes = NonZeroTime(m->timenow + DefaultProbeIntervalForTypeUnique/2 + mDNSRandom(DefaultProbeIntervalForTypeUnique/2));
977            }
978        }
979        rr->LastAPTime = m->SuppressProbes - rr->ThisAPInterval;
980    }
981    // Skip kDNSRecordTypeKnownUnique and kDNSRecordTypeShared records here and set their LastAPTime in the "else" block below so
982    // that they get announced immediately, otherwise, their announcement would be delayed until the based on the SuppressProbes value.
983    else if ((rr->resrec.RecordType != kDNSRecordTypeKnownUnique) && (rr->resrec.RecordType != kDNSRecordTypeShared) && m->SuppressProbes && (m->SuppressProbes - m->timenow >= 0))
984        rr->LastAPTime = m->SuppressProbes - rr->ThisAPInterval + DefaultProbeIntervalForTypeUnique * DefaultProbeCountForTypeUnique + rr->ThisAPInterval / 2;
985    else
986        rr->LastAPTime = m->timenow - rr->ThisAPInterval;
987
988    // For reverse-mapping Sleep Proxy PTR records we don't want to start probing instantly -- we
989    // wait one second to give the client a chance to go to sleep, and then start our ARP/NDP probing.
990    // After three probes one second apart with no answer, we conclude the client is now sleeping
991    // and we can begin broadcasting our announcements to take over ownership of that IP address.
992    // If we don't wait for the client to go to sleep, then when the client sees our ARP Announcements there's a risk
993    // (depending on the OS and networking stack it's using) that it might interpret it as a conflict and change its IP address.
994    if (rr->AddressProxy.type)
995        rr->LastAPTime = m->timenow;
996
997    // Set LastMCTime to now, to inhibit multicast responses
998    // (no need to send additional multicast responses when we're announcing anyway)
999    rr->LastMCTime      = m->timenow;
1000    rr->LastMCInterface = mDNSInterfaceMark;
1001
1002    SetNextAnnounceProbeTime(m, rr);
1003}
1004
1005mDNSlocal const domainname *SetUnicastTargetToHostName(mDNS *const m, AuthRecord *rr)
1006{
1007    const domainname *target;
1008    if (rr->AutoTarget)
1009    {
1010        // For autotunnel services pointing at our IPv6 ULA we don't need or want a NAT mapping, but for all other
1011        // advertised services referencing our uDNS hostname, we want NAT mappings automatically created as appropriate,
1012        // with the port number in our advertised SRV record automatically tracking the external mapped port.
1013        DomainAuthInfo *AuthInfo = GetAuthInfoForName_internal(m, rr->resrec.name);
1014        if (!AuthInfo || !AuthInfo->AutoTunnel) rr->AutoTarget = Target_AutoHostAndNATMAP;
1015    }
1016
1017    target = GetServiceTarget(m, rr);
1018    if (!target || target->c[0] == 0)
1019    {
1020        // defer registration until we've got a target
1021        LogInfo("SetUnicastTargetToHostName No target for %s", ARDisplayString(m, rr));
1022        rr->state = regState_NoTarget;
1023        return mDNSNULL;
1024    }
1025    else
1026    {
1027        LogInfo("SetUnicastTargetToHostName target %##s for resource record %s", target->c, ARDisplayString(m,rr));
1028        return target;
1029    }
1030}
1031
1032// Right now this only applies to mDNS (.local) services where the target host is always m->MulticastHostname
1033// Eventually we should unify this with GetServiceTarget() in uDNS.c
1034mDNSlocal void SetTargetToHostName(mDNS *const m, AuthRecord *const rr)
1035{
1036    domainname *const target = GetRRDomainNameTarget(&rr->resrec);
1037    const domainname *newname = &m->MulticastHostname;
1038
1039    if (!target) LogInfo("SetTargetToHostName: Don't know how to set the target of rrtype %s", DNSTypeName(rr->resrec.rrtype));
1040
1041    if (!(rr->ForceMCast || rr->ARType == AuthRecordLocalOnly || rr->ARType == AuthRecordP2P || IsLocalDomain(&rr->namestorage)))
1042    {
1043        const domainname *const n = SetUnicastTargetToHostName(m, rr);
1044        if (n) newname = n;
1045        else { if (target) target->c[0] = 0; SetNewRData(&rr->resrec, mDNSNULL, 0); return; }
1046    }
1047
1048    if (target && SameDomainName(target, newname))
1049        debugf("SetTargetToHostName: Target of %##s is already %##s", rr->resrec.name->c, target->c);
1050
1051    if (target && !SameDomainName(target, newname))
1052    {
1053        AssignDomainName(target, newname);
1054        SetNewRData(&rr->resrec, mDNSNULL, 0);      // Update rdlength, rdestimate, rdatahash
1055
1056        // If we're in the middle of probing this record, we need to start again,
1057        // because changing its rdata may change the outcome of the tie-breaker.
1058        // (If the record type is kDNSRecordTypeUnique (unconfirmed unique) then DefaultProbeCountForRecordType is non-zero.)
1059        rr->ProbeCount     = DefaultProbeCountForRecordType(rr->resrec.RecordType);
1060
1061        // If we've announced this record, we really should send a goodbye packet for the old rdata before
1062        // changing to the new rdata. However, in practice, we only do SetTargetToHostName for unique records,
1063        // so when we announce them we'll set the kDNSClass_UniqueRRSet and clear any stale data that way.
1064        if (rr->RequireGoodbye && rr->resrec.RecordType == kDNSRecordTypeShared)
1065            debugf("Have announced shared record %##s (%s) at least once: should have sent a goodbye packet before updating",
1066                   rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
1067
1068        rr->AnnounceCount  = InitialAnnounceCount;
1069        rr->RequireGoodbye = mDNSfalse;
1070        rr->ProbeRestartCount = 0;
1071        InitializeLastAPTime(m, rr);
1072    }
1073}
1074
1075mDNSlocal void AcknowledgeRecord(mDNS *const m, AuthRecord *const rr)
1076{
1077    if (rr->RecordCallback)
1078    {
1079        // CAUTION: MUST NOT do anything more with rr after calling rr->Callback(), because the client's callback function
1080        // is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc.
1081        rr->Acknowledged = mDNStrue;
1082        mDNS_DropLockBeforeCallback();      // Allow client to legally make mDNS API calls from the callback
1083        rr->RecordCallback(m, rr, mStatus_NoError);
1084        mDNS_ReclaimLockAfterCallback();    // Decrement mDNS_reentrancy to block mDNS API calls again
1085    }
1086}
1087
1088mDNSexport void ActivateUnicastRegistration(mDNS *const m, AuthRecord *const rr)
1089{
1090    // Make sure that we don't activate the SRV record and associated service records, if it is in
1091    // NoTarget state. First time when a service is being instantiated, SRV record may be in NoTarget state.
1092    // We should not activate any of the other reords (PTR, TXT) that are part of the service. When
1093    // the target becomes available, the records will be reregistered.
1094    if (rr->resrec.rrtype != kDNSType_SRV)
1095    {
1096        AuthRecord *srvRR = mDNSNULL;
1097        if (rr->resrec.rrtype == kDNSType_PTR)
1098            srvRR = rr->Additional1;
1099        else if (rr->resrec.rrtype == kDNSType_TXT)
1100            srvRR = rr->DependentOn;
1101        if (srvRR)
1102        {
1103            if (srvRR->resrec.rrtype != kDNSType_SRV)
1104            {
1105                LogMsg("ActivateUnicastRegistration: ERROR!! Resource record %s wrong, expecting SRV type", ARDisplayString(m, srvRR));
1106            }
1107            else
1108            {
1109                LogInfo("ActivateUnicastRegistration: Found Service Record %s in state %d for %##s (%s)",
1110                        ARDisplayString(m, srvRR), srvRR->state, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
1111                rr->state = srvRR->state;
1112            }
1113        }
1114    }
1115
1116    if (rr->state == regState_NoTarget)
1117    {
1118        LogInfo("ActivateUnicastRegistration record %s in regState_NoTarget, not activating", ARDisplayString(m, rr));
1119        return;
1120    }
1121    // When we wake up from sleep, we call ActivateUnicastRegistration. It is possible that just before we went to sleep,
1122    // the service/record was being deregistered. In that case, we should not try to register again. For the cases where
1123    // the records are deregistered due to e.g., no target for the SRV record, we would have returned from above if it
1124    // was already in NoTarget state. If it was in the process of deregistration but did not complete fully before we went
1125    // to sleep, then it is okay to start in Pending state as we will go back to NoTarget state if we don't have a target.
1126    if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
1127    {
1128        LogInfo("ActivateUnicastRegistration: Resource record %s, current state %d, moving to DeregPending", ARDisplayString(m, rr), rr->state);
1129        rr->state = regState_DeregPending;
1130    }
1131    else
1132    {
1133        LogInfo("ActivateUnicastRegistration: Resource record %s, current state %d, moving to Pending", ARDisplayString(m, rr), rr->state);
1134        rr->state = regState_Pending;
1135    }
1136    rr->ProbeCount     = 0;
1137    rr->ProbeRestartCount = 0;
1138    rr->AnnounceCount  = 0;
1139    rr->ThisAPInterval = INIT_RECORD_REG_INTERVAL;
1140    rr->LastAPTime     = m->timenow - rr->ThisAPInterval;
1141    rr->expire         = 0; // Forget about all the leases, start fresh
1142    rr->uselease       = mDNStrue;
1143    rr->updateid       = zeroID;
1144    rr->SRVChanged     = mDNSfalse;
1145    rr->updateError    = mStatus_NoError;
1146    // RestartRecordGetZoneData calls this function whenever a new interface gets registered with core.
1147    // The records might already be registered with the server and hence could have NAT state.
1148    if (rr->NATinfo.clientContext)
1149    {
1150        mDNS_StopNATOperation_internal(m, &rr->NATinfo);
1151        rr->NATinfo.clientContext = mDNSNULL;
1152    }
1153    if (rr->nta) { CancelGetZoneData(m, rr->nta); rr->nta = mDNSNULL; }
1154    if (rr->tcp) { DisposeTCPConn(rr->tcp);       rr->tcp = mDNSNULL; }
1155    if (m->NextuDNSEvent - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
1156        m->NextuDNSEvent = (rr->LastAPTime + rr->ThisAPInterval);
1157}
1158
1159// Two records qualify to be local duplicates if:
1160// (a) the RecordTypes are the same, or
1161// (b) one is Unique and the other Verified
1162// (c) either is in the process of deregistering
1163#define RecordLDT(A,B) ((A)->resrec.RecordType == (B)->resrec.RecordType || \
1164                        ((A)->resrec.RecordType | (B)->resrec.RecordType) == (kDNSRecordTypeUnique | kDNSRecordTypeVerified) || \
1165                        ((A)->resrec.RecordType == kDNSRecordTypeDeregistering || (B)->resrec.RecordType == kDNSRecordTypeDeregistering))
1166
1167#define RecordIsLocalDuplicate(A,B) \
1168    ((A)->resrec.InterfaceID == (B)->resrec.InterfaceID && RecordLDT((A),(B)) && IdenticalResourceRecord(& (A)->resrec, & (B)->resrec))
1169
1170mDNSlocal AuthRecord *CheckAuthIdenticalRecord(AuthHash *r, AuthRecord *rr)
1171{
1172    const AuthGroup *a;
1173    AuthRecord *rp;
1174
1175    a = AuthGroupForRecord(r, &rr->resrec);
1176    if (!a) return mDNSNULL;
1177    rp = a->members;
1178    while (rp)
1179    {
1180        if (!RecordIsLocalDuplicate(rp, rr))
1181            rp = rp->next;
1182        else
1183        {
1184            if (rp->resrec.RecordType == kDNSRecordTypeDeregistering)
1185            {
1186                rp->AnnounceCount = 0;
1187                rp = rp->next;
1188            }
1189            else return rp;
1190        }
1191    }
1192    return (mDNSNULL);
1193}
1194
1195mDNSlocal mDNSBool CheckAuthRecordConflict(AuthHash *r, AuthRecord *rr)
1196{
1197    const AuthGroup *a;
1198    const AuthRecord *rp;
1199
1200    a = AuthGroupForRecord(r, &rr->resrec);
1201    if (!a) return mDNSfalse;
1202    rp = a->members;
1203    while (rp)
1204    {
1205        const AuthRecord *s1 = rr->RRSet ? rr->RRSet : rr;
1206        const AuthRecord *s2 = rp->RRSet ? rp->RRSet : rp;
1207        if (s1 != s2 && SameResourceRecordSignature(rp, rr) && !IdenticalSameNameRecord(&rp->resrec, &rr->resrec))
1208            return mDNStrue;
1209        else
1210            rp = rp->next;
1211    }
1212    return (mDNSfalse);
1213}
1214
1215// checks to see if "rr" is already present
1216mDNSlocal AuthRecord *CheckAuthSameRecord(AuthHash *r, AuthRecord *rr)
1217{
1218    const AuthGroup *a;
1219    AuthRecord *rp;
1220
1221    a = AuthGroupForRecord(r, &rr->resrec);
1222    if (!a) return mDNSNULL;
1223    rp = a->members;
1224    while (rp)
1225    {
1226        if (rp != rr)
1227            rp = rp->next;
1228        else
1229        {
1230            return rp;
1231        }
1232    }
1233    return (mDNSNULL);
1234}
1235
1236
1237mDNSlocal void DecrementAutoTargetServices(mDNS *const m, AuthRecord *const rr)
1238{
1239    if (RRLocalOnly(rr))
1240    {
1241        // A sanity check, this should be prevented in calling code.
1242        LogInfo("DecrementAutoTargetServices: called for RRLocalOnly() record: %s", ARDisplayString(m, rr));
1243        return;
1244    }
1245
1246    if (!AuthRecord_uDNS(rr) && rr->resrec.rrtype == kDNSType_SRV && rr->AutoTarget == Target_AutoHost)
1247    {
1248        // If about to get rid of the last advertised service
1249        if (m->AutoTargetServices == 1)
1250            DeadvertiseAllInterfaceRecords(m);
1251
1252        m->AutoTargetServices--;
1253        LogInfo("DecrementAutoTargetServices: AutoTargetServices %d Record %s", m->AutoTargetServices, ARDisplayString(m, rr));
1254    }
1255
1256#if BONJOUR_ON_DEMAND
1257    if (!AuthRecord_uDNS(rr))
1258    {
1259        if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1)
1260            m->NextBonjourDisableTime = NonZeroTime(m->timenow + (BONJOUR_DISABLE_DELAY * mDNSPlatformOneSecond));
1261        m->NumAllInterfaceRecords--;
1262        LogInfo("DecrementAutoTargetServices: NumAllInterfaceRecords %d NumAllInterfaceQuestions %d %s",
1263            m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, ARDisplayString(m, rr));
1264    }
1265#endif // BONJOUR_ON_DEMAND
1266}
1267
1268mDNSlocal void IncrementAutoTargetServices(mDNS *const m, AuthRecord *const rr)
1269{
1270    mDNSBool enablingBonjour = 0;
1271
1272    if (RRLocalOnly(rr))
1273    {
1274        // A sanity check, this should be prevented in calling code.
1275        LogInfo("IncrementAutoTargetServices: called for RRLocalOnly() record: %s", ARDisplayString(m, rr));
1276        return;
1277    }
1278
1279#if BONJOUR_ON_DEMAND
1280    if (!AuthRecord_uDNS(rr))
1281    {
1282        m->NumAllInterfaceRecords++;
1283        LogInfo("IncrementAutoTargetServices: NumAllInterfaceRecords %d NumAllInterfaceQuestions %d %s",
1284            m->NumAllInterfaceRecords, m->NumAllInterfaceQuestions, ARDisplayString(m, rr));
1285        if (m->NumAllInterfaceRecords + m->NumAllInterfaceQuestions == 1)
1286        {
1287            m->NextBonjourDisableTime = 0;
1288            if (m->BonjourEnabled == 0)
1289            {
1290                // Enable Bonjour immediately by scheduling network changed processing where
1291                // we will join the multicast group on each active interface.
1292                m->BonjourEnabled = 1;
1293                enablingBonjour = 1;
1294                m->NetworkChanged = m->timenow;
1295            }
1296        }
1297    }
1298#endif // BONJOUR_ON_DEMAND
1299
1300    if (!AuthRecord_uDNS(rr) && rr->resrec.rrtype == kDNSType_SRV && rr->AutoTarget == Target_AutoHost)
1301    {
1302        m->AutoTargetServices++;
1303        LogInfo("IncrementAutoTargetServices: AutoTargetServices %d Record %s", m->AutoTargetServices, ARDisplayString(m, rr));
1304
1305        // If this is the first advertised service and we did not just enable Bonjour above, then
1306        // advertise all the interface records.  If we did enable Bonjour above, the interface records will
1307        // be advertised during the network changed processing scheduled above, so no need
1308        // to do it here.
1309        if ((m->AutoTargetServices == 1) && (enablingBonjour == 0))
1310            AdvertiseAllInterfaceRecords(m);
1311    }
1312}
1313
1314mDNSlocal void getKeepaliveRaddr(mDNS *const m, AuthRecord *rr, mDNSAddr *raddr)
1315{
1316    mDNSAddr     laddr = zeroAddr;
1317    mDNSEthAddr  eth = zeroEthAddr;
1318    mDNSIPPort   lport = zeroIPPort;
1319    mDNSIPPort   rport = zeroIPPort;
1320    mDNSu32      timeout = 0;
1321    mDNSu32      seq = 0;
1322    mDNSu32      ack = 0;
1323    mDNSu16      win = 0;
1324
1325    if (mDNS_KeepaliveRecord(&rr->resrec))
1326    {
1327        mDNS_ExtractKeepaliveInfo(rr, &timeout, &laddr, raddr, &eth, &seq, &ack, &lport, &rport, &win);
1328        if (!timeout || mDNSAddressIsZero(&laddr) || mDNSAddressIsZero(raddr) || mDNSIPPortIsZero(lport) || mDNSIPPortIsZero(rport))
1329        {
1330            LogMsg("getKeepaliveRaddr: not a valid record %s for keepalive %#a:%d %#a:%d", ARDisplayString(m, rr), &laddr, lport.NotAnInteger, raddr, rport.NotAnInteger);
1331            return;
1332        }
1333    }
1334}
1335
1336// Exported so uDNS.c can call this
1337mDNSexport mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
1338{
1339    domainname *target = GetRRDomainNameTarget(&rr->resrec);
1340    AuthRecord *r;
1341    AuthRecord **p = &m->ResourceRecords;
1342    AuthRecord **d = &m->DuplicateRecords;
1343
1344    if ((mDNSs32)rr->resrec.rroriginalttl <= 0)
1345    { LogMsg("mDNS_Register_internal: TTL %X should be 1 - 0x7FFFFFFF %s", rr->resrec.rroriginalttl, ARDisplayString(m, rr)); return(mStatus_BadParamErr); }
1346
1347    if (!rr->resrec.RecordType)
1348    { LogMsg("mDNS_Register_internal: RecordType must be non-zero %s", ARDisplayString(m, rr)); return(mStatus_BadParamErr); }
1349
1350    if (m->ShutdownTime)
1351    { LogMsg("mDNS_Register_internal: Shutting down, can't register %s", ARDisplayString(m, rr)); return(mStatus_ServiceNotRunning); }
1352
1353    if (m->DivertMulticastAdvertisements && !AuthRecord_uDNS(rr))
1354    {
1355        mDNSInterfaceID previousID = rr->resrec.InterfaceID;
1356        if (rr->resrec.InterfaceID == mDNSInterface_Any || rr->resrec.InterfaceID == mDNSInterface_P2P)
1357        {
1358            rr->resrec.InterfaceID = mDNSInterface_LocalOnly;
1359            rr->ARType = AuthRecordLocalOnly;
1360        }
1361        if (rr->resrec.InterfaceID != mDNSInterface_LocalOnly)
1362        {
1363            NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID);
1364            if (intf && !intf->Advertise) { rr->resrec.InterfaceID = mDNSInterface_LocalOnly; rr->ARType = AuthRecordLocalOnly; }
1365        }
1366        if (rr->resrec.InterfaceID != previousID)
1367            LogInfo("mDNS_Register_internal: Diverting record to local-only %s", ARDisplayString(m, rr));
1368    }
1369
1370    if (RRLocalOnly(rr))
1371    {
1372        if (CheckAuthSameRecord(&m->rrauth, rr))
1373        {
1374            LogMsg("mDNS_Register_internal: ERROR!! Tried to register LocalOnly AuthRecord %p %##s (%s) that's already in the list",
1375                   rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
1376            return(mStatus_AlreadyRegistered);
1377        }
1378    }
1379    else
1380    {
1381        while (*p && *p != rr) p=&(*p)->next;
1382        if (*p)
1383        {
1384            LogMsg("mDNS_Register_internal: ERROR!! Tried to register AuthRecord %p %##s (%s) that's already in the list",
1385                   rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
1386            return(mStatus_AlreadyRegistered);
1387        }
1388    }
1389
1390    while (*d && *d != rr) d=&(*d)->next;
1391    if (*d)
1392    {
1393        LogMsg("mDNS_Register_internal: ERROR!! Tried to register AuthRecord %p %##s (%s) that's already in the Duplicate list",
1394               rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
1395        return(mStatus_AlreadyRegistered);
1396    }
1397
1398    if (rr->DependentOn)
1399    {
1400        if (rr->resrec.RecordType == kDNSRecordTypeUnique)
1401            rr->resrec.RecordType =  kDNSRecordTypeVerified;
1402        else if (rr->resrec.RecordType != kDNSRecordTypeKnownUnique)
1403        {
1404            LogMsg("mDNS_Register_internal: ERROR! %##s (%s): rr->DependentOn && RecordType != kDNSRecordTypeUnique or kDNSRecordTypeKnownUnique",
1405                   rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
1406            return(mStatus_Invalid);
1407        }
1408        if (!(rr->DependentOn->resrec.RecordType & (kDNSRecordTypeUnique | kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique)))
1409        {
1410            LogMsg("mDNS_Register_internal: ERROR! %##s (%s): rr->DependentOn->RecordType bad type %X",
1411                   rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->DependentOn->resrec.RecordType);
1412            return(mStatus_Invalid);
1413        }
1414    }
1415
1416    rr->next = mDNSNULL;
1417
1418    // Field Group 1: The actual information pertaining to this resource record
1419    // Set up by client prior to call
1420
1421    // Field Group 2: Persistent metadata for Authoritative Records
1422//  rr->Additional1       = set to mDNSNULL  in mDNS_SetupResourceRecord; may be overridden by client
1423//  rr->Additional2       = set to mDNSNULL  in mDNS_SetupResourceRecord; may be overridden by client
1424//  rr->DependentOn       = set to mDNSNULL  in mDNS_SetupResourceRecord; may be overridden by client
1425//  rr->RRSet             = set to mDNSNULL  in mDNS_SetupResourceRecord; may be overridden by client
1426//  rr->Callback          = already set      in mDNS_SetupResourceRecord
1427//  rr->Context           = already set      in mDNS_SetupResourceRecord
1428//  rr->RecordType        = already set      in mDNS_SetupResourceRecord
1429//  rr->HostTarget        = set to mDNSfalse in mDNS_SetupResourceRecord; may be overridden by client
1430//  rr->AllowRemoteQuery  = set to mDNSfalse in mDNS_SetupResourceRecord; may be overridden by client
1431    // Make sure target is not uninitialized data, or we may crash writing debugging log messages
1432    if (rr->AutoTarget && target) target->c[0] = 0;
1433
1434    // Field Group 3: Transient state for Authoritative Records
1435    rr->Acknowledged      = mDNSfalse;
1436    rr->ProbeCount        = DefaultProbeCountForRecordType(rr->resrec.RecordType);
1437    rr->ProbeRestartCount = 0;
1438    rr->AnnounceCount     = InitialAnnounceCount;
1439    rr->RequireGoodbye    = mDNSfalse;
1440    rr->AnsweredLocalQ    = mDNSfalse;
1441    rr->IncludeInProbe    = mDNSfalse;
1442    rr->ImmedUnicast      = mDNSfalse;
1443    rr->SendNSECNow       = mDNSNULL;
1444    rr->ImmedAnswer       = mDNSNULL;
1445    rr->ImmedAdditional   = mDNSNULL;
1446    rr->SendRNow          = mDNSNULL;
1447    rr->v4Requester       = zerov4Addr;
1448    rr->v6Requester       = zerov6Addr;
1449    rr->NextResponse      = mDNSNULL;
1450    rr->NR_AnswerTo       = mDNSNULL;
1451    rr->NR_AdditionalTo   = mDNSNULL;
1452    if (!rr->AutoTarget) InitializeLastAPTime(m, rr);
1453//  rr->LastAPTime        = Set for us in InitializeLastAPTime()
1454//  rr->LastMCTime        = Set for us in InitializeLastAPTime()
1455//  rr->LastMCInterface   = Set for us in InitializeLastAPTime()
1456    rr->NewRData          = mDNSNULL;
1457    rr->newrdlength       = 0;
1458    rr->UpdateCallback    = mDNSNULL;
1459    rr->UpdateCredits     = kMaxUpdateCredits;
1460    rr->NextUpdateCredit  = 0;
1461    rr->UpdateBlocked     = 0;
1462
1463    // For records we're holding as proxy (except reverse-mapping PTR records) two announcements is sufficient
1464    if (rr->WakeUp.HMAC.l[0] && !rr->AddressProxy.type) rr->AnnounceCount = 2;
1465
1466    // Field Group 4: Transient uDNS state for Authoritative Records
1467    rr->state             = regState_Zero;
1468    rr->uselease          = 0;
1469    rr->expire            = 0;
1470    rr->Private           = 0;
1471    rr->updateid          = zeroID;
1472    rr->updateIntID       = zeroOpaque64;
1473    rr->zone              = rr->resrec.name;
1474    rr->nta               = mDNSNULL;
1475    rr->tcp               = mDNSNULL;
1476    rr->OrigRData         = 0;
1477    rr->OrigRDLen         = 0;
1478    rr->InFlightRData     = 0;
1479    rr->InFlightRDLen     = 0;
1480    rr->QueuedRData       = 0;
1481    rr->QueuedRDLen       = 0;
1482    //mDNSPlatformMemZero(&rr->NATinfo, sizeof(rr->NATinfo));
1483    // We should be recording the actual internal port for this service record here. Once we initiate our NAT mapping
1484    // request we'll subsequently overwrite srv.port with the allocated external NAT port -- potentially multiple
1485    // times with different values if the external NAT port changes during the lifetime of the service registration.
1486    //if (rr->resrec.rrtype == kDNSType_SRV) rr->NATinfo.IntPort = rr->resrec.rdata->u.srv.port;
1487
1488//  rr->resrec.interface         = already set in mDNS_SetupResourceRecord
1489//  rr->resrec.name->c           = MUST be set by client
1490//  rr->resrec.rrtype            = already set in mDNS_SetupResourceRecord
1491//  rr->resrec.rrclass           = already set in mDNS_SetupResourceRecord
1492//  rr->resrec.rroriginalttl     = already set in mDNS_SetupResourceRecord
1493//  rr->resrec.rdata             = MUST be set by client, unless record type is CNAME or PTR and rr->HostTarget is set
1494
1495    // BIND named (name daemon) doesn't allow TXT records with zero-length rdata. This is strictly speaking correct,
1496    // since RFC 1035 specifies a TXT record as "One or more <character-string>s", not "Zero or more <character-string>s".
1497    // Since some legacy apps try to create zero-length TXT records, we'll silently correct it here.
1498    if (rr->resrec.rrtype == kDNSType_TXT && rr->resrec.rdlength == 0) { rr->resrec.rdlength = 1; rr->resrec.rdata->u.txt.c[0] = 0; }
1499
1500    if (rr->AutoTarget)
1501    {
1502        SetTargetToHostName(m, rr); // Also sets rdlength and rdestimate for us, and calls InitializeLastAPTime();
1503#ifndef UNICAST_DISABLED
1504        // If we have no target record yet, SetTargetToHostName will set rr->state == regState_NoTarget
1505        // In this case we leave the record half-formed in the list, and later we'll remove it from the list and re-add it properly.
1506        if (rr->state == regState_NoTarget)
1507        {
1508            // Initialize the target so that we don't crash while logging etc.
1509            domainname *tar = GetRRDomainNameTarget(&rr->resrec);
1510            if (tar) tar->c[0] = 0;
1511            LogInfo("mDNS_Register_internal: record %s in NoTarget state", ARDisplayString(m, rr));
1512        }
1513#endif
1514    }
1515    else
1516    {
1517        rr->resrec.rdlength   = GetRDLength(&rr->resrec, mDNSfalse);
1518        rr->resrec.rdestimate = GetRDLength(&rr->resrec, mDNStrue);
1519    }
1520
1521    if (!ValidateDomainName(rr->resrec.name))
1522    { LogMsg("Attempt to register record with invalid name: %s", ARDisplayString(m, rr)); return(mStatus_Invalid); }
1523
1524    // Don't do this until *after* we've set rr->resrec.rdlength
1525    if (!ValidateRData(rr->resrec.rrtype, rr->resrec.rdlength, rr->resrec.rdata))
1526    { LogMsg("Attempt to register record with invalid rdata: %s", ARDisplayString(m, rr)); return(mStatus_Invalid); }
1527
1528    rr->resrec.namehash   = DomainNameHashValue(rr->resrec.name);
1529    rr->resrec.rdatahash  = target ? DomainNameHashValue(target) : RDataHashValue(&rr->resrec);
1530
1531    if (RRLocalOnly(rr))
1532    {
1533        // If this is supposed to be unique, make sure we don't have any name conflicts.
1534        // If we found a conflict, we may still want to insert the record in the list but mark it appropriately
1535        // (kDNSRecordTypeDeregistering) so that we deliver RMV events to the application. But this causes more
1536        // complications and not clear whether there are any benefits. See rdar:9304275 for details.
1537        // Hence, just bail out.
1538        // This comment is doesn���t make any sense. -- SC
1539        if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
1540        {
1541            if (CheckAuthRecordConflict(&m->rrauth, rr))
1542            {
1543                LogInfo("mDNS_Register_internal: Name conflict %s (%p), InterfaceID %p", ARDisplayString(m, rr), rr, rr->resrec.InterfaceID);
1544                return mStatus_NameConflict;
1545            }
1546        }
1547    }
1548
1549    // For uDNS records, we don't support duplicate checks at this time.
1550#ifndef UNICAST_DISABLED
1551    if (AuthRecord_uDNS(rr))
1552    {
1553        if (!m->NewLocalRecords) m->NewLocalRecords = rr;
1554        // When we called SetTargetToHostName, it may have caused mDNS_Register_internal to be re-entered, appending new
1555        // records to the list, so we now need to update p to advance to the new end to the list before appending our new record.
1556        // Note that for AutoTunnel this should never happen, but this check makes the code future-proof.
1557        while (*p) p=&(*p)->next;
1558        *p = rr;
1559        if (rr->resrec.RecordType == kDNSRecordTypeUnique) rr->resrec.RecordType = kDNSRecordTypeVerified;
1560        rr->ProbeCount    = 0;
1561        rr->ProbeRestartCount = 0;
1562        rr->AnnounceCount = 0;
1563        if (rr->state != regState_NoTarget) ActivateUnicastRegistration(m, rr);
1564        return(mStatus_NoError);            // <--- Note: For unicast records, code currently bails out at this point
1565    }
1566#endif
1567
1568    // Now that we've finished building our new record, make sure it's not identical to one we already have
1569    if (RRLocalOnly(rr))
1570    {
1571        rr->ProbeCount    = 0;
1572        rr->ProbeRestartCount = 0;
1573        rr->AnnounceCount = 0;
1574        r = CheckAuthIdenticalRecord(&m->rrauth, rr);
1575    }
1576    else
1577    {
1578        for (r = m->ResourceRecords; r; r=r->next)
1579            if (RecordIsLocalDuplicate(r, rr))
1580            {
1581                if (r->resrec.RecordType == kDNSRecordTypeDeregistering) r->AnnounceCount = 0;
1582                else break;
1583            }
1584    }
1585
1586    if (r)
1587    {
1588        LogInfo("mDNS_Register_internal: Adding to duplicate list %s", ARDisplayString(m,rr));
1589        *d = rr;
1590        // If the previous copy of this record is already verified unique,
1591        // then indicate that we should move this record promptly to kDNSRecordTypeUnique state.
1592        // Setting ProbeCount to zero will cause SendQueries() to advance this record to
1593        // kDNSRecordTypeVerified state and call the client callback at the next appropriate time.
1594        if (rr->resrec.RecordType == kDNSRecordTypeUnique && r->resrec.RecordType == kDNSRecordTypeVerified)
1595            rr->ProbeCount = 0;
1596    }
1597    else
1598    {
1599        LogInfo("mDNS_Register_internal: Adding to active record list %s", ARDisplayString(m,rr));
1600        if (RRLocalOnly(rr))
1601        {
1602            AuthGroup *ag;
1603            ag = InsertAuthRecord(m, &m->rrauth, rr);
1604            if (ag && !ag->NewLocalOnlyRecords)
1605            {
1606                m->NewLocalOnlyRecords = mDNStrue;
1607                ag->NewLocalOnlyRecords = rr;
1608            }
1609            // No probing for LocalOnly records; acknowledge them right away
1610            if (rr->resrec.RecordType == kDNSRecordTypeUnique) rr->resrec.RecordType = kDNSRecordTypeVerified;
1611            AcknowledgeRecord(m, rr);
1612            return(mStatus_NoError);
1613        }
1614        else
1615        {
1616            if (!m->NewLocalRecords) m->NewLocalRecords = rr;
1617            *p = rr;
1618        }
1619    }
1620
1621    if (!AuthRecord_uDNS(rr))   // This check is superfluous, given that for unicast records we (currently) bail out above
1622    {
1623        // We have inserted the record in the list. See if we have to advertise the A/AAAA, HINFO, PTR records.
1624        IncrementAutoTargetServices(m, rr);
1625
1626        // For records that are not going to probe, acknowledge them right away
1627        if (rr->resrec.RecordType != kDNSRecordTypeUnique && rr->resrec.RecordType != kDNSRecordTypeDeregistering)
1628            AcknowledgeRecord(m, rr);
1629
1630        // Adding a record may affect whether or not we should sleep
1631        mDNS_UpdateAllowSleep(m);
1632    }
1633
1634    // If this is a non-sleep proxy keepalive record, fetch the MAC address of the remote host.
1635    // This is used by the in-NIC proxy to send the keepalive packets.
1636    if (!rr->WakeUp.HMAC.l[0] && mDNS_KeepaliveRecord(&rr->resrec))
1637    {
1638        mDNSAddr raddr;
1639        // Set the record type to known unique to prevent probing keep alive records.
1640        // Also make sure we do not announce the keepalive records.
1641       rr->resrec.RecordType = kDNSRecordTypeKnownUnique;
1642       rr->AnnounceCount     = 0;
1643       getKeepaliveRaddr(m, rr, &raddr);
1644       // This is an asynchronous call. Once the remote MAC address is available, helper will schedule an
1645       // asynchronous task to update the resource record
1646       mDNSPlatformGetRemoteMacAddr(&raddr);
1647    }
1648
1649    return(mStatus_NoError);
1650}
1651
1652mDNSlocal void RecordProbeFailure(mDNS *const m, const AuthRecord *const rr)
1653{
1654    m->ProbeFailTime = m->timenow;
1655    m->NumFailedProbes++;
1656    // If we've had fifteen or more probe failures, rate-limit to one every five seconds.
1657    // If a bunch of hosts have all been configured with the same name, then they'll all
1658    // conflict and run through the same series of names: name-2, name-3, name-4, etc.,
1659    // up to name-10. After that they'll start adding random increments in the range 1-100,
1660    // so they're more likely to branch out in the available namespace and settle on a set of
1661    // unique names quickly. If after five more tries the host is still conflicting, then we
1662    // may have a serious problem, so we start rate-limiting so we don't melt down the network.
1663    if (m->NumFailedProbes >= 15)
1664    {
1665        m->SuppressProbes = NonZeroTime(m->timenow + mDNSPlatformOneSecond * 5);
1666        LogMsg("Excessive name conflicts (%lu) for %##s (%s); rate limiting in effect",
1667               m->NumFailedProbes, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
1668    }
1669}
1670
1671mDNSlocal void CompleteRDataUpdate(mDNS *const m, AuthRecord *const rr)
1672{
1673    RData *OldRData = rr->resrec.rdata;
1674    mDNSu16 OldRDLen = rr->resrec.rdlength;
1675    SetNewRData(&rr->resrec, rr->NewRData, rr->newrdlength);    // Update our rdata
1676    rr->NewRData = mDNSNULL;                                    // Clear the NewRData pointer ...
1677    if (rr->UpdateCallback)
1678        rr->UpdateCallback(m, rr, OldRData, OldRDLen);          // ... and let the client know
1679}
1680
1681// Note: mDNS_Deregister_internal can call a user callback, which may change the record list and/or question list.
1682// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
1683// Exported so uDNS.c can call this
1684mDNSexport mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr, mDNS_Dereg_type drt)
1685{
1686    AuthRecord *r2;
1687    mDNSu8 RecordType = rr->resrec.RecordType;
1688    AuthRecord **p = &m->ResourceRecords;   // Find this record in our list of active records
1689    mDNSBool dupList = mDNSfalse;
1690
1691    if (RRLocalOnly(rr))
1692    {
1693        AuthGroup *a;
1694        AuthRecord **rp;
1695
1696        a = AuthGroupForRecord(&m->rrauth, &rr->resrec);
1697        if (!a) return mDNSfalse;
1698        rp = &a->members;
1699        while (*rp && *rp != rr) rp=&(*rp)->next;
1700        p = rp;
1701    }
1702    else
1703    {
1704        while (*p && *p != rr) p=&(*p)->next;
1705    }
1706
1707    if (*p)
1708    {
1709        // We found our record on the main list. See if there are any duplicates that need special handling.
1710        if (drt == mDNS_Dereg_conflict)     // If this was a conflict, see that all duplicates get the same treatment
1711        {
1712            // Scan for duplicates of rr, and mark them for deregistration at the end of this routine, after we've finished
1713            // deregistering rr. We need to do this scan *before* we give the client the chance to free and reuse the rr memory.
1714            for (r2 = m->DuplicateRecords; r2; r2=r2->next) if (RecordIsLocalDuplicate(r2, rr)) r2->ProbeCount = 0xFF;
1715        }
1716        else
1717        {
1718            // Before we delete the record (and potentially send a goodbye packet)
1719            // first see if we have a record on the duplicate list ready to take over from it.
1720            AuthRecord **d = &m->DuplicateRecords;
1721            while (*d && !RecordIsLocalDuplicate(*d, rr)) d=&(*d)->next;
1722            if (*d)
1723            {
1724                AuthRecord *dup = *d;
1725                debugf("mDNS_Register_internal: Duplicate record %p taking over from %p %##s (%s)",
1726                       dup, rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
1727                *d        = dup->next;      // Cut replacement record from DuplicateRecords list
1728                if (RRLocalOnly(rr))
1729                {
1730                    dup->next = mDNSNULL;
1731                    if (!InsertAuthRecord(m, &m->rrauth, dup)) LogMsg("mDNS_Deregister_internal: ERROR!! cannot insert %s", ARDisplayString(m, dup));
1732                }
1733                else
1734                {
1735                    dup->next = rr->next;       // And then...
1736                    rr->next  = dup;            // ... splice it in right after the record we're about to delete
1737                }
1738                dup->resrec.RecordType        = rr->resrec.RecordType;
1739                dup->ProbeCount      = rr->ProbeCount;
1740                dup->ProbeRestartCount = rr->ProbeRestartCount;
1741                dup->AnnounceCount   = rr->AnnounceCount;
1742                dup->RequireGoodbye  = rr->RequireGoodbye;
1743                dup->AnsweredLocalQ  = rr->AnsweredLocalQ;
1744                dup->ImmedAnswer     = rr->ImmedAnswer;
1745                dup->ImmedUnicast    = rr->ImmedUnicast;
1746                dup->ImmedAdditional = rr->ImmedAdditional;
1747                dup->v4Requester     = rr->v4Requester;
1748                dup->v6Requester     = rr->v6Requester;
1749                dup->ThisAPInterval  = rr->ThisAPInterval;
1750                dup->LastAPTime      = rr->LastAPTime;
1751                dup->LastMCTime      = rr->LastMCTime;
1752                dup->LastMCInterface = rr->LastMCInterface;
1753                dup->Private         = rr->Private;
1754                dup->state           = rr->state;
1755                rr->RequireGoodbye = mDNSfalse;
1756                rr->AnsweredLocalQ = mDNSfalse;
1757            }
1758        }
1759    }
1760    else
1761    {
1762        // We didn't find our record on the main list; try the DuplicateRecords list instead.
1763        p = &m->DuplicateRecords;
1764        while (*p && *p != rr) p=&(*p)->next;
1765        // If we found our record on the duplicate list, then make sure we don't send a goodbye for it
1766        if (*p)
1767        {
1768            // Duplicate records are not used for sending wakeups or goodbyes. Hence, deregister them
1769            // immediately. When there is a conflict, we deregister all the conflicting duplicate records
1770            // also that have been marked above in this function. In that case, we come here and if we don't
1771            // deregister (unilink from the DuplicateRecords list), we will be recursing infinitely. Hence,
1772            // clear the HMAC which will cause it to deregister. See <rdar://problem/10380988> for
1773            // details.
1774            rr->WakeUp.HMAC    = zeroEthAddr;
1775            rr->RequireGoodbye = mDNSfalse;
1776            rr->resrec.RecordType = kDNSRecordTypeDeregistering;
1777            dupList = mDNStrue;
1778        }
1779        if (*p) debugf("mDNS_Deregister_internal: Deleting DuplicateRecord %p %##s (%s)",
1780                       rr, rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
1781    }
1782
1783    if (!*p)
1784    {
1785        // No need to log an error message if we already know this is a potentially repeated deregistration
1786        if (drt != mDNS_Dereg_repeat)
1787            LogMsg("mDNS_Deregister_internal: Record %p not found in list %s", rr, ARDisplayString(m,rr));
1788        return(mStatus_BadReferenceErr);
1789    }
1790
1791    // If this is a shared record and we've announced it at least once,
1792    // we need to retract that announcement before we delete the record
1793
1794    // If this is a record (including mDNSInterface_LocalOnly records) for which we've given local-only answers then
1795    // it's tempting to just do "AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNSfalse)" here, but that would not not be safe.
1796    // The AnswerAllLocalQuestionsWithLocalAuthRecord routine walks the question list invoking client callbacks, using the "m->CurrentQuestion"
1797    // mechanism to cope with the client callback modifying the question list while that's happening.
1798    // However, mDNS_Deregister could have been called from a client callback (e.g. from the domain enumeration callback FoundDomain)
1799    // which means that the "m->CurrentQuestion" mechanism is already in use to protect that list, so we can't use it twice.
1800    // More generally, if we invoke callbacks from within a client callback, then those callbacks could deregister other
1801    // records, thereby invoking yet more callbacks, without limit.
1802    // The solution is to defer delivering the "Remove" events until mDNS_Execute time, just like we do for sending
1803    // actual goodbye packets.
1804
1805#ifndef UNICAST_DISABLED
1806    if (AuthRecord_uDNS(rr))
1807    {
1808        if (rr->RequireGoodbye)
1809        {
1810            if (rr->tcp) { DisposeTCPConn(rr->tcp); rr->tcp = mDNSNULL; }
1811            rr->resrec.RecordType    = kDNSRecordTypeDeregistering;
1812            m->LocalRemoveEvents     = mDNStrue;
1813            uDNS_DeregisterRecord(m, rr);
1814            // At this point unconditionally we bail out
1815            // Either uDNS_DeregisterRecord will have completed synchronously, and called CompleteDeregistration,
1816            // which calls us back here with RequireGoodbye set to false, or it will have initiated the deregistration
1817            // process and will complete asynchronously. Either way we don't need to do anything more here.
1818            return(mStatus_NoError);
1819        }
1820        // Sometimes the records don't complete proper deregistration i.e., don't wait for a response
1821        // from the server. In that case, if the records have been part of a group update, clear the
1822        // state here. Some recors e.g., AutoTunnel gets reused without ever being completely initialized
1823        rr->updateid = zeroID;
1824
1825        // We defer cleaning up NAT state only after sending goodbyes. This is important because
1826        // RecordRegistrationGotZoneData guards against creating NAT state if clientContext is non-NULL.
1827        // This happens today when we turn on/off interface where we get multiple network transitions
1828        // and RestartRecordGetZoneData triggers re-registration of the resource records even though
1829        // they may be in Registered state which causes NAT information to be setup multiple times. Defering
1830        // the cleanup here keeps clientContext non-NULL and hence prevents that. Note that cleaning up
1831        // NAT state here takes care of the case where we did not send goodbyes at all.
1832        if (rr->NATinfo.clientContext)
1833        {
1834            mDNS_StopNATOperation_internal(m, &rr->NATinfo);
1835            rr->NATinfo.clientContext = mDNSNULL;
1836        }
1837        if (rr->nta) { CancelGetZoneData(m, rr->nta); rr->nta = mDNSNULL; }
1838        if (rr->tcp) { DisposeTCPConn(rr->tcp);       rr->tcp = mDNSNULL; }
1839    }
1840#endif // UNICAST_DISABLED
1841
1842    if      (RecordType == kDNSRecordTypeUnregistered)
1843        LogMsg("mDNS_Deregister_internal: %s already marked kDNSRecordTypeUnregistered", ARDisplayString(m, rr));
1844    else if (RecordType == kDNSRecordTypeDeregistering)
1845    {
1846        LogMsg("mDNS_Deregister_internal: %s already marked kDNSRecordTypeDeregistering", ARDisplayString(m, rr));
1847        return(mStatus_BadReferenceErr);
1848    }
1849
1850    // <rdar://problem/7457925> Local-only questions don't get remove events for unique records
1851    // We may want to consider changing this code so that we generate local-only question "rmv"
1852    // events (and maybe goodbye packets too) for unique records as well as for shared records
1853    // Note: If we change the logic for this "if" statement, need to ensure that the code in
1854    // CompleteDeregistration() sets the appropriate state variables to gaurantee that "else"
1855    // clause will execute here and the record will be cut from the list.
1856    if (rr->WakeUp.HMAC.l[0] ||
1857        (RecordType == kDNSRecordTypeShared && (rr->RequireGoodbye || rr->AnsweredLocalQ)))
1858    {
1859        verbosedebugf("mDNS_Deregister_internal: Starting deregistration for %s", ARDisplayString(m, rr));
1860        rr->resrec.RecordType    = kDNSRecordTypeDeregistering;
1861        rr->resrec.rroriginalttl = 0;
1862        rr->AnnounceCount        = rr->WakeUp.HMAC.l[0] ? WakeupCount : (drt == mDNS_Dereg_rapid) ? 1 : GoodbyeCount;
1863        rr->ThisAPInterval       = mDNSPlatformOneSecond * 2;
1864        rr->LastAPTime           = m->timenow - rr->ThisAPInterval;
1865        m->LocalRemoveEvents     = mDNStrue;
1866        if (m->NextScheduledResponse - (m->timenow + mDNSPlatformOneSecond/10) >= 0)
1867            m->NextScheduledResponse = (m->timenow + mDNSPlatformOneSecond/10);
1868    }
1869    else
1870    {
1871        if (!dupList && RRLocalOnly(rr))
1872        {
1873            AuthGroup *ag = RemoveAuthRecord(m, &m->rrauth, rr);
1874            if (ag->NewLocalOnlyRecords == rr) ag->NewLocalOnlyRecords = rr->next;
1875        }
1876        else
1877        {
1878            *p = rr->next;                  // Cut this record from the list
1879            if (m->NewLocalRecords == rr) m->NewLocalRecords = rr->next;
1880            DecrementAutoTargetServices(m, rr);
1881        }
1882        // If someone is about to look at this, bump the pointer forward
1883        if (m->CurrentRecord   == rr) m->CurrentRecord   = rr->next;
1884        rr->next = mDNSNULL;
1885
1886        // Should we generate local remove events here?
1887        // i.e. something like:
1888        // if (rr->AnsweredLocalQ) { AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, mDNSfalse); rr->AnsweredLocalQ = mDNSfalse; }
1889
1890        verbosedebugf("mDNS_Deregister_internal: Deleting record for %s", ARDisplayString(m, rr));
1891        rr->resrec.RecordType = kDNSRecordTypeUnregistered;
1892
1893        if ((drt == mDNS_Dereg_conflict || drt == mDNS_Dereg_repeat) && RecordType == kDNSRecordTypeShared)
1894            debugf("mDNS_Deregister_internal: Cannot have a conflict on a shared record! %##s (%s)",
1895                   rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
1896
1897        // If we have an update queued up which never executed, give the client a chance to free that memory
1898        if (rr->NewRData) CompleteRDataUpdate(m, rr);   // Update our rdata, clear the NewRData pointer, and return memory to the client
1899
1900
1901        // CAUTION: MUST NOT do anything more with rr after calling rr->Callback(), because the client's callback function
1902        // is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc.
1903        // In this case the likely client action to the mStatus_MemFree message is to free the memory,
1904        // so any attempt to touch rr after this is likely to lead to a crash.
1905        if (drt != mDNS_Dereg_conflict)
1906        {
1907            mDNS_DropLockBeforeCallback();      // Allow client to legally make mDNS API calls from the callback
1908            LogInfo("mDNS_Deregister_internal: callback with mStatus_MemFree for %s", ARDisplayString(m, rr));
1909            if (rr->RecordCallback)
1910                rr->RecordCallback(m, rr, mStatus_MemFree);         // MUST NOT touch rr after this
1911            mDNS_ReclaimLockAfterCallback();    // Decrement mDNS_reentrancy to block mDNS API calls again
1912        }
1913        else
1914        {
1915            RecordProbeFailure(m, rr);
1916            mDNS_DropLockBeforeCallback();      // Allow client to legally make mDNS API calls from the callback
1917            if (rr->RecordCallback)
1918                rr->RecordCallback(m, rr, mStatus_NameConflict);    // MUST NOT touch rr after this
1919            mDNS_ReclaimLockAfterCallback();    // Decrement mDNS_reentrancy to block mDNS API calls again
1920            // Now that we've finished deregistering rr, check our DuplicateRecords list for any that we marked previously.
1921            // Note that with all the client callbacks going on, by the time we get here all the
1922            // records we marked may have been explicitly deregistered by the client anyway.
1923            r2 = m->DuplicateRecords;
1924            while (r2)
1925            {
1926                if (r2->ProbeCount != 0xFF)
1927                {
1928                    r2 = r2->next;
1929                }
1930                else
1931                {
1932#if APPLE_OSX_mDNSResponder
1933                    // See if this record was also registered with any D2D plugins.
1934                    D2D_stop_advertising_record(r2);
1935#endif
1936                    mDNS_Deregister_internal(m, r2, mDNS_Dereg_conflict);
1937                    // As this is a duplicate record, it will be unlinked from the list
1938                    // immediately
1939                    r2 = m->DuplicateRecords;
1940                }
1941            }
1942        }
1943    }
1944    mDNS_UpdateAllowSleep(m);
1945    return(mStatus_NoError);
1946}
1947
1948// ***************************************************************************
1949#if COMPILER_LIKES_PRAGMA_MARK
1950#pragma mark -
1951#pragma mark - Packet Sending Functions
1952#endif
1953
1954mDNSlocal void AddRecordToResponseList(AuthRecord ***nrpp, AuthRecord *rr, AuthRecord *add)
1955{
1956    if (rr->NextResponse == mDNSNULL && *nrpp != &rr->NextResponse)
1957    {
1958        **nrpp = rr;
1959        // NR_AdditionalTo must point to a record with NR_AnswerTo set (and not NR_AdditionalTo)
1960        // If 'add' does not meet this requirement, then follow its NR_AdditionalTo pointer to a record that does
1961        // The referenced record will definitely be acceptable (by recursive application of this rule)
1962        if (add && add->NR_AdditionalTo) add = add->NR_AdditionalTo;
1963        rr->NR_AdditionalTo = add;
1964        *nrpp = &rr->NextResponse;
1965    }
1966    debugf("AddRecordToResponseList: %##s (%s) already in list", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
1967}
1968
1969mDNSlocal void AddRRSetAdditionalsToResponseList(mDNS *const m, AuthRecord ***nrpp, AuthRecord *rr, AuthRecord *additional, const mDNSInterfaceID InterfaceID)
1970{
1971    AuthRecord *rr2;
1972    if (additional->resrec.RecordType & kDNSRecordTypeUniqueMask)
1973    {
1974        for (rr2 = m->ResourceRecords; rr2; rr2 = rr2->next)
1975        {
1976            if ((rr2->resrec.namehash == additional->resrec.namehash) &&
1977                (rr2->resrec.rrtype   == additional->resrec.rrtype) &&
1978                (rr2 != additional) &&
1979                (rr2->resrec.RecordType & kDNSRecordTypeUniqueMask) &&
1980                (rr2->resrec.rrclass  == additional->resrec.rrclass) &&
1981                ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) &&
1982                SameDomainName(rr2->resrec.name, additional->resrec.name))
1983            {
1984                AddRecordToResponseList(nrpp, rr2, rr);
1985            }
1986        }
1987    }
1988}
1989
1990mDNSlocal void AddAdditionalsToResponseList(mDNS *const m, AuthRecord *ResponseRecords, AuthRecord ***nrpp, const mDNSInterfaceID InterfaceID)
1991{
1992    AuthRecord  *rr, *rr2;
1993    for (rr=ResponseRecords; rr; rr=rr->NextResponse)           // For each record we plan to put
1994    {
1995        // (Note: This is an "if", not a "while". If we add a record, we'll find it again
1996        // later in the "for" loop, and we will follow further "additional" links then.)
1997        if (rr->Additional1 && ResourceRecordIsValidInterfaceAnswer(rr->Additional1, InterfaceID))
1998        {
1999            AddRecordToResponseList(nrpp, rr->Additional1, rr);
2000            AddRRSetAdditionalsToResponseList(m, nrpp, rr, rr->Additional1, InterfaceID);
2001        }
2002
2003        if (rr->Additional2 && ResourceRecordIsValidInterfaceAnswer(rr->Additional2, InterfaceID))
2004        {
2005            AddRecordToResponseList(nrpp, rr->Additional2, rr);
2006            AddRRSetAdditionalsToResponseList(m, nrpp, rr, rr->Additional2, InterfaceID);
2007        }
2008
2009        // For SRV records, automatically add the Address record(s) for the target host
2010        if (rr->resrec.rrtype == kDNSType_SRV)
2011        {
2012            for (rr2=m->ResourceRecords; rr2; rr2=rr2->next)                    // Scan list of resource records
2013                if (RRTypeIsAddressType(rr2->resrec.rrtype) &&                  // For all address records (A/AAAA) ...
2014                    ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) &&   // ... which are valid for answer ...
2015                    rr->resrec.rdatahash == rr2->resrec.namehash &&         // ... whose name is the name of the SRV target
2016                    SameDomainName(&rr->resrec.rdata->u.srv.target, rr2->resrec.name))
2017                    AddRecordToResponseList(nrpp, rr2, rr);
2018        }
2019        else if (RRTypeIsAddressType(rr->resrec.rrtype))    // For A or AAAA, put counterpart as additional
2020        {
2021            for (rr2=m->ResourceRecords; rr2; rr2=rr2->next)                    // Scan list of resource records
2022                if (RRTypeIsAddressType(rr2->resrec.rrtype) &&                  // For all address records (A/AAAA) ...
2023                    ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) &&   // ... which are valid for answer ...
2024                    rr->resrec.namehash == rr2->resrec.namehash &&              // ... and have the same name
2025                    SameDomainName(rr->resrec.name, rr2->resrec.name))
2026                    AddRecordToResponseList(nrpp, rr2, rr);
2027        }
2028        else if (rr->resrec.rrtype == kDNSType_PTR)         // For service PTR, see if we want to add DeviceInfo record
2029        {
2030            if (ResourceRecordIsValidInterfaceAnswer(&m->DeviceInfo, InterfaceID) &&
2031                SameDomainLabel(rr->resrec.rdata->u.name.c, m->DeviceInfo.resrec.name->c))
2032                AddRecordToResponseList(nrpp, &m->DeviceInfo, rr);
2033        }
2034    }
2035}
2036
2037mDNSlocal int AnonInfoSpace(AnonymousInfo *info)
2038{
2039    ResourceRecord *rr = info->nsec3RR;
2040
2041    // 2 bytes for compressed name + type (2) class (2) TTL (4) rdlength (2) rdata (n)
2042    return (2 + 10 + rr->rdlength);
2043}
2044
2045mDNSlocal void SendDelayedUnicastResponse(mDNS *const m, const mDNSAddr *const dest, const mDNSInterfaceID InterfaceID)
2046{
2047    AuthRecord *rr;
2048    AuthRecord  *ResponseRecords = mDNSNULL;
2049    AuthRecord **nrp             = &ResponseRecords;
2050    NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID);
2051    int AnoninfoSpace = 0;
2052
2053    // Make a list of all our records that need to be unicast to this destination
2054    for (rr = m->ResourceRecords; rr; rr=rr->next)
2055    {
2056        // If we find we can no longer unicast this answer, clear ImmedUnicast
2057        if (rr->ImmedAnswer == mDNSInterfaceMark               ||
2058            mDNSSameIPv4Address(rr->v4Requester, onesIPv4Addr) ||
2059            mDNSSameIPv6Address(rr->v6Requester, onesIPv6Addr)  )
2060            rr->ImmedUnicast = mDNSfalse;
2061
2062        if (rr->ImmedUnicast && rr->ImmedAnswer == InterfaceID)
2063        {
2064            if ((dest->type == mDNSAddrType_IPv4 && mDNSSameIPv4Address(rr->v4Requester, dest->ip.v4)) ||
2065                (dest->type == mDNSAddrType_IPv6 && mDNSSameIPv6Address(rr->v6Requester, dest->ip.v6)))
2066            {
2067                rr->ImmedAnswer  = mDNSNULL;                // Clear the state fields
2068                rr->ImmedUnicast = mDNSfalse;
2069                rr->v4Requester  = zerov4Addr;
2070                rr->v6Requester  = zerov6Addr;
2071
2072                // Only sent records registered for P2P over P2P interfaces
2073                if (intf && !mDNSPlatformValidRecordForInterface(rr, intf->InterfaceID))
2074                {
2075                    continue;
2076                }
2077
2078                if (rr->NextResponse == mDNSNULL && nrp != &rr->NextResponse)   // rr->NR_AnswerTo
2079                {
2080                    rr->NR_AnswerTo = NR_AnswerMulticast;
2081                    *nrp = rr;
2082                    nrp = &rr->NextResponse;
2083                }
2084            }
2085        }
2086    }
2087
2088    AddAdditionalsToResponseList(m, ResponseRecords, &nrp, InterfaceID);
2089
2090    while (ResponseRecords)
2091    {
2092        mDNSu8 *responseptr = m->omsg.data;
2093        mDNSu8 *newptr;
2094        InitializeDNSMessage(&m->omsg.h, zeroID, ResponseFlags);
2095
2096        // Put answers in the packet
2097        while (ResponseRecords && ResponseRecords->NR_AnswerTo)
2098        {
2099            rr = ResponseRecords;
2100            if (rr->resrec.AnonInfo)
2101            {
2102                AnoninfoSpace += AnonInfoSpace(rr->resrec.AnonInfo);
2103                rr->resrec.AnonInfo->SendNow = mDNSInterfaceMark;
2104            }
2105            if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
2106                rr->resrec.rrclass |= kDNSClass_UniqueRRSet;        // Temporarily set the cache flush bit so PutResourceRecord will set it
2107
2108            // Retract the limit by AnoninfoSpace which we need to put the AnoInfo option.
2109            newptr = PutResourceRecordTTLWithLimit(&m->omsg, responseptr, &m->omsg.h.numAnswers, &rr->resrec, rr->resrec.rroriginalttl,
2110                 m->omsg.data + (AllowedRRSpace(&m->omsg) - AnoninfoSpace));
2111
2112            rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;           // Make sure to clear cache flush bit back to normal state
2113            if (!newptr && m->omsg.h.numAnswers)
2114            {
2115                break; // If packet full, send it now
2116            }
2117            if (newptr) responseptr = newptr;
2118            ResponseRecords = rr->NextResponse;
2119            rr->NextResponse    = mDNSNULL;
2120            rr->NR_AnswerTo     = mDNSNULL;
2121            rr->NR_AdditionalTo = mDNSNULL;
2122            rr->RequireGoodbye  = mDNStrue;
2123        }
2124
2125        // We have reserved the space for AnonInfo option. PutResourceRecord uses the
2126        // standard limit (AllowedRRSpace) and we should have space now.
2127        for (rr = m->ResourceRecords; rr; rr=rr->next)
2128        {
2129            if (rr->resrec.AnonInfo && rr->resrec.AnonInfo->SendNow == mDNSInterfaceMark)
2130            {
2131                ResourceRecord *nsec3RR = rr->resrec.AnonInfo->nsec3RR;
2132
2133                newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAuthorities, nsec3RR);
2134                if (newptr)
2135                {
2136                    responseptr = newptr;
2137                    debugf("SendDelayedUnicastResponse: Added NSEC3 Record %s on %p", RRDisplayString(m, nsec3RR), intf->InterfaceID);
2138                }
2139                else
2140                {
2141                    // We allocated space and we should not fail. Don't break, we need to clear the SendNow flag.
2142                    LogMsg("SendDelayedUnicastResponse: ERROR!! Cannot Add NSEC3 Record %s on %p", RRDisplayString(m, nsec3RR), intf->InterfaceID);
2143                }
2144                rr->resrec.AnonInfo->SendNow = mDNSNULL;
2145            }
2146        }
2147
2148        // Add additionals, if there's space
2149        while (ResponseRecords && !ResponseRecords->NR_AnswerTo)
2150        {
2151            rr = ResponseRecords;
2152            if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
2153                rr->resrec.rrclass |= kDNSClass_UniqueRRSet;        // Temporarily set the cache flush bit so PutResourceRecord will set it
2154            newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAdditionals, &rr->resrec);
2155            rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;           // Make sure to clear cache flush bit back to normal state
2156
2157            if (newptr) responseptr = newptr;
2158            if (newptr && m->omsg.h.numAnswers) rr->RequireGoodbye = mDNStrue;
2159            else if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask) rr->ImmedAnswer = mDNSInterfaceMark;
2160            ResponseRecords = rr->NextResponse;
2161            rr->NextResponse    = mDNSNULL;
2162            rr->NR_AnswerTo     = mDNSNULL;
2163            rr->NR_AdditionalTo = mDNSNULL;
2164        }
2165
2166        if (m->omsg.h.numAnswers)
2167            mDNSSendDNSMessage(m, &m->omsg, responseptr, InterfaceID, mDNSNULL, dest, MulticastDNSPort, mDNSNULL, mDNSNULL, mDNSfalse);
2168    }
2169}
2170
2171// CompleteDeregistration guarantees that on exit the record will have been cut from the m->ResourceRecords list
2172// and the client's mStatus_MemFree callback will have been invoked
2173mDNSexport void CompleteDeregistration(mDNS *const m, AuthRecord *rr)
2174{
2175    LogInfo("CompleteDeregistration: called for Resource record %s", ARDisplayString(m, rr));
2176    // Clearing rr->RequireGoodbye signals mDNS_Deregister_internal() that
2177    // it should go ahead and immediately dispose of this registration
2178    rr->resrec.RecordType = kDNSRecordTypeShared;
2179    rr->RequireGoodbye    = mDNSfalse;
2180    rr->WakeUp.HMAC       = zeroEthAddr;
2181    if (rr->AnsweredLocalQ) { AnswerAllLocalQuestionsWithLocalAuthRecord(m, rr, QC_rmv); rr->AnsweredLocalQ = mDNSfalse; }
2182    mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);     // Don't touch rr after this
2183}
2184
2185// DiscardDeregistrations is used on shutdown and sleep to discard (forcibly and immediately)
2186// any deregistering records that remain in the m->ResourceRecords list.
2187// DiscardDeregistrations calls mDNS_Deregister_internal which can call a user callback,
2188// which may change the record list and/or question list.
2189// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
2190mDNSlocal void DiscardDeregistrations(mDNS *const m)
2191{
2192    if (m->CurrentRecord)
2193        LogMsg("DiscardDeregistrations ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
2194    m->CurrentRecord = m->ResourceRecords;
2195
2196    while (m->CurrentRecord)
2197    {
2198        AuthRecord *rr = m->CurrentRecord;
2199        if (!AuthRecord_uDNS(rr) && rr->resrec.RecordType == kDNSRecordTypeDeregistering)
2200            CompleteDeregistration(m, rr);      // Don't touch rr after this
2201        else
2202            m->CurrentRecord = rr->next;
2203    }
2204}
2205
2206mDNSlocal mStatus GetLabelDecimalValue(const mDNSu8 *const src, mDNSu8 *dst)
2207{
2208    int i, val = 0;
2209    if (src[0] < 1 || src[0] > 3) return(mStatus_Invalid);
2210    for (i=1; i<=src[0]; i++)
2211    {
2212        if (src[i] < '0' || src[i] > '9') return(mStatus_Invalid);
2213        val = val * 10 + src[i] - '0';
2214    }
2215    if (val > 255) return(mStatus_Invalid);
2216    *dst = (mDNSu8)val;
2217    return(mStatus_NoError);
2218}
2219
2220mDNSlocal mStatus GetIPv4FromName(mDNSAddr *const a, const domainname *const name)
2221{
2222    int skip = CountLabels(name) - 6;
2223    if (skip < 0) { LogMsg("GetIPFromName: Need six labels in IPv4 reverse mapping name %##s", name); return mStatus_Invalid; }
2224    if (GetLabelDecimalValue(SkipLeadingLabels(name, skip+3)->c, &a->ip.v4.b[0]) ||
2225        GetLabelDecimalValue(SkipLeadingLabels(name, skip+2)->c, &a->ip.v4.b[1]) ||
2226        GetLabelDecimalValue(SkipLeadingLabels(name, skip+1)->c, &a->ip.v4.b[2]) ||
2227        GetLabelDecimalValue(SkipLeadingLabels(name, skip+0)->c, &a->ip.v4.b[3])) return mStatus_Invalid;
2228    a->type = mDNSAddrType_IPv4;
2229    return(mStatus_NoError);
2230}
2231
2232#define HexVal(X) ( ((X) >= '0' && (X) <= '9') ? ((X) - '0'     ) :   \
2233                    ((X) >= 'A' && (X) <= 'F') ? ((X) - 'A' + 10) :   \
2234                    ((X) >= 'a' && (X) <= 'f') ? ((X) - 'a' + 10) : -1)
2235
2236mDNSlocal mStatus GetIPv6FromName(mDNSAddr *const a, const domainname *const name)
2237{
2238    int i, h, l;
2239    const domainname *n;
2240
2241    int skip = CountLabels(name) - 34;
2242    if (skip < 0) { LogMsg("GetIPFromName: Need 34 labels in IPv6 reverse mapping name %##s", name); return mStatus_Invalid; }
2243
2244    n = SkipLeadingLabels(name, skip);
2245    for (i=0; i<16; i++)
2246    {
2247        if (n->c[0] != 1) return mStatus_Invalid;
2248        l = HexVal(n->c[1]);
2249        n = (const domainname *)(n->c + 2);
2250
2251        if (n->c[0] != 1) return mStatus_Invalid;
2252        h = HexVal(n->c[1]);
2253        n = (const domainname *)(n->c + 2);
2254
2255        if (l<0 || h<0) return mStatus_Invalid;
2256        a->ip.v6.b[15-i] = (mDNSu8)((h << 4) | l);
2257    }
2258
2259    a->type = mDNSAddrType_IPv6;
2260    return(mStatus_NoError);
2261}
2262
2263mDNSlocal mDNSs32 ReverseMapDomainType(const domainname *const name)
2264{
2265    int skip = CountLabels(name) - 2;
2266    if (skip >= 0)
2267    {
2268        const domainname *suffix = SkipLeadingLabels(name, skip);
2269        if (SameDomainName(suffix, (const domainname*)"\x7" "in-addr" "\x4" "arpa")) return mDNSAddrType_IPv4;
2270        if (SameDomainName(suffix, (const domainname*)"\x3" "ip6"     "\x4" "arpa")) return mDNSAddrType_IPv6;
2271    }
2272    return(mDNSAddrType_None);
2273}
2274
2275mDNSlocal void SendARP(mDNS *const m, const mDNSu8 op, const AuthRecord *const rr,
2276                       const mDNSv4Addr *const spa, const mDNSEthAddr *const tha, const mDNSv4Addr *const tpa, const mDNSEthAddr *const dst)
2277{
2278    int i;
2279    mDNSu8 *ptr = m->omsg.data;
2280    NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID);
2281    if (!intf) { LogMsg("SendARP: No interface with InterfaceID %p found %s", rr->resrec.InterfaceID, ARDisplayString(m,rr)); return; }
2282
2283    // 0x00 Destination address
2284    for (i=0; i<6; i++) *ptr++ = dst->b[i];
2285
2286    // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option, BPF will fill in the real interface address for us)
2287    for (i=0; i<6; i++) *ptr++ = intf->MAC.b[0];
2288
2289    // 0x0C ARP Ethertype (0x0806)
2290    *ptr++ = 0x08; *ptr++ = 0x06;
2291
2292    // 0x0E ARP header
2293    *ptr++ = 0x00; *ptr++ = 0x01;   // Hardware address space; Ethernet = 1
2294    *ptr++ = 0x08; *ptr++ = 0x00;   // Protocol address space; IP = 0x0800
2295    *ptr++ = 6;                     // Hardware address length
2296    *ptr++ = 4;                     // Protocol address length
2297    *ptr++ = 0x00; *ptr++ = op;     // opcode; Request = 1, Response = 2
2298
2299    // 0x16 Sender hardware address (our MAC address)
2300    for (i=0; i<6; i++) *ptr++ = intf->MAC.b[i];
2301
2302    // 0x1C Sender protocol address
2303    for (i=0; i<4; i++) *ptr++ = spa->b[i];
2304
2305    // 0x20 Target hardware address
2306    for (i=0; i<6; i++) *ptr++ = tha->b[i];
2307
2308    // 0x26 Target protocol address
2309    for (i=0; i<4; i++) *ptr++ = tpa->b[i];
2310
2311    // 0x2A Total ARP Packet length 42 bytes
2312    mDNSPlatformSendRawPacket(m->omsg.data, ptr, rr->resrec.InterfaceID);
2313}
2314
2315mDNSlocal mDNSu16 CheckSum(const void *const data, mDNSs32 length, mDNSu32 sum)
2316{
2317    const mDNSu16 *ptr = data;
2318    while (length > 0) { length -= 2; sum += *ptr++; }
2319    sum = (sum & 0xFFFF) + (sum >> 16);
2320    sum = (sum & 0xFFFF) + (sum >> 16);
2321    return(sum != 0xFFFF ? sum : 0);
2322}
2323
2324mDNSlocal mDNSu16 IPv6CheckSum(const mDNSv6Addr *const src, const mDNSv6Addr *const dst, const mDNSu8 protocol, const void *const data, const mDNSu32 length)
2325{
2326    IPv6PseudoHeader ph;
2327    ph.src = *src;
2328    ph.dst = *dst;
2329    ph.len.b[0] = length >> 24;
2330    ph.len.b[1] = length >> 16;
2331    ph.len.b[2] = length >> 8;
2332    ph.len.b[3] = length;
2333    ph.pro.b[0] = 0;
2334    ph.pro.b[1] = 0;
2335    ph.pro.b[2] = 0;
2336    ph.pro.b[3] = protocol;
2337    return CheckSum(&ph, sizeof(ph), CheckSum(data, length, 0));
2338}
2339
2340mDNSlocal void SendNDP(mDNS *const m, const mDNSu8 op, const mDNSu8 flags, const AuthRecord *const rr,
2341                       const mDNSv6Addr *const spa, const mDNSEthAddr *const tha, const mDNSv6Addr *const tpa, const mDNSEthAddr *const dst)
2342{
2343    int i;
2344    mDNSOpaque16 checksum;
2345    mDNSu8 *ptr = m->omsg.data;
2346    // Some recipient hosts seem to ignore Neighbor Solicitations if the IPv6-layer destination address is not the
2347    // appropriate IPv6 solicited node multicast address, so we use that IPv6-layer destination address, even though
2348    // at the Ethernet-layer we unicast the packet to the intended target, to avoid wasting network bandwidth.
2349    const mDNSv6Addr mc = { { 0xFF,0x02,0x00,0x00, 0,0,0,0, 0,0,0,1, 0xFF,tpa->b[0xD],tpa->b[0xE],tpa->b[0xF] } };
2350    const mDNSv6Addr *const v6dst = (op == NDP_Sol) ? &mc : tpa;
2351    NetworkInterfaceInfo *intf = FirstInterfaceForID(m, rr->resrec.InterfaceID);
2352    if (!intf) { LogMsg("SendNDP: No interface with InterfaceID %p found %s", rr->resrec.InterfaceID, ARDisplayString(m,rr)); return; }
2353
2354    // 0x00 Destination address
2355    for (i=0; i<6; i++) *ptr++ = dst->b[i];
2356    // Right now we only send Neighbor Solicitations to verify whether the host we're proxying for has gone to sleep yet.
2357    // Since we know who we're looking for, we send it via Ethernet-layer unicast, rather than bothering every host on the
2358    // link with a pointless link-layer multicast.
2359    // Should we want to send traditional Neighbor Solicitations in the future, where we really don't know in advance what
2360    // Ethernet-layer address we're looking for, we'll need to send to the appropriate Ethernet-layer multicast address:
2361    // *ptr++ = 0x33;
2362    // *ptr++ = 0x33;
2363    // *ptr++ = 0xFF;
2364    // *ptr++ = tpa->b[0xD];
2365    // *ptr++ = tpa->b[0xE];
2366    // *ptr++ = tpa->b[0xF];
2367
2368    // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option, BPF will fill in the real interface address for us)
2369    for (i=0; i<6; i++)
2370	if (tha)
2371	    *ptr++ = tha->b[i];
2372	else
2373	    *ptr++ = intf->MAC.b[i];
2374
2375    // 0x0C IPv6 Ethertype (0x86DD)
2376    *ptr++ = 0x86; *ptr++ = 0xDD;
2377
2378    // 0x0E IPv6 header
2379    *ptr++ = 0x60; *ptr++ = 0x00; *ptr++ = 0x00; *ptr++ = 0x00;     // Version, Traffic Class, Flow Label
2380    *ptr++ = 0x00; *ptr++ = 0x20;                                   // Length
2381    *ptr++ = 0x3A;                                                  // Protocol == ICMPv6
2382    *ptr++ = 0xFF;                                                  // Hop Limit
2383
2384    // 0x16 Sender IPv6 address
2385    for (i=0; i<16; i++) *ptr++ = spa->b[i];
2386
2387    // 0x26 Destination IPv6 address
2388    for (i=0; i<16; i++) *ptr++ = v6dst->b[i];
2389
2390    // 0x36 NDP header
2391    *ptr++ = op;                    // 0x87 == Neighbor Solicitation, 0x88 == Neighbor Advertisement
2392    *ptr++ = 0x00;                  // Code
2393    *ptr++ = 0x00; *ptr++ = 0x00;   // Checksum placeholder (0x38, 0x39)
2394    *ptr++ = flags;
2395    *ptr++ = 0x00; *ptr++ = 0x00; *ptr++ = 0x00;
2396
2397    if (op == NDP_Sol)  // Neighbor Solicitation. The NDP "target" is the address we seek.
2398    {
2399        // 0x3E NDP target.
2400        for (i=0; i<16; i++) *ptr++ = tpa->b[i];
2401        // 0x4E Source Link-layer Address
2402        // <http://www.ietf.org/rfc/rfc2461.txt>
2403        // MUST NOT be included when the source IP address is the unspecified address.
2404        // Otherwise, on link layers that have addresses this option MUST be included
2405        // in multicast solicitations and SHOULD be included in unicast solicitations.
2406        if (!mDNSIPv6AddressIsZero(*spa))
2407        {
2408            *ptr++ = NDP_SrcLL; // Option Type 1 == Source Link-layer Address
2409            *ptr++ = 0x01;      // Option length 1 (in units of 8 octets)
2410            for (i=0; i<6; i++)
2411		if (tha)
2412		    *ptr++ = tha->b[i];
2413		else
2414		    *ptr++ = intf->MAC.b[i];
2415        }
2416    }
2417    else            // Neighbor Advertisement. The NDP "target" is the address we're giving information about.
2418    {
2419        // 0x3E NDP target.
2420        for (i=0; i<16; i++) *ptr++ = spa->b[i];
2421        // 0x4E Target Link-layer Address
2422        *ptr++ = NDP_TgtLL; // Option Type 2 == Target Link-layer Address
2423        *ptr++ = 0x01;      // Option length 1 (in units of 8 octets)
2424        for (i=0; i<6; i++)
2425	    if (tha)
2426		*ptr++ = tha->b[i];
2427	    else
2428		*ptr++ = intf->MAC.b[i];
2429    }
2430
2431    // 0x4E or 0x56 Total NDP Packet length 78 or 86 bytes
2432    m->omsg.data[0x13] = ptr - &m->omsg.data[0x36];     // Compute actual length
2433    checksum.NotAnInteger = ~IPv6CheckSum(spa, v6dst, 0x3A, &m->omsg.data[0x36], m->omsg.data[0x13]);
2434    m->omsg.data[0x38] = checksum.b[0];
2435    m->omsg.data[0x39] = checksum.b[1];
2436
2437    mDNSPlatformSendRawPacket(m->omsg.data, ptr, rr->resrec.InterfaceID);
2438}
2439
2440mDNSlocal void SetupTracerOpt(const mDNS *const m, rdataOPT *const Trace)
2441{
2442    mDNSu32 DNS_VERS = _DNS_SD_H;
2443    Trace->u.tracer.platf    = m->mDNS_plat;
2444    Trace->u.tracer.mDNSv    = DNS_VERS;
2445
2446    Trace->opt              = kDNSOpt_Trace;
2447    Trace->optlen           = DNSOpt_TraceData_Space - 4;
2448}
2449
2450mDNSlocal void SetupOwnerOpt(const mDNS *const m, const NetworkInterfaceInfo *const intf, rdataOPT *const owner)
2451{
2452    owner->u.owner.vers     = 0;
2453    owner->u.owner.seq      = m->SleepSeqNum;
2454    owner->u.owner.HMAC     = m->PrimaryMAC;
2455    owner->u.owner.IMAC     = intf->MAC;
2456    owner->u.owner.password = zeroEthAddr;
2457
2458    // Don't try to compute the optlen until *after* we've set up the data fields
2459    // 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
2460    owner->opt              = kDNSOpt_Owner;
2461    owner->optlen           = DNSOpt_Owner_Space(&m->PrimaryMAC, &intf->MAC) - 4;
2462}
2463
2464mDNSlocal void GrantUpdateCredit(AuthRecord *rr)
2465{
2466    if (++rr->UpdateCredits >= kMaxUpdateCredits) rr->NextUpdateCredit = 0;
2467    else rr->NextUpdateCredit = NonZeroTime(rr->NextUpdateCredit + kUpdateCreditRefreshInterval);
2468}
2469
2470mDNSlocal mDNSBool ShouldSendGoodbyesBeforeSleep(mDNS *const m, const NetworkInterfaceInfo *intf, AuthRecord *rr)
2471{
2472    // If there are no sleep proxies, we set the state to SleepState_Sleeping explicitly
2473    // and hence there is no need to check for Transfering state. But if we have sleep
2474    // proxies and partially sending goodbyes for some records, we will be in Transfering
2475    // state and hence need to make sure that we send goodbyes in that case too. Checking whether
2476    // we are not awake handles both cases.
2477    if ((rr->AuthFlags & AuthFlagsWakeOnly) && (m->SleepState != SleepState_Awake))
2478    {
2479        debugf("ShouldSendGoodbyesBeforeSleep: marking for goodbye", ARDisplayString(m, rr));
2480        return mDNStrue;
2481    }
2482
2483    if (m->SleepState != SleepState_Sleeping)
2484        return mDNSfalse;
2485
2486    // If we are going to sleep and in SleepState_Sleeping, SendGoodbyes on the interface tell you
2487    // whether you can send goodbyes or not.
2488    if (!intf->SendGoodbyes)
2489    {
2490        debugf("ShouldSendGoodbyesBeforeSleep: not sending goodbye %s, int %p", ARDisplayString(m, rr), intf->InterfaceID);
2491        return mDNSfalse;
2492    }
2493    else
2494    {
2495        debugf("ShouldSendGoodbyesBeforeSleep: sending goodbye %s, int %p", ARDisplayString(m, rr), intf->InterfaceID);
2496        return mDNStrue;
2497    }
2498}
2499
2500mDNSlocal mDNSBool IsInterfaceValidForAuthRecord(const AuthRecord *ar, mDNSInterfaceID InterfaceID)
2501{
2502    mDNSBool result;
2503
2504    if (ar->resrec.InterfaceID == mDNSInterface_Any)
2505    {
2506        result = mDNSPlatformValidRecordForInterface(ar, InterfaceID);
2507    }
2508    else
2509    {
2510        result = (ar->resrec.InterfaceID == InterfaceID);
2511    }
2512
2513    return(result);
2514}
2515
2516// Note about acceleration of announcements to facilitate automatic coalescing of
2517// multiple independent threads of announcements into a single synchronized thread:
2518// The announcements in the packet may be at different stages of maturity;
2519// One-second interval, two-second interval, four-second interval, and so on.
2520// After we've put in all the announcements that are due, we then consider
2521// whether there are other nearly-due announcements that are worth accelerating.
2522// To be eligible for acceleration, a record MUST NOT be older (further along
2523// its timeline) than the most mature record we've already put in the packet.
2524// In other words, younger records can have their timelines accelerated to catch up
2525// with their elder bretheren; this narrows the age gap and helps them eventually get in sync.
2526// Older records cannot have their timelines accelerated; this would just widen
2527// the gap between them and their younger bretheren and get them even more out of sync.
2528
2529// Note: SendResponses calls mDNS_Deregister_internal which can call a user callback, which may change
2530// the record list and/or question list.
2531// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
2532mDNSlocal void SendResponses(mDNS *const m)
2533{
2534    int pktcount = 0;
2535    AuthRecord *rr, *r2;
2536    mDNSs32 maxExistingAnnounceInterval = 0;
2537    const NetworkInterfaceInfo *intf = GetFirstActiveInterface(m->HostInterfaces);
2538
2539    m->NextScheduledResponse = m->timenow + FutureTime;
2540
2541    if (m->SleepState == SleepState_Transferring) RetrySPSRegistrations(m);
2542
2543    for (rr = m->ResourceRecords; rr; rr=rr->next)
2544        if (rr->ImmedUnicast)
2545        {
2546            mDNSAddr v4 = { mDNSAddrType_IPv4, {{{0}}} };
2547            mDNSAddr v6 = { mDNSAddrType_IPv6, {{{0}}} };
2548            v4.ip.v4 = rr->v4Requester;
2549            v6.ip.v6 = rr->v6Requester;
2550            if (!mDNSIPv4AddressIsZero(rr->v4Requester)) SendDelayedUnicastResponse(m, &v4, rr->ImmedAnswer);
2551            if (!mDNSIPv6AddressIsZero(rr->v6Requester)) SendDelayedUnicastResponse(m, &v6, rr->ImmedAnswer);
2552            if (rr->ImmedUnicast)
2553            {
2554                LogMsg("SendResponses: ERROR: rr->ImmedUnicast still set: %s", ARDisplayString(m, rr));
2555                rr->ImmedUnicast = mDNSfalse;
2556            }
2557        }
2558
2559    // ***
2560    // *** 1. Setup: Set the SendRNow and ImmedAnswer fields to indicate which interface(s) the records need to be sent on
2561    // ***
2562
2563    // Run through our list of records, and decide which ones we're going to announce on all interfaces
2564    for (rr = m->ResourceRecords; rr; rr=rr->next)
2565    {
2566        while (rr->NextUpdateCredit && m->timenow - rr->NextUpdateCredit >= 0) GrantUpdateCredit(rr);
2567        if (TimeToAnnounceThisRecord(rr, m->timenow))
2568        {
2569            if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
2570            {
2571                if (!rr->WakeUp.HMAC.l[0])
2572                {
2573                    if (rr->AnnounceCount) rr->ImmedAnswer = mDNSInterfaceMark;     // Send goodbye packet on all interfaces
2574                }
2575                else
2576                {
2577                    mDNSBool unicastOnly;
2578                    LogSPS("SendResponses: Sending wakeup %2d for %.6a %s", rr->AnnounceCount-3, &rr->WakeUp.IMAC, ARDisplayString(m, rr));
2579                    unicastOnly = ((rr->AnnounceCount == WakeupCount) || (rr->AnnounceCount == WakeupCount - 1)) ? mDNStrue : mDNSfalse;
2580                    SendWakeup(m, rr->resrec.InterfaceID, &rr->WakeUp.IMAC, &rr->WakeUp.password, unicastOnly);
2581                    for (r2 = rr; r2; r2=r2->next)
2582                        if ((r2->resrec.RecordType == kDNSRecordTypeDeregistering) && r2->AnnounceCount && (r2->resrec.InterfaceID == rr->resrec.InterfaceID) &&
2583                            mDNSSameEthAddress(&r2->WakeUp.IMAC, &rr->WakeUp.IMAC) && !mDNSSameEthAddress(&zeroEthAddr, &r2->WakeUp.HMAC))
2584                        {
2585                            // For now we only want to send a single Unsolicited Neighbor Advertisement restoring the address to the original
2586                            // owner, because these packets can cause some IPv6 stacks to falsely conclude that there's an address conflict.
2587                            if (r2->AddressProxy.type == mDNSAddrType_IPv6 && r2->AnnounceCount == WakeupCount)
2588                            {
2589                                LogSPS("NDP Announcement %2d Releasing traffic for H-MAC %.6a I-MAC %.6a %s",
2590                                       r2->AnnounceCount-3, &r2->WakeUp.HMAC, &r2->WakeUp.IMAC, ARDisplayString(m,r2));
2591                                SendNDP(m, NDP_Adv, NDP_Override, r2, &r2->AddressProxy.ip.v6, &r2->WakeUp.IMAC, &AllHosts_v6, &AllHosts_v6_Eth);
2592                            }
2593                            r2->LastAPTime = m->timenow;
2594                            // After 15 wakeups without success (maybe host has left the network) send three goodbyes instead
2595                            if (--r2->AnnounceCount <= GoodbyeCount) r2->WakeUp.HMAC = zeroEthAddr;
2596                        }
2597                }
2598            }
2599            else if (ResourceRecordIsValidAnswer(rr))
2600            {
2601                if (rr->AddressProxy.type)
2602                {
2603                    if (!mDNSSameEthAddress(&zeroEthAddr, &rr->WakeUp.HMAC))
2604                    {
2605                        rr->AnnounceCount--;
2606                        rr->ThisAPInterval *= 2;
2607                        rr->LastAPTime = m->timenow;
2608                        if (rr->AddressProxy.type == mDNSAddrType_IPv4)
2609                        {
2610                            LogSPS("ARP Announcement %2d Capturing traffic for H-MAC %.6a I-MAC %.6a %s",
2611                                    rr->AnnounceCount, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m,rr));
2612                            SendARP(m, 1, rr, &rr->AddressProxy.ip.v4, &zeroEthAddr, &rr->AddressProxy.ip.v4, &onesEthAddr);
2613                        }
2614                        else if (rr->AddressProxy.type == mDNSAddrType_IPv6)
2615                        {
2616                            LogSPS("NDP Announcement %2d Capturing traffic for H-MAC %.6a I-MAC %.6a %s",
2617                                    rr->AnnounceCount, &rr->WakeUp.HMAC, &rr->WakeUp.IMAC, ARDisplayString(m,rr));
2618                            SendNDP(m, NDP_Adv, NDP_Override, rr, &rr->AddressProxy.ip.v6, mDNSNULL, &AllHosts_v6, &AllHosts_v6_Eth);
2619                        }
2620                    }
2621                }
2622                else
2623                {
2624                    rr->ImmedAnswer = mDNSInterfaceMark;        // Send on all interfaces
2625                    if (maxExistingAnnounceInterval < rr->ThisAPInterval)
2626                        maxExistingAnnounceInterval = rr->ThisAPInterval;
2627                    if (rr->UpdateBlocked) rr->UpdateBlocked = 0;
2628                }
2629            }
2630        }
2631    }
2632
2633    // Any interface-specific records we're going to send are marked as being sent on all appropriate interfaces (which is just one)
2634    // Eligible records that are more than half-way to their announcement time are accelerated
2635    for (rr = m->ResourceRecords; rr; rr=rr->next)
2636        if ((rr->resrec.InterfaceID && rr->ImmedAnswer) ||
2637            (rr->ThisAPInterval <= maxExistingAnnounceInterval &&
2638             TimeToAnnounceThisRecord(rr, m->timenow + rr->ThisAPInterval/2) &&
2639             !rr->AddressProxy.type &&                  // Don't include ARP Annoucements when considering which records to accelerate
2640             ResourceRecordIsValidAnswer(rr)))
2641            rr->ImmedAnswer = mDNSInterfaceMark;        // Send on all interfaces
2642
2643    // When sending SRV records (particularly when announcing a new service) automatically add related Address record(s) as additionals
2644    // Note: Currently all address records are interface-specific, so it's safe to set ImmedAdditional to their InterfaceID,
2645    // which will be non-null. If by some chance there is an address record that's not interface-specific (should never happen)
2646    // then all that means is that it won't get sent -- which would not be the end of the world.
2647    for (rr = m->ResourceRecords; rr; rr=rr->next)
2648    {
2649        if (rr->ImmedAnswer && rr->resrec.rrtype == kDNSType_SRV)
2650            for (r2=m->ResourceRecords; r2; r2=r2->next)                // Scan list of resource records
2651                if (RRTypeIsAddressType(r2->resrec.rrtype) &&           // For all address records (A/AAAA) ...
2652                    ResourceRecordIsValidAnswer(r2) &&                  // ... which are valid for answer ...
2653                    rr->LastMCTime - r2->LastMCTime >= 0 &&             // ... which we have not sent recently ...
2654                    rr->resrec.rdatahash == r2->resrec.namehash &&      // ... whose name is the name of the SRV target
2655                    SameDomainName(&rr->resrec.rdata->u.srv.target, r2->resrec.name) &&
2656                    (rr->ImmedAnswer == mDNSInterfaceMark || rr->ImmedAnswer == r2->resrec.InterfaceID))
2657                    r2->ImmedAdditional = r2->resrec.InterfaceID;       // ... then mark this address record for sending too
2658        // We also make sure we send the DeviceInfo TXT record too, if necessary
2659        // We check for RecordType == kDNSRecordTypeShared because we don't want to tag the
2660        // DeviceInfo TXT record onto a goodbye packet (RecordType == kDNSRecordTypeDeregistering).
2661        if (rr->ImmedAnswer && rr->resrec.RecordType == kDNSRecordTypeShared && rr->resrec.rrtype == kDNSType_PTR)
2662            if (ResourceRecordIsValidAnswer(&m->DeviceInfo) && SameDomainLabel(rr->resrec.rdata->u.name.c, m->DeviceInfo.resrec.name->c))
2663            {
2664                if (!m->DeviceInfo.ImmedAnswer) m->DeviceInfo.ImmedAnswer = rr->ImmedAnswer;
2665                else m->DeviceInfo.ImmedAnswer = mDNSInterfaceMark;
2666            }
2667    }
2668
2669    // If there's a record which is supposed to be unique that we're going to send, then make sure that we give
2670    // the whole RRSet as an atomic unit. That means that if we have any other records with the same name/type/class
2671    // then we need to mark them for sending too. Otherwise, if we set the kDNSClass_UniqueRRSet bit on a
2672    // record, then other RRSet members that have not been sent recently will get flushed out of client caches.
2673    // -- 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
2674    // -- If any record is marked to be sent on all interfaces, make sure the whole set is marked to be sent on all interfaces
2675    for (rr = m->ResourceRecords; rr; rr=rr->next)
2676        if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
2677        {
2678            if (rr->ImmedAnswer)            // If we're sending this as answer, see that its whole RRSet is similarly marked
2679            {
2680                for (r2 = m->ResourceRecords; r2; r2=r2->next)
2681                {
2682                    if ((r2->resrec.RecordType & kDNSRecordTypeUniqueMask) && ResourceRecordIsValidAnswer(r2) &&
2683                        (r2->ImmedAnswer != mDNSInterfaceMark) && (r2->ImmedAnswer != rr->ImmedAnswer) &&
2684                        SameResourceRecordSignature(r2, rr) &&
2685                        ((rr->ImmedAnswer == mDNSInterfaceMark) || IsInterfaceValidForAuthRecord(r2, rr->ImmedAnswer)))
2686                    {
2687                        r2->ImmedAnswer = !r2->ImmedAnswer ? rr->ImmedAnswer : mDNSInterfaceMark;
2688                    }
2689                }
2690            }
2691            else if (rr->ImmedAdditional)   // If we're sending this as additional, see that its whole RRSet is similarly marked
2692            {
2693                for (r2 = m->ResourceRecords; r2; r2=r2->next)
2694                {
2695                    if ((r2->resrec.RecordType & kDNSRecordTypeUniqueMask) && ResourceRecordIsValidAnswer(r2) &&
2696                        (r2->ImmedAdditional != rr->ImmedAdditional) &&
2697                        SameResourceRecordSignature(r2, rr) &&
2698                        IsInterfaceValidForAuthRecord(r2, rr->ImmedAdditional))
2699                    {
2700                        r2->ImmedAdditional = rr->ImmedAdditional;
2701                    }
2702                }
2703            }
2704        }
2705
2706    // Now set SendRNow state appropriately
2707    for (rr = m->ResourceRecords; rr; rr=rr->next)
2708    {
2709        if (rr->ImmedAnswer == mDNSInterfaceMark)       // Sending this record on all appropriate interfaces
2710        {
2711            rr->SendRNow = !intf ? mDNSNULL : (rr->resrec.InterfaceID) ? rr->resrec.InterfaceID : intf->InterfaceID;
2712            rr->ImmedAdditional = mDNSNULL;             // No need to send as additional if sending as answer
2713            rr->LastMCTime      = m->timenow;
2714            rr->LastMCInterface = rr->ImmedAnswer;
2715            rr->ProbeRestartCount = 0;                  // Reset the probe restart count
2716            // If we're announcing this record, and it's at least half-way to its ordained time, then consider this announcement done
2717            if (TimeToAnnounceThisRecord(rr, m->timenow + rr->ThisAPInterval/2))
2718            {
2719                rr->AnnounceCount--;
2720                if (rr->resrec.RecordType != kDNSRecordTypeDeregistering)
2721                    rr->ThisAPInterval *= 2;
2722                rr->LastAPTime = m->timenow;
2723                debugf("Announcing %##s (%s) %d", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype), rr->AnnounceCount);
2724            }
2725        }
2726        else if (rr->ImmedAnswer)                       // Else, just respond to a single query on single interface:
2727        {
2728            rr->SendRNow        = rr->ImmedAnswer;      // Just respond on that interface
2729            rr->ImmedAdditional = mDNSNULL;             // No need to send as additional too
2730            rr->LastMCTime      = m->timenow;
2731            rr->LastMCInterface = rr->ImmedAnswer;
2732        }
2733        SetNextAnnounceProbeTime(m, rr);
2734        //if (rr->SendRNow) LogMsg("%-15.4a %s", &rr->v4Requester, ARDisplayString(m, rr));
2735    }
2736
2737    // ***
2738    // *** 2. Loop through interface list, sending records as appropriate
2739    // ***
2740
2741    while (intf)
2742    {
2743        int OwnerRecordSpace = (m->AnnounceOwner && intf->MAC.l[0]) ? DNSOpt_Header_Space + DNSOpt_Owner_Space(&m->PrimaryMAC, &intf->MAC) : 0;
2744        int TraceRecordSpace = (mDNS_McastTracingEnabled && MDNS_TRACER) ? DNSOpt_Header_Space + DNSOpt_TraceData_Space : 0;
2745        int numDereg    = 0;
2746        int numAnnounce = 0;
2747        int numAnswer   = 0;
2748        int AnoninfoSpace = 0;
2749        mDNSu8 *responseptr = m->omsg.data;
2750        mDNSu8 *newptr;
2751        InitializeDNSMessage(&m->omsg.h, zeroID, ResponseFlags);
2752
2753        // First Pass. Look for:
2754        // 1. Deregistering records that need to send their goodbye packet
2755        // 2. Updated records that need to retract their old data
2756        // 3. Answers and announcements we need to send
2757        for (rr = m->ResourceRecords; rr; rr=rr->next)
2758        {
2759
2760            // Skip this interface if the record InterfaceID is *Any and the record is not
2761            // appropriate for the interface type.
2762            if ((rr->SendRNow == intf->InterfaceID) &&
2763                ((rr->resrec.InterfaceID == mDNSInterface_Any) && !mDNSPlatformValidRecordForInterface(rr, intf->InterfaceID)))
2764            {
2765                rr->SendRNow = GetNextActiveInterfaceID(intf);
2766            }
2767            else if (rr->SendRNow == intf->InterfaceID)
2768            {
2769                RData  *OldRData    = rr->resrec.rdata;
2770                mDNSu16 oldrdlength = rr->resrec.rdlength;
2771                mDNSu8 active = (mDNSu8)
2772                                (rr->resrec.RecordType != kDNSRecordTypeDeregistering && !ShouldSendGoodbyesBeforeSleep(m, intf, rr));
2773                newptr = mDNSNULL;
2774                if (rr->NewRData && active)
2775                {
2776                    // See if we should send a courtesy "goodbye" for the old data before we replace it.
2777                    if (ResourceRecordIsValidAnswer(rr) && rr->resrec.RecordType == kDNSRecordTypeShared && rr->RequireGoodbye)
2778                    {
2779                        newptr = PutRR_OS_TTL(responseptr, &m->omsg.h.numAnswers, &rr->resrec, 0);
2780                        if (newptr) { responseptr = newptr; numDereg++; rr->RequireGoodbye = mDNSfalse; }
2781                        else continue; // If this packet is already too full to hold the goodbye for this record, skip it for now and we'll retry later
2782                    }
2783                    SetNewRData(&rr->resrec, rr->NewRData, rr->newrdlength);
2784                }
2785
2786                if (rr->resrec.AnonInfo)
2787                {
2788                    int tmp = AnonInfoSpace(rr->resrec.AnonInfo);
2789
2790                    AnoninfoSpace += tmp;
2791                    // Adjust OwnerRecordSpace/TraceRecordSpace which is used by PutRR_OS_TTL below so that
2792                    // we have space to put in the NSEC3 record in the authority section.
2793                    OwnerRecordSpace += tmp;
2794                    TraceRecordSpace += tmp;
2795                }
2796
2797                if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
2798                    rr->resrec.rrclass |= kDNSClass_UniqueRRSet;        // Temporarily set the cache flush bit so PutResourceRecord will set it
2799                newptr = PutRR_OS_TTL(responseptr, &m->omsg.h.numAnswers, &rr->resrec, active ? rr->resrec.rroriginalttl : 0);
2800                rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;           // Make sure to clear cache flush bit back to normal state
2801                if (newptr)
2802                {
2803                    responseptr = newptr;
2804                    rr->RequireGoodbye = active;
2805                    if (rr->resrec.RecordType == kDNSRecordTypeDeregistering) numDereg++;
2806                    else if (rr->LastAPTime == m->timenow) numAnnounce++;else numAnswer++;
2807                }
2808
2809                if (rr->NewRData && active)
2810                    SetNewRData(&rr->resrec, OldRData, oldrdlength);
2811
2812                // The first time through (pktcount==0), if this record is verified unique
2813                // (i.e. typically A, AAAA, SRV, TXT and reverse-mapping PTR), set the flag to add an NSEC too.
2814                if (!pktcount && active && (rr->resrec.RecordType & kDNSRecordTypeActiveUniqueMask) && !rr->SendNSECNow)
2815                    rr->SendNSECNow = mDNSInterfaceMark;
2816
2817                if (newptr)     // If succeeded in sending, advance to next interface
2818                {
2819                    if (rr->resrec.AnonInfo)
2820                    {
2821                        debugf("SendResponses: Marking %s, OwnerRecordSpace %d, TraceRecordSpace %d, limit %p", ARDisplayString(m, rr), OwnerRecordSpace,
2822                                TraceRecordSpace, m->omsg.data + AllowedRRSpace(&m->omsg) - OwnerRecordSpace - TraceRecordSpace);
2823                        rr->resrec.AnonInfo->SendNow = intf->InterfaceID;
2824                    }
2825
2826                    // If sending on all interfaces, go to next interface; else we're finished now
2827                    if (rr->ImmedAnswer == mDNSInterfaceMark && rr->resrec.InterfaceID == mDNSInterface_Any)
2828                        rr->SendRNow = GetNextActiveInterfaceID(intf);
2829                    else
2830                        rr->SendRNow = mDNSNULL;
2831                }
2832            }
2833        }
2834
2835        // Get the reserved space back
2836        OwnerRecordSpace -= AnoninfoSpace;
2837        TraceRecordSpace -= AnoninfoSpace;
2838        newptr = responseptr;
2839        for (rr = m->ResourceRecords; rr; rr=rr->next)
2840        {
2841            if (rr->resrec.AnonInfo && rr->resrec.AnonInfo->SendNow == intf->InterfaceID)
2842            {
2843                ResourceRecord *nsec3RR = rr->resrec.AnonInfo->nsec3RR;
2844
2845                newptr = PutRR_OS_TTL(newptr, &m->omsg.h.numAuthorities, nsec3RR,  nsec3RR->rroriginalttl);
2846                if (newptr)
2847                {
2848                    responseptr = newptr;
2849                    debugf("SendResponses: Added NSEC3 %s, OwnerRecordSpace %d, TraceRecordSpace %d, limit %p", ARDisplayString(m, rr), OwnerRecordSpace,
2850                            TraceRecordSpace, m->omsg.data + AllowedRRSpace(&m->omsg) - OwnerRecordSpace - TraceRecordSpace);
2851                }
2852                else
2853                {
2854                    LogMsg("SendResponses: Cannot add NSEC3 %s, OwnerRecordSpace %d, TraceRecordSpace %d, limit %p", ARDisplayString(m, rr), OwnerRecordSpace,
2855                            TraceRecordSpace, m->omsg.data + AllowedRRSpace(&m->omsg) - OwnerRecordSpace - TraceRecordSpace);
2856                }
2857                rr->resrec.AnonInfo->SendNow = mDNSNULL;
2858            }
2859        }
2860        // Second Pass. Add additional records, if there's space.
2861        newptr = responseptr;
2862        for (rr = m->ResourceRecords; rr; rr=rr->next)
2863            if (rr->ImmedAdditional == intf->InterfaceID)
2864                if (ResourceRecordIsValidAnswer(rr))
2865                {
2866                    // If we have at least one answer already in the packet, then plan to add additionals too
2867                    mDNSBool SendAdditional = (m->omsg.h.numAnswers > 0);
2868
2869                    // If we're not planning to send any additionals, but this record is a unique one, then
2870                    // make sure we haven't already sent any other members of its RRSet -- if we have, then they
2871                    // will have had the cache flush bit set, so now we need to finish the job and send the rest.
2872                    if (!SendAdditional && (rr->resrec.RecordType & kDNSRecordTypeUniqueMask))
2873                    {
2874                        const AuthRecord *a;
2875                        for (a = m->ResourceRecords; a; a=a->next)
2876                            if (a->LastMCTime      == m->timenow &&
2877                                a->LastMCInterface == intf->InterfaceID &&
2878                                SameResourceRecordSignature(a, rr)) { SendAdditional = mDNStrue; break; }
2879                    }
2880                    if (!SendAdditional)                    // If we don't want to send this after all,
2881                        rr->ImmedAdditional = mDNSNULL;     // then cancel its ImmedAdditional field
2882                    else if (newptr)                        // Else, try to add it if we can
2883                    {
2884                        // The first time through (pktcount==0), if this record is verified unique
2885                        // (i.e. typically A, AAAA, SRV, TXT and reverse-mapping PTR), set the flag to add an NSEC too.
2886                        if (!pktcount && (rr->resrec.RecordType & kDNSRecordTypeActiveUniqueMask) && !rr->SendNSECNow)
2887                            rr->SendNSECNow = mDNSInterfaceMark;
2888
2889                        if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
2890                            rr->resrec.rrclass |= kDNSClass_UniqueRRSet;    // Temporarily set the cache flush bit so PutResourceRecord will set it
2891                        newptr = PutRR_OS(newptr, &m->omsg.h.numAdditionals, &rr->resrec);
2892                        rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;       // Make sure to clear cache flush bit back to normal state
2893                        if (newptr)
2894                        {
2895                            responseptr = newptr;
2896                            rr->ImmedAdditional = mDNSNULL;
2897                            rr->RequireGoodbye = mDNStrue;
2898                            // If we successfully put this additional record in the packet, we record LastMCTime & LastMCInterface.
2899                            // This matters particularly in the case where we have more than one IPv6 (or IPv4) address, because otherwise,
2900                            // when we see our own multicast with the cache flush bit set, if we haven't set LastMCTime, then we'll get
2901                            // all concerned and re-announce our record again to make sure it doesn't get flushed from peer caches.
2902                            rr->LastMCTime      = m->timenow;
2903                            rr->LastMCInterface = intf->InterfaceID;
2904                        }
2905                    }
2906                }
2907
2908        // Third Pass. Add NSEC records, if there's space.
2909        // When we're generating an NSEC record in response to a specify query for that type
2910        // (recognized by rr->SendNSECNow == intf->InterfaceID) we should really put the NSEC in the Answer Section,
2911        // not Additional Section, but for now it's easier to handle both cases in this Additional Section loop here.
2912        for (rr = m->ResourceRecords; rr; rr=rr->next)
2913            if (rr->SendNSECNow == mDNSInterfaceMark || rr->SendNSECNow == intf->InterfaceID)
2914            {
2915                AuthRecord nsec;
2916                mDNSu8 *ptr;
2917                int len;
2918                mDNS_SetupResourceRecord(&nsec, mDNSNULL, mDNSInterface_Any, kDNSType_NSEC, rr->resrec.rroriginalttl, kDNSRecordTypeUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
2919                nsec.resrec.rrclass |= kDNSClass_UniqueRRSet;
2920                AssignDomainName(&nsec.namestorage, rr->resrec.name);
2921                ptr = nsec.rdatastorage.u.data;
2922                len = DomainNameLength(rr->resrec.name);
2923                // We have a nxt name followed by window number, window length and a window bitmap
2924                nsec.resrec.rdlength = len + 2 + NSEC_MCAST_WINDOW_SIZE;
2925                if (nsec.resrec.rdlength <= StandardAuthRDSize)
2926                {
2927                    mDNSPlatformMemZero(ptr, nsec.resrec.rdlength);
2928                    AssignDomainName((domainname *)ptr, rr->resrec.name);
2929                    ptr += len;
2930                    *ptr++ = 0; // window number
2931                    *ptr++ = NSEC_MCAST_WINDOW_SIZE; // window length
2932                    for (r2 = m->ResourceRecords; r2; r2=r2->next)
2933                        if (ResourceRecordIsValidAnswer(r2) && SameResourceRecordNameClassInterface(r2, rr))
2934                        {
2935                            if (r2->resrec.rrtype >= kDNSQType_ANY) { LogMsg("SendResponses: Can't create NSEC for record %s", ARDisplayString(m, r2)); break; }
2936                            else ptr[r2->resrec.rrtype >> 3] |= 128 >> (r2->resrec.rrtype & 7);
2937                        }
2938                    newptr = responseptr;
2939                    if (!r2)    // If we successfully built our NSEC record, add it to the packet now
2940                    {
2941                        newptr = PutRR_OS(responseptr, &m->omsg.h.numAdditionals, &nsec.resrec);
2942                        if (newptr) responseptr = newptr;
2943                    }
2944                }
2945                else LogMsg("SendResponses: not enough space (%d)  in authrecord for nsec", nsec.resrec.rdlength);
2946
2947                // If we successfully put the NSEC record, clear the SendNSECNow flag
2948                // If we consider this NSEC optional, then we unconditionally clear the SendNSECNow flag, even if we fail to put this additional record
2949                if (newptr || rr->SendNSECNow == mDNSInterfaceMark)
2950                {
2951                    rr->SendNSECNow = mDNSNULL;
2952                    // Run through remainder of list clearing SendNSECNow flag for all other records which would generate the same NSEC
2953                    for (r2 = rr->next; r2; r2=r2->next)
2954                        if (SameResourceRecordNameClassInterface(r2, rr))
2955                            if (r2->SendNSECNow == mDNSInterfaceMark || r2->SendNSECNow == intf->InterfaceID)
2956                                r2->SendNSECNow = mDNSNULL;
2957                }
2958            }
2959
2960        if (m->omsg.h.numAnswers || m->omsg.h.numAdditionals)
2961        {
2962            // If we have data to send, add OWNER/TRACER/OWNER+TRACER option if necessary, then send packet
2963            if (OwnerRecordSpace || TraceRecordSpace)
2964            {
2965                AuthRecord opt;
2966                mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
2967                opt.resrec.rrclass    = NormalMaxDNSMessageData;
2968                opt.resrec.rdlength   = sizeof(rdataOPT);
2969                opt.resrec.rdestimate = sizeof(rdataOPT);
2970                if (OwnerRecordSpace && TraceRecordSpace)
2971                {
2972                    opt.resrec.rdlength   += sizeof(rdataOPT); // Two options in this OPT record
2973                    opt.resrec.rdestimate += sizeof(rdataOPT);
2974                    SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[0]);
2975                    SetupTracerOpt(m, &opt.resrec.rdata->u.opt[1]);
2976                }
2977                else if (OwnerRecordSpace)
2978                {
2979                    SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[0]);
2980                }
2981                else if (TraceRecordSpace)
2982                {
2983                    SetupTracerOpt(m, &opt.resrec.rdata->u.opt[0]);
2984                }
2985                newptr = PutResourceRecord(&m->omsg, responseptr, &m->omsg.h.numAdditionals, &opt.resrec);
2986                if (newptr)
2987                {
2988                    responseptr = newptr;
2989                }
2990                else if (m->omsg.h.numAnswers + m->omsg.h.numAuthorities + m->omsg.h.numAdditionals == 1)
2991                {
2992                    LogInfo("SendResponses: No space in packet for %s %s OPT record (%d/%d/%d/%d) %s", OwnerRecordSpace ? "OWNER" : "", TraceRecordSpace ? "TRACER" : "",
2993                            m->omsg.h.numQuestions, m->omsg.h.numAnswers, m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt));
2994                }
2995                else
2996                {
2997                    LogMsg("SendResponses: How did we fail to have space for %s %s OPT record (%d/%d/%d/%d) %s", OwnerRecordSpace ? "OWNER" : "", TraceRecordSpace ? "TRACER" : "",
2998                           m->omsg.h.numQuestions, m->omsg.h.numAnswers, m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt));
2999                }
3000            }
3001
3002            debugf("SendResponses: Sending %d Deregistration%s, %d Announcement%s, %d Answer%s, %d Additional%s on %p",
3003                   numDereg,                 numDereg                 == 1 ? "" : "s",
3004                   numAnnounce,              numAnnounce              == 1 ? "" : "s",
3005                   numAnswer,                numAnswer                == 1 ? "" : "s",
3006                   m->omsg.h.numAdditionals, m->omsg.h.numAdditionals == 1 ? "" : "s", intf->InterfaceID);
3007
3008            if (intf->IPv4Available) mDNSSendDNSMessage(m, &m->omsg, responseptr, intf->InterfaceID, mDNSNULL, &AllDNSLinkGroup_v4, MulticastDNSPort, mDNSNULL, mDNSNULL, mDNSfalse);
3009            if (intf->IPv6Available) mDNSSendDNSMessage(m, &m->omsg, responseptr, intf->InterfaceID, mDNSNULL, &AllDNSLinkGroup_v6, MulticastDNSPort, mDNSNULL, mDNSNULL, mDNSfalse);
3010            if (!m->SuppressSending) m->SuppressSending = NonZeroTime(m->timenow + (mDNSPlatformOneSecond+9)/10);
3011            if (++pktcount >= 1000) { LogMsg("SendResponses exceeded loop limit %d: giving up", pktcount); break; }
3012            // There might be more things to send on this interface, so go around one more time and try again.
3013        }
3014        else    // Nothing more to send on this interface; go to next
3015        {
3016            const NetworkInterfaceInfo *next = GetFirstActiveInterface(intf->next);
3017            #if MDNS_DEBUGMSGS && 0
3018            const char *const msg = next ? "SendResponses: Nothing more on %p; moving to %p" : "SendResponses: Nothing more on %p";
3019            debugf(msg, intf, next);
3020            #endif
3021            intf = next;
3022            pktcount = 0;       // When we move to a new interface, reset packet count back to zero -- NSEC generation logic uses it
3023        }
3024    }
3025
3026    // ***
3027    // *** 3. Cleanup: Now that everything is sent, call client callback functions, and reset state variables
3028    // ***
3029
3030    if (m->CurrentRecord)
3031        LogMsg("SendResponses ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
3032    m->CurrentRecord = m->ResourceRecords;
3033    while (m->CurrentRecord)
3034    {
3035        rr = m->CurrentRecord;
3036        m->CurrentRecord = rr->next;
3037
3038        if (rr->SendRNow)
3039        {
3040            if (rr->ARType != AuthRecordLocalOnly && rr->ARType != AuthRecordP2P)
3041                LogInfo("SendResponses: No active interface %d to send: %d %02X %s",
3042                     (uint32_t)rr->SendRNow, (uint32_t)rr->resrec.InterfaceID, rr->resrec.RecordType, ARDisplayString(m, rr));
3043            rr->SendRNow = mDNSNULL;
3044        }
3045
3046        if (rr->ImmedAnswer || rr->resrec.RecordType == kDNSRecordTypeDeregistering)
3047        {
3048            if (rr->NewRData) CompleteRDataUpdate(m, rr);   // Update our rdata, clear the NewRData pointer, and return memory to the client
3049
3050            if (rr->resrec.RecordType == kDNSRecordTypeDeregistering && rr->AnnounceCount == 0)
3051            {
3052                // For Unicast, when we get the response from the server, we will call CompleteDeregistration
3053                if (!AuthRecord_uDNS(rr)) CompleteDeregistration(m, rr);        // Don't touch rr after this
3054            }
3055            else
3056            {
3057                rr->ImmedAnswer  = mDNSNULL;
3058                rr->ImmedUnicast = mDNSfalse;
3059                rr->v4Requester  = zerov4Addr;
3060                rr->v6Requester  = zerov6Addr;
3061            }
3062        }
3063    }
3064    verbosedebugf("SendResponses: Next in %ld ticks", m->NextScheduledResponse - m->timenow);
3065}
3066
3067// Calling CheckCacheExpiration() is an expensive operation because it has to look at the entire cache,
3068// so we want to be lazy about how frequently we do it.
3069// 1. If a cache record is currently referenced by *no* active questions,
3070//    then we don't mind expiring it up to a minute late (who will know?)
3071// 2. Else, if a cache record is due for some of its final expiration queries,
3072//    we'll allow them to be late by up to 2% of the TTL
3073// 3. Else, if a cache record has completed all its final expiration queries without success,
3074//    and is expiring, and had an original TTL more than ten seconds, we'll allow it to be one second late
3075// 4. Else, it is expiring and had an original TTL of ten seconds or less (includes explicit goodbye packets),
3076//    so allow at most 1/10 second lateness
3077// 5. For records with rroriginalttl set to zero, that means we really want to delete them immediately
3078//    (we have a new record with DelayDelivery set, waiting for the old record to go away before we can notify clients).
3079#define CacheCheckGracePeriod(RR) (                                                   \
3080        ((RR)->CRActiveQuestion == mDNSNULL            ) ? (60 * mDNSPlatformOneSecond) : \
3081        ((RR)->UnansweredQueries < MaxUnansweredQueries) ? (TicksTTL(rr)/50)            : \
3082        ((RR)->resrec.rroriginalttl > 10               ) ? (mDNSPlatformOneSecond)      : \
3083        ((RR)->resrec.rroriginalttl > 0                ) ? (mDNSPlatformOneSecond/10)   : 0)
3084
3085#define NextCacheCheckEvent(RR) ((RR)->NextRequiredQuery + CacheCheckGracePeriod(RR))
3086
3087mDNSexport void ScheduleNextCacheCheckTime(mDNS *const m, const mDNSu32 slot, const mDNSs32 event)
3088{
3089    if (m->rrcache_nextcheck[slot] - event > 0)
3090        m->rrcache_nextcheck[slot] = event;
3091    if (m->NextCacheCheck          - event > 0)
3092        m->NextCacheCheck          = event;
3093}
3094
3095// Note: MUST call SetNextCacheCheckTimeForRecord any time we change:
3096// rr->TimeRcvd
3097// rr->resrec.rroriginalttl
3098// rr->UnansweredQueries
3099// rr->CRActiveQuestion
3100mDNSexport void SetNextCacheCheckTimeForRecord(mDNS *const m, CacheRecord *const rr)
3101{
3102    rr->NextRequiredQuery = RRExpireTime(rr);
3103
3104    // If we have an active question, then see if we want to schedule a refresher query for this record.
3105    // Usually we expect to do four queries, at 80-82%, 85-87%, 90-92% and then 95-97% of the TTL.
3106    if (rr->CRActiveQuestion && rr->UnansweredQueries < MaxUnansweredQueries)
3107    {
3108        rr->NextRequiredQuery -= TicksTTL(rr)/20 * (MaxUnansweredQueries - rr->UnansweredQueries);
3109        rr->NextRequiredQuery += mDNSRandom((mDNSu32)TicksTTL(rr)/50);
3110        verbosedebugf("SetNextCacheCheckTimeForRecord: NextRequiredQuery in %ld sec CacheCheckGracePeriod %d ticks for %s",
3111                      (rr->NextRequiredQuery - m->timenow) / mDNSPlatformOneSecond, CacheCheckGracePeriod(rr), CRDisplayString(m,rr));
3112    }
3113    ScheduleNextCacheCheckTime(m, HashSlotFromNameHash(rr->resrec.namehash), NextCacheCheckEvent(rr));
3114}
3115
3116#define kMinimumReconfirmTime                     ((mDNSu32)mDNSPlatformOneSecond *  5)
3117#define kDefaultReconfirmTimeForWake              ((mDNSu32)mDNSPlatformOneSecond *  5)
3118#define kDefaultReconfirmTimeForNoAnswer          ((mDNSu32)mDNSPlatformOneSecond *  5)
3119
3120// Delay before restarting questions on a flapping interface.
3121#define kDefaultQueryDelayTimeForFlappingInterface ((mDNSu32)mDNSPlatformOneSecond *  3)
3122// After kDefaultQueryDelayTimeForFlappingInterface seconds, allow enough time for up to three queries (0, 1, and 4 seconds)
3123// plus three seconds for "response delay" before removing the reconfirmed records from the cache.
3124#define kDefaultReconfirmTimeForFlappingInterface (kDefaultQueryDelayTimeForFlappingInterface + ((mDNSu32)mDNSPlatformOneSecond *  7))
3125
3126mDNSexport mStatus mDNS_Reconfirm_internal(mDNS *const m, CacheRecord *const rr, mDNSu32 interval)
3127{
3128    if (interval < kMinimumReconfirmTime)
3129        interval = kMinimumReconfirmTime;
3130    if (interval > 0x10000000)  // Make sure interval doesn't overflow when we multiply by four below
3131        interval = 0x10000000;
3132
3133    // If the expected expiration time for this record is more than interval+33%, then accelerate its expiration
3134    if (RRExpireTime(rr) - m->timenow > (mDNSs32)((interval * 4) / 3))
3135    {
3136        // Add a 33% random amount to the interval, to avoid synchronization between multiple hosts
3137        // For all the reconfirmations in a given batch, we want to use the same random value
3138        // so that the reconfirmation questions can be grouped into a single query packet
3139        if (!m->RandomReconfirmDelay) m->RandomReconfirmDelay = 1 + mDNSRandom(FutureTime);
3140        interval += m->RandomReconfirmDelay % ((interval/3) + 1);
3141        rr->TimeRcvd          = m->timenow - (mDNSs32)interval * 3;
3142        rr->resrec.rroriginalttl     = (interval * 4 + mDNSPlatformOneSecond - 1) / mDNSPlatformOneSecond;
3143        SetNextCacheCheckTimeForRecord(m, rr);
3144    }
3145    debugf("mDNS_Reconfirm_internal:%6ld ticks to go for %s %p",
3146           RRExpireTime(rr) - m->timenow, CRDisplayString(m, rr), rr->CRActiveQuestion);
3147    return(mStatus_NoError);
3148}
3149
3150// BuildQuestion puts a question into a DNS Query packet and if successful, updates the value of queryptr.
3151// It also appends to the list of known answer records that need to be included,
3152// and updates the forcast for the size of the known answer section.
3153mDNSlocal mDNSBool BuildQuestion(mDNS *const m, const NetworkInterfaceInfo *intf, DNSMessage *query, mDNSu8 **queryptr,
3154                                 DNSQuestion *q, CacheRecord ***kalistptrptr, mDNSu32 *answerforecast)
3155{
3156    mDNSBool ucast = (q->LargeAnswers || q->RequestUnicast) && m->CanReceiveUnicastOn5353 && intf->SupportsUnicastMDNSResponse;
3157    mDNSu16 ucbit = (mDNSu16)(ucast ? kDNSQClass_UnicastResponse : 0);
3158    const mDNSu8 *const limit = query->data + NormalMaxDNSMessageData;
3159    mDNSu8 anoninfo_space = q->AnonInfo ? AnonInfoSpace(q->AnonInfo) : 0;
3160    mDNSu8 *newptr = putQuestion(query, *queryptr, limit - *answerforecast - anoninfo_space, &q->qname, q->qtype, (mDNSu16)(q->qclass | ucbit));
3161    if (!newptr)
3162    {
3163        debugf("BuildQuestion: No more space in this packet for question %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
3164        return(mDNSfalse);
3165    }
3166    else
3167    {
3168        mDNSu32 forecast = *answerforecast + anoninfo_space;
3169        const CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname);
3170        CacheRecord *rr;
3171        CacheRecord **ka = *kalistptrptr;   // Make a working copy of the pointer we're going to update
3172
3173        for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)             // If we have a resource record in our cache,
3174            if (rr->resrec.InterfaceID == q->SendQNow &&                    // received on this interface
3175                !(rr->resrec.RecordType & kDNSRecordTypeUniqueMask) &&      // which is a shared (i.e. not unique) record type
3176                rr->NextInKAList == mDNSNULL && ka != &rr->NextInKAList &&  // which is not already in the known answer list
3177                rr->resrec.rdlength <= SmallRecordLimit &&                  // which is small enough to sensibly fit in the packet
3178                SameNameRecordAnswersQuestion(&rr->resrec, q) &&            // which answers our question
3179                rr->TimeRcvd + TicksTTL(rr)/2 - m->timenow >                // and its half-way-to-expiry time is at least 1 second away
3180                mDNSPlatformOneSecond)                                      // (also ensures we never include goodbye records with TTL=1)
3181            {
3182                // We don't want to include unique records in the Known Answer section. The Known Answer section
3183                // is intended to suppress floods of shared-record replies from many other devices on the network.
3184                // That concept really does not apply to unique records, and indeed if we do send a query for
3185                // which we have a unique record already in our cache, then including that unique record as a
3186                // Known Answer, so as to suppress the only answer we were expecting to get, makes little sense.
3187
3188                *ka = rr;   // Link this record into our known answer chain
3189                ka = &rr->NextInKAList;
3190                // We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n)
3191                forecast += 12 + rr->resrec.rdestimate;
3192                // If we're trying to put more than one question in this packet, and it doesn't fit
3193                // then undo that last question and try again next time
3194                if (query->h.numQuestions > 1 && newptr + forecast >= limit)
3195                {
3196                    query->h.numQuestions--;
3197                    debugf("BuildQuestion: Retracting question %##s (%s) new forecast total %d, total questions %d",
3198                           q->qname.c, DNSTypeName(q->qtype), newptr + forecast - query->data, query->h.numQuestions);
3199                    ka = *kalistptrptr;     // Go back to where we started and retract these answer records
3200                    while (*ka) { CacheRecord *c = *ka; *ka = mDNSNULL; ka = &c->NextInKAList; }
3201                    return(mDNSfalse);      // Return false, so we'll try again in the next packet
3202                }
3203            }
3204
3205        // Success! Update our state pointers, increment UnansweredQueries as appropriate, and return
3206        *queryptr        = newptr;              // Update the packet pointer
3207        *answerforecast  = forecast;            // Update the forecast
3208        *kalistptrptr    = ka;                  // Update the known answer list pointer
3209        if (ucast) q->ExpectUnicastResp = NonZeroTime(m->timenow);
3210
3211        for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)             // For every resource record in our cache,
3212            if (rr->resrec.InterfaceID == q->SendQNow &&                    // received on this interface
3213                rr->NextInKAList == mDNSNULL && ka != &rr->NextInKAList &&  // which is not in the known answer list
3214                SameNameRecordAnswersQuestion(&rr->resrec, q))              // which answers our question
3215            {
3216                rr->UnansweredQueries++;                                    // indicate that we're expecting a response
3217                rr->LastUnansweredTime = m->timenow;
3218                SetNextCacheCheckTimeForRecord(m, rr);
3219            }
3220
3221        return(mDNStrue);
3222    }
3223}
3224
3225// When we have a query looking for a specified name, but there appear to be no answers with
3226// that name, ReconfirmAntecedents() is called with depth=0 to start the reconfirmation process
3227// for any records in our cache that reference the given name (e.g. PTR and SRV records).
3228// For any such cache record we find, we also recursively call ReconfirmAntecedents() for *its* name.
3229// We increment depth each time we recurse, to guard against possible infinite loops, with a limit of 5.
3230// A typical reconfirmation scenario might go like this:
3231// Depth 0: Name "myhost.local" has no address records
3232// Depth 1: SRV "My Service._example._tcp.local." refers to "myhost.local"; may be stale
3233// Depth 2: PTR "_example._tcp.local." refers to "My Service"; may be stale
3234// Depth 3: PTR "_services._dns-sd._udp.local." refers to "_example._tcp.local."; may be stale
3235// Currently depths 4 and 5 are not expected to occur; if we did get to depth 5 we'd reconfim any records we
3236// found referring to the given name, but not recursively descend any further reconfirm *their* antecedents.
3237mDNSlocal void ReconfirmAntecedents(mDNS *const m, const domainname *const name, const mDNSu32 namehash, const mDNSInterfaceID InterfaceID, const int depth)
3238{
3239    mDNSu32 slot;
3240    const CacheGroup *cg;
3241    CacheRecord *cr;
3242    debugf("ReconfirmAntecedents (depth=%d) for %##s", depth, name->c);
3243    if (!InterfaceID) return; // mDNS records have a non-zero InterfaceID. If InterfaceID is 0, then there's nothing to do.
3244    FORALL_CACHERECORDS(slot, cg, cr)
3245    {
3246        const domainname *crtarget;
3247        if (cr->resrec.InterfaceID != InterfaceID) continue; // Skip non-mDNS records and mDNS records from other interfaces.
3248        if (cr->resrec.rdatahash != namehash)      continue; // Skip records whose rdata hash doesn't match the name hash.
3249        crtarget = GetRRDomainNameTarget(&cr->resrec);
3250        if (crtarget && SameDomainName(crtarget, name))
3251        {
3252            LogInfo("ReconfirmAntecedents: Reconfirming (depth=%d, InterfaceID=%p) %s", depth, InterfaceID, CRDisplayString(m, cr));
3253            mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
3254            if (depth < 5)
3255                ReconfirmAntecedents(m, cr->resrec.name, cr->resrec.namehash, InterfaceID, depth+1);
3256        }
3257    }
3258}
3259
3260// If we get no answer for a AAAA query, then before doing an automatic implicit ReconfirmAntecedents
3261// we check if we have an address record for the same name. If we do have an IPv4 address for a given
3262// name but not an IPv6 address, that's okay (it just means the device doesn't do IPv6) so the failure
3263// to get a AAAA response is not grounds to doubt the PTR/SRV chain that lead us to that name.
3264mDNSlocal const CacheRecord *CacheHasAddressTypeForName(mDNS *const m, const domainname *const name, const mDNSu32 namehash)
3265{
3266    CacheGroup *const cg = CacheGroupForName(m, namehash, name);
3267    const CacheRecord *cr = cg ? cg->members : mDNSNULL;
3268    while (cr && !RRTypeIsAddressType(cr->resrec.rrtype)) cr=cr->next;
3269    return(cr);
3270}
3271
3272
3273mDNSlocal const CacheRecord *FindSPSInCache1(mDNS *const m, const DNSQuestion *const q, const CacheRecord *const c0, const CacheRecord *const c1)
3274{
3275#ifndef SPC_DISABLED
3276    CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname);
3277    const CacheRecord *cr, *bestcr = mDNSNULL;
3278    mDNSu32 bestmetric = 1000000;
3279    for (cr = cg ? cg->members : mDNSNULL; cr; cr=cr->next)
3280        if (cr->resrec.rrtype == kDNSType_PTR && cr->resrec.rdlength >= 6)                      // If record is PTR type, with long enough name,
3281            if (cr != c0 && cr != c1)                                                           // that's not one we've seen before,
3282                if (SameNameRecordAnswersQuestion(&cr->resrec, q))                              // and answers our browse query,
3283                    if (!IdenticalSameNameRecord(&cr->resrec, &m->SPSRecords.RR_PTR.resrec))    // and is not our own advertised service...
3284                    {
3285                        mDNSu32 metric = SPSMetric(cr->resrec.rdata->u.name.c);
3286                        if (bestmetric > metric) { bestmetric = metric; bestcr = cr; }
3287                    }
3288    return(bestcr);
3289#else // SPC_DISABLED
3290    (void) m;
3291    (void) q;
3292    (void) c0;
3293    (void) c1;
3294    (void) c1;
3295    return mDNSNULL;
3296#endif // SPC_DISABLED
3297}
3298
3299mDNSlocal void CheckAndSwapSPS(const CacheRecord **sps1, const CacheRecord **sps2)
3300{
3301    const CacheRecord *swap_sps;
3302    mDNSu32 metric1, metric2;
3303
3304    if (!(*sps1) || !(*sps2)) return;
3305    metric1 = SPSMetric((*sps1)->resrec.rdata->u.name.c);
3306    metric2 = SPSMetric((*sps2)->resrec.rdata->u.name.c);
3307    if (!SPSFeatures((*sps1)->resrec.rdata->u.name.c) && SPSFeatures((*sps2)->resrec.rdata->u.name.c) && (metric2 >= metric1))
3308    {
3309        swap_sps = *sps1;
3310        *sps1    = *sps2;
3311        *sps2    = swap_sps;
3312    }
3313}
3314
3315mDNSlocal void ReorderSPSByFeature(const CacheRecord *sps[3])
3316{
3317    CheckAndSwapSPS(&sps[0], &sps[1]);
3318    CheckAndSwapSPS(&sps[0], &sps[2]);
3319    CheckAndSwapSPS(&sps[1], &sps[2]);
3320}
3321
3322
3323// Finds the three best Sleep Proxies we currently have in our cache
3324mDNSexport void FindSPSInCache(mDNS *const m, const DNSQuestion *const q, const CacheRecord *sps[3])
3325{
3326    sps[0] =                      FindSPSInCache1(m, q, mDNSNULL, mDNSNULL);
3327    sps[1] = !sps[0] ? mDNSNULL : FindSPSInCache1(m, q, sps[0],   mDNSNULL);
3328    sps[2] = !sps[1] ? mDNSNULL : FindSPSInCache1(m, q, sps[0],   sps[1]);
3329
3330    // SPS is already sorted by metric. We want to move the entries to the beginning of the array
3331    // only if they have equally good metric and support features.
3332    ReorderSPSByFeature(sps);
3333}
3334
3335// Only DupSuppressInfos newer than the specified 'time' are allowed to remain active
3336mDNSlocal void ExpireDupSuppressInfo(DupSuppressInfo ds[DupSuppressInfoSize], mDNSs32 time)
3337{
3338    int i;
3339    for (i=0; i<DupSuppressInfoSize; i++) if (ds[i].Time - time < 0) ds[i].InterfaceID = mDNSNULL;
3340}
3341
3342mDNSlocal void ExpireDupSuppressInfoOnInterface(DupSuppressInfo ds[DupSuppressInfoSize], mDNSs32 time, mDNSInterfaceID InterfaceID)
3343{
3344    int i;
3345    for (i=0; i<DupSuppressInfoSize; i++) if (ds[i].InterfaceID == InterfaceID && ds[i].Time - time < 0) ds[i].InterfaceID = mDNSNULL;
3346}
3347
3348mDNSlocal mDNSBool SuppressOnThisInterface(const DupSuppressInfo ds[DupSuppressInfoSize], const NetworkInterfaceInfo * const intf)
3349{
3350    int i;
3351    mDNSBool v4 = !intf->IPv4Available;     // If this interface doesn't do v4, we don't need to find a v4 duplicate of this query
3352    mDNSBool v6 = !intf->IPv6Available;     // If this interface doesn't do v6, we don't need to find a v6 duplicate of this query
3353    for (i=0; i<DupSuppressInfoSize; i++)
3354        if (ds[i].InterfaceID == intf->InterfaceID)
3355        {
3356            if      (ds[i].Type == mDNSAddrType_IPv4) v4 = mDNStrue;
3357            else if (ds[i].Type == mDNSAddrType_IPv6) v6 = mDNStrue;
3358            if (v4 && v6) return(mDNStrue);
3359        }
3360    return(mDNSfalse);
3361}
3362
3363mDNSlocal void RecordDupSuppressInfo(DupSuppressInfo ds[DupSuppressInfoSize], mDNSs32 Time, mDNSInterfaceID InterfaceID, mDNSs32 Type)
3364{
3365    int i, j;
3366
3367    // See if we have this one in our list somewhere already
3368    for (i=0; i<DupSuppressInfoSize; i++) if (ds[i].InterfaceID == InterfaceID && ds[i].Type == Type) break;
3369
3370    // If not, find a slot we can re-use
3371    if (i >= DupSuppressInfoSize)
3372    {
3373        i = 0;
3374        for (j=1; j<DupSuppressInfoSize && ds[i].InterfaceID; j++)
3375            if (!ds[j].InterfaceID || ds[j].Time - ds[i].Time < 0)
3376                i = j;
3377    }
3378
3379    // Record the info about this query we saw
3380    ds[i].Time        = Time;
3381    ds[i].InterfaceID = InterfaceID;
3382    ds[i].Type        = Type;
3383}
3384
3385mDNSlocal void mDNSSendWakeOnResolve(mDNS *const m, DNSQuestion *q)
3386{
3387    int len, i, cnt;
3388    mDNSInterfaceID InterfaceID = q->InterfaceID;
3389    domainname *d = &q->qname;
3390
3391    // We can't send magic packets without knowing which interface to send it on.
3392    if (InterfaceID == mDNSInterface_Any || LocalOnlyOrP2PInterface(InterfaceID))
3393    {
3394        LogMsg("mDNSSendWakeOnResolve: ERROR!! Invalid InterfaceID %p for question %##s", InterfaceID, q->qname.c);
3395        return;
3396    }
3397
3398    // Split MAC@IPAddress and pass them separately
3399    len = d->c[0];
3400    cnt = 0;
3401    for (i = 1; i < len; i++)
3402    {
3403        if (d->c[i] == '@')
3404        {
3405            char EthAddr[18];   // ethernet adddress : 12 bytes + 5 ":" + 1 NULL byte
3406            char IPAddr[47];    // Max IP address len: 46 bytes (IPv6) + 1 NULL byte
3407            if (cnt != 5)
3408            {
3409                LogMsg("mDNSSendWakeOnResolve: ERROR!! Malformed Ethernet address %##s, cnt %d", q->qname.c, cnt);
3410                return;
3411            }
3412            if ((i - 1) > (int) (sizeof(EthAddr) - 1))
3413            {
3414                LogMsg("mDNSSendWakeOnResolve: ERROR!! Malformed Ethernet address %##s, length %d", q->qname.c, i - 1);
3415                return;
3416            }
3417            if ((len - i) > (int)(sizeof(IPAddr) - 1))
3418            {
3419                LogMsg("mDNSSendWakeOnResolve: ERROR!! Malformed IP address %##s, length %d", q->qname.c, len - i);
3420                return;
3421            }
3422            mDNSPlatformMemCopy(EthAddr, &d->c[1], i - 1);
3423            EthAddr[i - 1] = 0;
3424            mDNSPlatformMemCopy(IPAddr, &d->c[i + 1], len - i);
3425            IPAddr[len - i] = 0;
3426            m->mDNSStats.WakeOnResolves++;
3427            mDNSPlatformSendWakeupPacket(InterfaceID, EthAddr, IPAddr, InitialWakeOnResolveCount - q->WakeOnResolveCount);
3428            return;
3429        }
3430        else if (d->c[i] == ':')
3431            cnt++;
3432    }
3433    LogMsg("mDNSSendWakeOnResolve: ERROR!! Malformed WakeOnResolve name %##s", q->qname.c);
3434}
3435
3436
3437mDNSlocal mDNSBool AccelerateThisQuery(mDNS *const m, DNSQuestion *q)
3438{
3439    // If more than 90% of the way to the query time, we should unconditionally accelerate it
3440    if (TimeToSendThisQuestion(q, m->timenow + q->ThisQInterval/10))
3441        return(mDNStrue);
3442
3443    // If half-way to next scheduled query time, only accelerate if it will add less than 512 bytes to the packet
3444    if (TimeToSendThisQuestion(q, m->timenow + q->ThisQInterval/2))
3445    {
3446        // We forecast: qname (n) type (2) class (2)
3447        mDNSu32 forecast = (mDNSu32)DomainNameLength(&q->qname) + 4;
3448        const CacheGroup *const cg = CacheGroupForName(m, q->qnamehash, &q->qname);
3449        const CacheRecord *rr;
3450        for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)             // If we have a resource record in our cache,
3451            if (rr->resrec.rdlength <= SmallRecordLimit &&                  // which is small enough to sensibly fit in the packet
3452                SameNameRecordAnswersQuestion(&rr->resrec, q) &&            // which answers our question
3453                rr->TimeRcvd + TicksTTL(rr)/2 - m->timenow >= 0 &&          // and it is less than half-way to expiry
3454                rr->NextRequiredQuery - (m->timenow + q->ThisQInterval) > 0) // and we'll ask at least once again before NextRequiredQuery
3455            {
3456                // We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n)
3457                forecast += 12 + rr->resrec.rdestimate;
3458                if (forecast >= 512) return(mDNSfalse); // If this would add 512 bytes or more to the packet, don't accelerate
3459            }
3460        return(mDNStrue);
3461    }
3462
3463    return(mDNSfalse);
3464}
3465
3466// How Standard Queries are generated:
3467// 1. The Question Section contains the question
3468// 2. The Additional Section contains answers we already know, to suppress duplicate responses
3469
3470// How Probe Queries are generated:
3471// 1. The Question Section contains queries for the name we intend to use, with QType=ANY because
3472// if some other host is already using *any* records with this name, we want to know about it.
3473// 2. The Authority Section contains the proposed values we intend to use for one or more
3474// of our records with that name (analogous to the Update section of DNS Update packets)
3475// because if some other host is probing at the same time, we each want to know what the other is
3476// planning, in order to apply the tie-breaking rule to see who gets to use the name and who doesn't.
3477
3478mDNSlocal void SendQueries(mDNS *const m)
3479{
3480    mDNSu32 slot;
3481    CacheGroup *cg;
3482    CacheRecord *cr;
3483    AuthRecord *ar;
3484    int pktcount = 0;
3485    DNSQuestion *q;
3486    // For explanation of maxExistingQuestionInterval logic, see comments for maxExistingAnnounceInterval
3487    mDNSs32 maxExistingQuestionInterval = 0;
3488    const NetworkInterfaceInfo *intf = GetFirstActiveInterface(m->HostInterfaces);
3489    CacheRecord *KnownAnswerList = mDNSNULL;
3490
3491    // 1. If time for a query, work out what we need to do
3492
3493    // We're expecting to send a query anyway, so see if any expiring cache records are close enough
3494    // to their NextRequiredQuery to be worth batching them together with this one
3495    FORALL_CACHERECORDS(slot, cg, cr)
3496    {
3497        if (cr->CRActiveQuestion && cr->UnansweredQueries < MaxUnansweredQueries)
3498        {
3499            if (m->timenow + TicksTTL(cr)/50 - cr->NextRequiredQuery >= 0)
3500            {
3501                debugf("Sending %d%% cache expiration query for %s", 80 + 5 * cr->UnansweredQueries, CRDisplayString(m, cr));
3502                q = cr->CRActiveQuestion;
3503                ExpireDupSuppressInfoOnInterface(q->DupSuppress, m->timenow - TicksTTL(cr)/20, cr->resrec.InterfaceID);
3504                // For uDNS queries (TargetQID non-zero) we adjust LastQTime,
3505                // and bump UnansweredQueries so that we don't spin trying to send the same cache expiration query repeatedly
3506                if (q->Target.type)
3507                {
3508                    q->SendQNow = mDNSInterfaceMark; // If targeted query, mark it
3509                }
3510                else if (!mDNSOpaque16IsZero(q->TargetQID))
3511                {
3512                    q->LastQTime = m->timenow - q->ThisQInterval;
3513                    cr->UnansweredQueries++;
3514                    m->mDNSStats.CacheRefreshQueries++;
3515                }
3516                else if (q->SendQNow == mDNSNULL)
3517                {
3518                    q->SendQNow = cr->resrec.InterfaceID;
3519                }
3520                else if (q->SendQNow != cr->resrec.InterfaceID)
3521                {
3522                    q->SendQNow = mDNSInterfaceMark;
3523                }
3524
3525                // Indicate that this question was marked for sending
3526                // to update an existing cached answer record.
3527                // The browse throttling logic below uses this to determine
3528                // if the query should be sent.
3529                if (mDNSOpaque16IsZero(q->TargetQID))
3530                    q->CachedAnswerNeedsUpdate = mDNStrue;
3531            }
3532        }
3533    }
3534
3535    // Scan our list of questions to see which:
3536    //     *WideArea*  queries need to be sent
3537    //     *unicast*   queries need to be sent
3538    //     *multicast* queries we're definitely going to send
3539    if (m->CurrentQuestion)
3540        LogMsg("SendQueries ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
3541    m->CurrentQuestion = m->Questions;
3542    while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
3543    {
3544        q = m->CurrentQuestion;
3545        if (q->Target.type && (q->SendQNow || TimeToSendThisQuestion(q, m->timenow)))
3546        {
3547            mDNSu8       *qptr        = m->omsg.data;
3548            const mDNSu8 *const limit = m->omsg.data + sizeof(m->omsg.data);
3549
3550            // 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
3551            if (!q->LocalSocket) q->LocalSocket = mDNSPlatformUDPSocket(zeroIPPort);
3552            if (q->LocalSocket)
3553            {
3554                InitializeDNSMessage(&m->omsg.h, q->TargetQID, QueryFlags);
3555                qptr = putQuestion(&m->omsg, qptr, limit, &q->qname, q->qtype, q->qclass);
3556                mDNSSendDNSMessage(m, &m->omsg, qptr, mDNSInterface_Any, q->LocalSocket, &q->Target, q->TargetPort, mDNSNULL, mDNSNULL, q->UseBackgroundTrafficClass);
3557                q->ThisQInterval    *= QuestionIntervalStep;
3558            }
3559            if (q->ThisQInterval > MaxQuestionInterval)
3560                q->ThisQInterval = MaxQuestionInterval;
3561            q->LastQTime         = m->timenow;
3562            q->LastQTxTime       = m->timenow;
3563            q->RecentAnswerPkts  = 0;
3564            q->SendQNow          = mDNSNULL;
3565            q->ExpectUnicastResp = NonZeroTime(m->timenow);
3566        }
3567        else if (mDNSOpaque16IsZero(q->TargetQID) && !q->Target.type && TimeToSendThisQuestion(q, m->timenow))
3568        {
3569            //LogInfo("Time to send %##s (%s) %d", q->qname.c, DNSTypeName(q->qtype), m->timenow - NextQSendTime(q));
3570            q->SendQNow = mDNSInterfaceMark;        // Mark this question for sending on all interfaces
3571            if (maxExistingQuestionInterval < q->ThisQInterval)
3572                maxExistingQuestionInterval = q->ThisQInterval;
3573        }
3574        // If m->CurrentQuestion wasn't modified out from under us, advance it now
3575        // We can't do this at the start of the loop because uDNS_CheckCurrentQuestion() depends on having
3576        // m->CurrentQuestion point to the right question
3577        if (q == m->CurrentQuestion) m->CurrentQuestion = m->CurrentQuestion->next;
3578    }
3579    while (m->CurrentQuestion)
3580    {
3581        LogInfo("SendQueries question loop 1: Skipping NewQuestion %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
3582        m->CurrentQuestion = m->CurrentQuestion->next;
3583    }
3584    m->CurrentQuestion = mDNSNULL;
3585
3586    // Scan our list of questions
3587    // (a) to see if there are any more that are worth accelerating, and
3588    // (b) to update the state variables for *all* the questions we're going to send
3589    // Note: Don't set NextScheduledQuery until here, because uDNS_CheckCurrentQuestion in the loop above can add new questions to the list,
3590    // which causes NextScheduledQuery to get (incorrectly) set to m->timenow. Setting it here is the right place, because the very
3591    // 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.
3592    m->NextScheduledQuery = m->timenow + FutureTime;
3593    for (q = m->Questions; q && q != m->NewQuestions; q=q->next)
3594    {
3595        if (mDNSOpaque16IsZero(q->TargetQID)
3596            && (q->SendQNow || (!q->Target.type && ActiveQuestion(q) && q->ThisQInterval <= maxExistingQuestionInterval && AccelerateThisQuery(m,q))))
3597        {
3598            // If at least halfway to next query time, advance to next interval
3599            // If less than halfway to next query time, then
3600            // treat this as logically a repeat of the last transmission, without advancing the interval
3601            if (m->timenow - (q->LastQTime + (q->ThisQInterval/2)) >= 0)
3602            {
3603                // If we have reached the answer threshold for this question,
3604                // don't send it again until MaxQuestionInterval unless:
3605                //  one of its cached answers needs to be refreshed,
3606                //  or it's the initial query for a kDNSServiceFlagsThresholdFinder mode browse.
3607                if (q->BrowseThreshold
3608                    && (q->CurrentAnswers >= q->BrowseThreshold)
3609                    && (q->CachedAnswerNeedsUpdate == mDNSfalse)
3610                    && !((q->flags & kDNSServiceFlagsThresholdFinder) && (q->ThisQInterval == InitialQuestionInterval)))
3611                {
3612                    q->SendQNow = mDNSNULL;
3613                    q->ThisQInterval = MaxQuestionInterval;
3614                    q->LastQTime = m->timenow;
3615                    q->RequestUnicast = 0;
3616                    LogInfo("SendQueries: (%s) %##s reached threshold of %d answers",
3617                         DNSTypeName(q->qtype), q->qname.c, q->BrowseThreshold);
3618                }
3619                else
3620                {
3621                    // Mark this question for sending on all interfaces
3622                    q->SendQNow = mDNSInterfaceMark;
3623                    q->ThisQInterval *= QuestionIntervalStep;
3624                }
3625
3626                debugf("SendQueries: %##s (%s) next interval %d seconds RequestUnicast = %d",
3627                       q->qname.c, DNSTypeName(q->qtype), q->ThisQInterval / InitialQuestionInterval, q->RequestUnicast);
3628
3629                if (q->ThisQInterval > MaxQuestionInterval)
3630                {
3631                    q->ThisQInterval = MaxQuestionInterval;
3632                }
3633                else if (mDNSOpaque16IsZero(q->TargetQID) && q->InterfaceID &&
3634                         q->CurrentAnswers == 0 && q->ThisQInterval == InitialQuestionInterval * QuestionIntervalStep3 && !q->RequestUnicast &&
3635                         !(RRTypeIsAddressType(q->qtype) && CacheHasAddressTypeForName(m, &q->qname, q->qnamehash)))
3636                {
3637                    // Generally don't need to log this.
3638                    // It's not especially noteworthy if a query finds no results -- this usually happens for domain
3639                    // enumeration queries in the LL subdomain (e.g. "db._dns-sd._udp.0.0.254.169.in-addr.arpa")
3640                    // and when there simply happen to be no instances of the service the client is looking
3641                    // for (e.g. iTunes is set to look for RAOP devices, and the current network has none).
3642                    debugf("SendQueries: Zero current answers for %##s (%s); will reconfirm antecedents",
3643                           q->qname.c, DNSTypeName(q->qtype));
3644                    // Sending third query, and no answers yet; time to begin doubting the source
3645                    ReconfirmAntecedents(m, &q->qname, q->qnamehash, q->InterfaceID, 0);
3646                }
3647            }
3648
3649            // Mark for sending. (If no active interfaces, then don't even try.)
3650            q->SendOnAll = (q->SendQNow == mDNSInterfaceMark);
3651            if (q->SendOnAll)
3652            {
3653                q->SendQNow  = !intf ? mDNSNULL : (q->InterfaceID) ? q->InterfaceID : intf->InterfaceID;
3654                q->LastQTime = m->timenow;
3655            }
3656
3657            // If we recorded a duplicate suppression for this question less than half an interval ago,
3658            // then we consider it recent enough that we don't need to do an identical query ourselves.
3659            ExpireDupSuppressInfo(q->DupSuppress, m->timenow - q->ThisQInterval/2);
3660
3661            q->LastQTxTime      = m->timenow;
3662            q->RecentAnswerPkts = 0;
3663            if (q->RequestUnicast) q->RequestUnicast--;
3664        }
3665        // For all questions (not just the ones we're sending) check what the next scheduled event will be
3666        // We don't need to consider NewQuestions here because for those we'll set m->NextScheduledQuery in AnswerNewQuestion
3667        SetNextQueryTime(m,q);
3668    }
3669
3670    // 2. Scan our authoritative RR list to see what probes we might need to send
3671
3672    m->NextScheduledProbe = m->timenow + FutureTime;
3673
3674    if (m->CurrentRecord)
3675        LogMsg("SendQueries ERROR m->CurrentRecord already set %s", ARDisplayString(m, m->CurrentRecord));
3676    m->CurrentRecord = m->ResourceRecords;
3677    while (m->CurrentRecord)
3678    {
3679        ar = m->CurrentRecord;
3680        m->CurrentRecord = ar->next;
3681        if (!AuthRecord_uDNS(ar) && ar->resrec.RecordType == kDNSRecordTypeUnique)  // For all records that are still probing...
3682        {
3683            // 1. If it's not reached its probe time, just make sure we update m->NextScheduledProbe correctly
3684            if (m->timenow - (ar->LastAPTime + ar->ThisAPInterval) < 0)
3685            {
3686                SetNextAnnounceProbeTime(m, ar);
3687            }
3688            // 2. else, if it has reached its probe time, mark it for sending and then update m->NextScheduledProbe correctly
3689            else if (ar->ProbeCount)
3690            {
3691                if (ar->AddressProxy.type == mDNSAddrType_IPv4)
3692                {
3693                    // There's a problem here. If a host is waking up, and we probe to see if it responds, then
3694                    // it will see those ARP probes as signalling intent to use the address, so it picks a different one.
3695                    // A more benign way to find out if a host is responding to ARPs might be send a standard ARP *request*
3696                    // (using our sender IP address) instead of an ARP *probe* (using all-zero sender IP address).
3697                    // A similar concern may apply to the NDP Probe too. -- SC
3698                    LogSPS("SendQueries ARP Probe %d %s %s", ar->ProbeCount, InterfaceNameForID(m, ar->resrec.InterfaceID), ARDisplayString(m,ar));
3699                    SendARP(m, 1, ar, &zerov4Addr, &zeroEthAddr, &ar->AddressProxy.ip.v4, &ar->WakeUp.IMAC);
3700                }
3701                else if (ar->AddressProxy.type == mDNSAddrType_IPv6)
3702                {
3703                    LogSPS("SendQueries NDP Probe %d %s %s", ar->ProbeCount, InterfaceNameForID(m, ar->resrec.InterfaceID), ARDisplayString(m,ar));
3704                    // IPv6 source = zero
3705                    // No target hardware address
3706                    // IPv6 target address is address we're probing
3707                    // Ethernet destination address is Ethernet interface address of the Sleep Proxy client we're probing
3708                    SendNDP(m, NDP_Sol, 0, ar, &zerov6Addr, mDNSNULL, &ar->AddressProxy.ip.v6, &ar->WakeUp.IMAC);
3709                }
3710                // Mark for sending. (If no active interfaces, then don't even try.)
3711                ar->SendRNow   = (!intf || ar->WakeUp.HMAC.l[0]) ? mDNSNULL : ar->resrec.InterfaceID ? ar->resrec.InterfaceID : intf->InterfaceID;
3712                ar->LastAPTime = m->timenow;
3713                // When we have a late conflict that resets a record to probing state we use a special marker value greater
3714                // than DefaultProbeCountForTypeUnique. Here we detect that state and reset ar->ProbeCount back to the right value.
3715                if (ar->ProbeCount > DefaultProbeCountForTypeUnique)
3716                    ar->ProbeCount = DefaultProbeCountForTypeUnique;
3717                ar->ProbeCount--;
3718                SetNextAnnounceProbeTime(m, ar);
3719                if (ar->ProbeCount == 0)
3720                {
3721                    // If this is the last probe for this record, then see if we have any matching records
3722                    // on our duplicate list which should similarly have their ProbeCount cleared to zero...
3723                    AuthRecord *r2;
3724                    for (r2 = m->DuplicateRecords; r2; r2=r2->next)
3725                        if (r2->resrec.RecordType == kDNSRecordTypeUnique && RecordIsLocalDuplicate(r2, ar))
3726                            r2->ProbeCount = 0;
3727                    // ... then acknowledge this record to the client.
3728                    // We do this optimistically, just as we're about to send the third probe.
3729                    // This helps clients that both advertise and browse, and want to filter themselves
3730                    // from the browse results list, because it helps ensure that the registration
3731                    // confirmation will be delivered 1/4 second *before* the browse "add" event.
3732                    // A potential downside is that we could deliver a registration confirmation and then find out
3733                    // moments later that there's a name conflict, but applications have to be prepared to handle
3734                    // late conflicts anyway (e.g. on connection of network cable, etc.), so this is nothing new.
3735                    if (!ar->Acknowledged) AcknowledgeRecord(m, ar);
3736                }
3737            }
3738            // else, if it has now finished probing, move it to state Verified,
3739            // and update m->NextScheduledResponse so it will be announced
3740            else
3741            {
3742                if (!ar->Acknowledged) AcknowledgeRecord(m, ar);    // Defensive, just in case it got missed somehow
3743                ar->resrec.RecordType     = kDNSRecordTypeVerified;
3744                ar->ThisAPInterval = DefaultAnnounceIntervalForTypeUnique;
3745                ar->LastAPTime     = m->timenow - DefaultAnnounceIntervalForTypeUnique;
3746                SetNextAnnounceProbeTime(m, ar);
3747            }
3748        }
3749    }
3750    m->CurrentRecord = m->DuplicateRecords;
3751    while (m->CurrentRecord)
3752    {
3753        ar = m->CurrentRecord;
3754        m->CurrentRecord = ar->next;
3755        if (ar->resrec.RecordType == kDNSRecordTypeUnique && ar->ProbeCount == 0 && !ar->Acknowledged)
3756            AcknowledgeRecord(m, ar);
3757    }
3758
3759    // 3. Now we know which queries and probes we're sending,
3760    // go through our interface list sending the appropriate queries on each interface
3761    while (intf)
3762    {
3763        int OwnerRecordSpace = (m->AnnounceOwner && intf->MAC.l[0]) ? DNSOpt_Header_Space + DNSOpt_Owner_Space(&m->PrimaryMAC, &intf->MAC) : 0;
3764        int TraceRecordSpace = (mDNS_McastTracingEnabled && MDNS_TRACER) ? DNSOpt_Header_Space + DNSOpt_TraceData_Space : 0;
3765        mDNSu8 *queryptr = m->omsg.data;
3766        mDNSBool useBackgroundTrafficClass = mDNSfalse;    // set if we should use background traffic class
3767
3768        InitializeDNSMessage(&m->omsg.h, zeroID, QueryFlags);
3769        if (KnownAnswerList) verbosedebugf("SendQueries:   KnownAnswerList set... Will continue from previous packet");
3770        if (!KnownAnswerList)
3771        {
3772            // Start a new known-answer list
3773            CacheRecord **kalistptr = &KnownAnswerList;
3774            mDNSu32 answerforecast = OwnerRecordSpace + TraceRecordSpace;  // Start by assuming we'll need at least enough space to put the Owner+Tracer Option
3775
3776            // Put query questions in this packet
3777            for (q = m->Questions; q && q != m->NewQuestions; q=q->next)
3778            {
3779                if (mDNSOpaque16IsZero(q->TargetQID) && (q->SendQNow == intf->InterfaceID))
3780                {
3781                    mDNSBool Suppress = mDNSfalse;
3782                    debugf("SendQueries: %s question for %##s (%s) at %d forecast total %d",
3783                           SuppressOnThisInterface(q->DupSuppress, intf) ? "Suppressing" : "Putting    ",
3784                           q->qname.c, DNSTypeName(q->qtype), queryptr - m->omsg.data, queryptr + answerforecast - m->omsg.data);
3785
3786                    // If interface is P2P type, verify that query should be sent over it.
3787                    if (!mDNSPlatformValidQuestionForInterface(q, intf))
3788                    {
3789                        q->SendQNow = (q->InterfaceID || !q->SendOnAll) ? mDNSNULL : GetNextActiveInterfaceID(intf);
3790                    }
3791                    // If we're suppressing this question, or we successfully put it, update its SendQNow state
3792                    else if ((Suppress = SuppressOnThisInterface(q->DupSuppress, intf)) ||
3793                        BuildQuestion(m, intf, &m->omsg, &queryptr, q, &kalistptr, &answerforecast))
3794                    {
3795                        // We successfully added the question to the packet. Make sure that
3796                        // we also send the NSEC3 record if required. BuildQuestion accounted for
3797                        // the space.
3798                        //
3799                        // Note: We don't suppress anonymous questions and hence Suppress should always
3800                        // be zero.
3801
3802                        if (Suppress)
3803                            m->mDNSStats.DupQuerySuppressions++;
3804
3805                        if (!Suppress && q->AnonInfo)
3806                        {
3807                            debugf("SendQueries: marking for question %##s, Suppress %d", q->qname.c, Suppress);
3808                            q->AnonInfo->SendNow = intf->InterfaceID;
3809                        }
3810                        q->SendQNow = (q->InterfaceID || !q->SendOnAll) ? mDNSNULL : GetNextActiveInterfaceID(intf);
3811                        if (q->WakeOnResolveCount)
3812                        {
3813                            mDNSSendWakeOnResolve(m, q);
3814                            q->WakeOnResolveCount--;
3815                        }
3816
3817                        // use background traffic class if any included question requires it
3818                        if (q->UseBackgroundTrafficClass)
3819                        {
3820                            useBackgroundTrafficClass = mDNStrue;
3821                        }
3822                    }
3823                }
3824            }
3825
3826            // Put probe questions in this packet
3827            for (ar = m->ResourceRecords; ar; ar=ar->next)
3828            {
3829                if (ar->SendRNow != intf->InterfaceID)
3830                    continue;
3831
3832                // If interface is a P2P variant, verify that the probe should be sent over it.
3833                if (!mDNSPlatformValidRecordForInterface(ar, intf->InterfaceID))
3834                {
3835                    ar->SendRNow = (ar->resrec.InterfaceID) ? mDNSNULL : GetNextActiveInterfaceID(intf);
3836                    ar->IncludeInProbe = mDNSfalse;
3837                }
3838                else
3839                {
3840                    mDNSBool ucast = (ar->ProbeCount >= DefaultProbeCountForTypeUnique-1) && m->CanReceiveUnicastOn5353 && intf->SupportsUnicastMDNSResponse;
3841                    mDNSu16 ucbit = (mDNSu16)(ucast ? kDNSQClass_UnicastResponse : 0);
3842                    const mDNSu8 *const limit = m->omsg.data + (m->omsg.h.numQuestions ? NormalMaxDNSMessageData : AbsoluteMaxDNSMessageData);
3843                    // We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n)
3844                    mDNSu32 forecast = answerforecast + 12 + ar->resrec.rdestimate;
3845                    mDNSBool putProbe = mDNStrue;
3846                    mDNSu16 qclass = ar->resrec.rrclass | ucbit;
3847
3848                    {// Determine if this probe question is already in packet's dns message
3849                        const mDNSu8 *questionptr = m->omsg.data;
3850                        DNSQuestion question;
3851                        mDNSu16 n;
3852                        for (n = 0; n < m->omsg.h.numQuestions && questionptr; n++)
3853                        {
3854                            questionptr = getQuestion(&m->omsg, questionptr, limit, mDNSInterface_Any, &question);
3855                            if (questionptr && (question.qtype == kDNSQType_ANY) && (question.qclass == qclass) &&
3856                                (question.qnamehash == ar->resrec.namehash) && SameDomainName(&question.qname, ar->resrec.name))
3857                            {
3858                                putProbe = mDNSfalse;  // set to false if already in message
3859                                break;
3860                            }
3861                        }
3862                    }
3863
3864                    if (putProbe)
3865                    {
3866                        mDNSu8 *newptr = putQuestion(&m->omsg, queryptr, limit - forecast, ar->resrec.name, kDNSQType_ANY, qclass);
3867                        if (newptr)
3868                        {
3869                            queryptr       = newptr;
3870                            answerforecast = forecast;
3871                            ar->SendRNow = (ar->resrec.InterfaceID) ? mDNSNULL : GetNextActiveInterfaceID(intf);
3872                            ar->IncludeInProbe = mDNStrue;
3873                            verbosedebugf("SendQueries:   Put Question %##s (%s) probecount %d InterfaceID= %d %d %d",
3874                                      ar->resrec.name->c, DNSTypeName(ar->resrec.rrtype), ar->ProbeCount, ar->resrec.InterfaceID, ar->resrec.rdestimate, answerforecast);
3875                        }
3876                    }
3877                    else
3878                    {
3879                        ar->SendRNow = (ar->resrec.InterfaceID) ? mDNSNULL : GetNextActiveInterfaceID(intf);
3880                        ar->IncludeInProbe = mDNStrue;
3881                    }
3882                }
3883            }
3884        }
3885
3886        // Put our known answer list (either new one from this question or questions, or remainder of old one from last time)
3887        while (KnownAnswerList)
3888        {
3889            CacheRecord *ka = KnownAnswerList;
3890            mDNSu32 SecsSinceRcvd = ((mDNSu32)(m->timenow - ka->TimeRcvd)) / mDNSPlatformOneSecond;
3891            mDNSu8 *newptr = PutResourceRecordTTLWithLimit(&m->omsg, queryptr, &m->omsg.h.numAnswers, &ka->resrec, ka->resrec.rroriginalttl - SecsSinceRcvd,
3892                                                           m->omsg.data + NormalMaxDNSMessageData - OwnerRecordSpace - TraceRecordSpace);
3893            if (newptr)
3894            {
3895                verbosedebugf("SendQueries:   Put %##s (%s) at %d - %d",
3896                              ka->resrec.name->c, DNSTypeName(ka->resrec.rrtype), queryptr - m->omsg.data, newptr - m->omsg.data);
3897                queryptr = newptr;
3898                KnownAnswerList = ka->NextInKAList;
3899                ka->NextInKAList = mDNSNULL;
3900            }
3901            else
3902            {
3903                // If we ran out of space and we have more than one question in the packet, that's an error --
3904                // we shouldn't have put more than one question if there was a risk of us running out of space.
3905                if (m->omsg.h.numQuestions > 1)
3906                    LogMsg("SendQueries:   Put %d answers; No more space for known answers", m->omsg.h.numAnswers);
3907                m->omsg.h.flags.b[0] |= kDNSFlag0_TC;
3908                break;
3909            }
3910        }
3911
3912        for (ar = m->ResourceRecords; ar; ar=ar->next)
3913        {
3914            if (ar->IncludeInProbe)
3915            {
3916                mDNSu8 *newptr = PutResourceRecord(&m->omsg, queryptr, &m->omsg.h.numAuthorities, &ar->resrec);
3917                ar->IncludeInProbe = mDNSfalse;
3918                if (newptr) queryptr = newptr;
3919                else LogMsg("SendQueries:   How did we fail to have space for the Update record %s", ARDisplayString(m,ar));
3920            }
3921        }
3922
3923        for (q = m->Questions; q; q = q->next)
3924        {
3925            if (q->AnonInfo && q->AnonInfo->SendNow == intf->InterfaceID)
3926            {
3927                mDNSu8 *newptr = PutResourceRecord(&m->omsg, queryptr, &m->omsg.h.numAuthorities, q->AnonInfo->nsec3RR);
3928                if (newptr)
3929                {
3930                    debugf("SendQueries: Added NSEC3 record %s on InterfaceID %p", RRDisplayString(m, q->AnonInfo->nsec3RR), intf->InterfaceID);
3931                    queryptr = newptr;
3932                }
3933                else
3934                {
3935                    LogMsg("SendQueries: ERROR!! Cannot add NSEC3 record %s on InterfaceID %p", RRDisplayString(m, q->AnonInfo->nsec3RR), intf->InterfaceID);
3936                }
3937                q->AnonInfo->SendNow = mDNSNULL;
3938            }
3939        }
3940
3941        if (queryptr > m->omsg.data)
3942        {
3943            // If we have data to send, add OWNER/TRACER/OWNER+TRACER option if necessary, then send packet
3944            if (OwnerRecordSpace || TraceRecordSpace)
3945            {
3946                AuthRecord opt;
3947                mDNS_SetupResourceRecord(&opt, mDNSNULL, mDNSInterface_Any, kDNSType_OPT, kStandardTTL, kDNSRecordTypeKnownUnique, AuthRecordAny, mDNSNULL, mDNSNULL);
3948                opt.resrec.rrclass    = NormalMaxDNSMessageData;
3949                opt.resrec.rdlength   = sizeof(rdataOPT);
3950                opt.resrec.rdestimate = sizeof(rdataOPT);
3951                if (OwnerRecordSpace && TraceRecordSpace)
3952                {
3953                    opt.resrec.rdlength   += sizeof(rdataOPT);  // Two options in this OPT record
3954                    opt.resrec.rdestimate += sizeof(rdataOPT);
3955                    SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[0]);
3956                    SetupTracerOpt(m, &opt.resrec.rdata->u.opt[1]);
3957                }
3958                else if (OwnerRecordSpace)
3959                {
3960                    SetupOwnerOpt(m, intf, &opt.resrec.rdata->u.opt[0]);
3961                }
3962                else if (TraceRecordSpace)
3963                {
3964                    SetupTracerOpt(m, &opt.resrec.rdata->u.opt[0]);
3965                }
3966                queryptr = PutResourceRecordTTLWithLimit(&m->omsg, queryptr, &m->omsg.h.numAdditionals,
3967                                                         &opt.resrec, opt.resrec.rroriginalttl, m->omsg.data + AbsoluteMaxDNSMessageData);
3968                if (!queryptr)
3969                {
3970                    LogMsg("SendQueries: How did we fail to have space for %s %s OPT record (%d/%d/%d/%d) %s", OwnerRecordSpace ? "OWNER" : "", TraceRecordSpace ? "TRACER" : "",
3971                           m->omsg.h.numQuestions, m->omsg.h.numAnswers, m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt));
3972                }
3973                if (queryptr > m->omsg.data + NormalMaxDNSMessageData)
3974                {
3975                    if (m->omsg.h.numQuestions != 1 || m->omsg.h.numAnswers != 0 || m->omsg.h.numAuthorities != 1 || m->omsg.h.numAdditionals != 1)
3976                        LogMsg("SendQueries: Why did we generate oversized packet with %s %s OPT record %p %p %p (%d/%d/%d/%d) %s", OwnerRecordSpace ? "OWNER" : "",
3977                                TraceRecordSpace ? "TRACER" : "", m->omsg.data, m->omsg.data + NormalMaxDNSMessageData, queryptr, m->omsg.h.numQuestions, m->omsg.h.numAnswers,
3978                                m->omsg.h.numAuthorities, m->omsg.h.numAdditionals, ARDisplayString(m, &opt));
3979                }
3980            }
3981
3982            if ((m->omsg.h.flags.b[0] & kDNSFlag0_TC) && m->omsg.h.numQuestions > 1)
3983                LogMsg("SendQueries: Should not have more than one question (%d) in a truncated packet", m->omsg.h.numQuestions);
3984            debugf("SendQueries:   Sending %d Question%s %d Answer%s %d Update%s on %p",
3985                   m->omsg.h.numQuestions,   m->omsg.h.numQuestions   == 1 ? "" : "s",
3986                   m->omsg.h.numAnswers,     m->omsg.h.numAnswers     == 1 ? "" : "s",
3987                   m->omsg.h.numAuthorities, m->omsg.h.numAuthorities == 1 ? "" : "s", intf->InterfaceID);
3988            if (intf->IPv4Available) mDNSSendDNSMessage(m, &m->omsg, queryptr, intf->InterfaceID, mDNSNULL, &AllDNSLinkGroup_v4, MulticastDNSPort, mDNSNULL, mDNSNULL, useBackgroundTrafficClass);
3989            if (intf->IPv6Available) mDNSSendDNSMessage(m, &m->omsg, queryptr, intf->InterfaceID, mDNSNULL, &AllDNSLinkGroup_v6, MulticastDNSPort, mDNSNULL, mDNSNULL, useBackgroundTrafficClass);
3990            if (!m->SuppressSending) m->SuppressSending = NonZeroTime(m->timenow + (mDNSPlatformOneSecond+9)/10);
3991            if (++pktcount >= 1000)
3992            { LogMsg("SendQueries exceeded loop limit %d: giving up", pktcount); break; }
3993            // There might be more records left in the known answer list, or more questions to send
3994            // on this interface, so go around one more time and try again.
3995        }
3996        else    // Nothing more to send on this interface; go to next
3997        {
3998            const NetworkInterfaceInfo *next = GetFirstActiveInterface(intf->next);
3999            #if MDNS_DEBUGMSGS && 0
4000            const char *const msg = next ? "SendQueries:   Nothing more on %p; moving to %p" : "SendQueries:   Nothing more on %p";
4001            debugf(msg, intf, next);
4002            #endif
4003            intf = next;
4004        }
4005    }
4006
4007    // 4. Final housekeeping
4008
4009    // 4a. Debugging check: Make sure we announced all our records
4010    for (ar = m->ResourceRecords; ar; ar=ar->next)
4011        if (ar->SendRNow)
4012        {
4013            if (ar->ARType != AuthRecordLocalOnly && ar->ARType != AuthRecordP2P)
4014                LogInfo("SendQueries: No active interface %d to send probe: %d %s",
4015                    (uint32_t)ar->SendRNow, (uint32_t)ar->resrec.InterfaceID, ARDisplayString(m, ar));
4016            ar->SendRNow = mDNSNULL;
4017        }
4018
4019    // 4b. When we have lingering cache records that we're keeping around for a few seconds in the hope
4020    // that their interface which went away might come back again, the logic will want to send queries
4021    // for those records, but we can't because their interface isn't here any more, so to keep the
4022    // state machine ticking over we just pretend we did so.
4023    // If the interface does not come back in time, the cache record will expire naturally
4024    FORALL_CACHERECORDS(slot, cg, cr)
4025    {
4026        if (cr->CRActiveQuestion && cr->UnansweredQueries < MaxUnansweredQueries)
4027        {
4028            if (m->timenow + TicksTTL(cr)/50 - cr->NextRequiredQuery >= 0)
4029            {
4030                cr->UnansweredQueries++;
4031                cr->CRActiveQuestion->SendQNow = mDNSNULL;
4032                SetNextCacheCheckTimeForRecord(m, cr);
4033            }
4034        }
4035    }
4036
4037    // 4c. Debugging check: Make sure we sent all our planned questions
4038    // Do this AFTER the lingering cache records check above, because that will prevent spurious warnings for questions
4039    // we legitimately couldn't send because the interface is no longer available
4040    for (q = m->Questions; q; q=q->next)
4041    {
4042        if (q->SendQNow)
4043        {
4044            DNSQuestion *x;
4045            for (x = m->NewQuestions; x; x=x->next) if (x == q) break;  // Check if this question is a NewQuestion
4046            // There will not be an active interface for questions applied to mDNSInterface_BLE
4047            // so don't log the warning in that case.
4048            if (q->InterfaceID != mDNSInterface_BLE)
4049                LogInfo("SendQueries: No active interface %d to send %s question: %d %##s (%s)",
4050                    (uint32_t)q->SendQNow, x ? "new" : "old", (uint32_t)q->InterfaceID, q->qname.c, DNSTypeName(q->qtype));
4051            q->SendQNow = mDNSNULL;
4052        }
4053        q->CachedAnswerNeedsUpdate = mDNSfalse;
4054    }
4055}
4056
4057mDNSlocal void SendWakeup(mDNS *const m, mDNSInterfaceID InterfaceID, mDNSEthAddr *EthAddr, mDNSOpaque48 *password, mDNSBool unicastOnly)
4058{
4059    int i, j;
4060
4061    mDNSu8 *ptr = m->omsg.data;
4062    NetworkInterfaceInfo *intf = FirstInterfaceForID(m, InterfaceID);
4063    if (!intf) { LogMsg("SendARP: No interface with InterfaceID %p found", InterfaceID); return; }
4064
4065    // 0x00 Destination address
4066    for (i=0; i<6; i++) *ptr++ = EthAddr->b[i];
4067
4068    // 0x06 Source address (Note: Since we don't currently set the BIOCSHDRCMPLT option, BPF will fill in the real interface address for us)
4069    for (i=0; i<6; i++) *ptr++ = intf->MAC.b[0];
4070
4071    // 0x0C Ethertype (0x0842)
4072    *ptr++ = 0x08;
4073    *ptr++ = 0x42;
4074
4075    // 0x0E Wakeup sync sequence
4076    for (i=0; i<6; i++) *ptr++ = 0xFF;
4077
4078    // 0x14 Wakeup data
4079    for (j=0; j<16; j++) for (i=0; i<6; i++) *ptr++ = EthAddr->b[i];
4080
4081    // 0x74 Password
4082    for (i=0; i<6; i++) *ptr++ = password->b[i];
4083
4084    mDNSPlatformSendRawPacket(m->omsg.data, ptr, InterfaceID);
4085
4086    if (!unicastOnly)
4087    {
4088        // For Ethernet switches that don't flood-foward packets with unknown unicast destination MAC addresses,
4089        // broadcast is the only reliable way to get a wakeup packet to the intended target machine.
4090        // For 802.11 WPA networks, where a sleeping target machine may have missed a broadcast/multicast
4091        // key rotation, unicast is the only way to get a wakeup packet to the intended target machine.
4092        // So, we send one of each, unicast first, then broadcast second.
4093        for (i=0; i<6; i++) m->omsg.data[i] = 0xFF;
4094        mDNSPlatformSendRawPacket(m->omsg.data, ptr, InterfaceID);
4095    }
4096}
4097
4098// ***************************************************************************
4099#if COMPILER_LIKES_PRAGMA_MARK
4100#pragma mark -
4101#pragma mark - RR List Management & Task Management
4102#endif
4103
4104// Whenever a question is answered, reset its state so that we don't query
4105// the network repeatedly. This happens first time when we answer the question and
4106// and later when we refresh the cache.
4107mDNSlocal void ResetQuestionState(mDNS *const m, DNSQuestion *q)
4108{
4109    q->LastQTime        = m->timenow;
4110    q->LastQTxTime      = m->timenow;
4111    q->RecentAnswerPkts = 0;
4112    q->ThisQInterval    = MaxQuestionInterval;
4113    q->RequestUnicast   = 0;
4114    // Reset unansweredQueries so that we don't penalize this server later when we
4115    // start sending queries when the cache expires.
4116    q->unansweredQueries = 0;
4117    debugf("ResetQuestionState: Set MaxQuestionInterval for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
4118}
4119
4120// Note: AnswerCurrentQuestionWithResourceRecord can call a user callback, which may change the record list and/or question list.
4121// Any code walking either list must use the m->CurrentQuestion (and possibly m->CurrentRecord) mechanism to protect against this.
4122// In fact, to enforce this, the routine will *only* answer the question currently pointed to by m->CurrentQuestion,
4123// which will be auto-advanced (possibly to NULL) if the client callback cancels the question.
4124mDNSexport void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheRecord *const rr, const QC_result AddRecord)
4125{
4126    DNSQuestion *const q = m->CurrentQuestion;
4127    const mDNSBool followcname = FollowCNAME(q, &rr->resrec, AddRecord);
4128
4129    verbosedebugf("AnswerCurrentQuestionWithResourceRecord:%4lu %s (%s) TTL %d %s",
4130                  q->CurrentAnswers, AddRecord ? "Add" : "Rmv", MortalityDisplayString(rr->resrec.mortality),
4131                  rr->resrec.rroriginalttl, CRDisplayString(m, rr));
4132
4133    // When the response for the question was validated, the entire rrset was validated. If we deliver
4134    // a RMV for a single record in the rrset, we invalidate the response. If we deliver another add
4135    // in the future, we will do the revalidation again.
4136    //
4137    // Also, if we deliver an ADD for a negative cache record and it has no NSEC/NSEC3, the ValidationStatus needs
4138    // to be reset. This happens normally when we deliver a "secure" negative response followed by an insecure
4139    // negative response which can happen e.g., when disconnecting from network that leads to a negative response
4140    // due to no DNS servers. As we don't deliver RMVs for negative responses that were delivered before, we need
4141    // to do it on the next ADD of a negative cache record. This ADD could be the result of a timeout, no DNS servers
4142    // etc. in which case we need to reset the state to make sure we don't deliver them as secure. If this is
4143    // a real negative response, we would reset the state here and validate the results at the end of this function.
4144    // or the real response again if we purge the cache.
4145    if (q->ValidationRequired && ((AddRecord == QC_rmv) ||
4146        (rr->resrec.RecordType == kDNSRecordTypePacketNegative && (AddRecord == QC_add))))
4147    {
4148        q->ValidationStatus = 0;
4149        q->ValidationState = DNSSECValRequired;
4150    }
4151
4152    // Normally we don't send out the unicast query if we have answered using our local only auth records e.g., /etc/hosts.
4153    // But if the query for "A" record has a local answer but query for "AAAA" record has no local answer, we might
4154    // send the AAAA query out which will come back with CNAME and will also answer the "A" query. To prevent that,
4155    // we check to see if that query already has a unique local answer.
4156    if (q->LOAddressAnswers)
4157    {
4158        LogInfo("AnswerCurrentQuestionWithResourceRecord: Question %p %##s (%s) not answering with record %s due to "
4159                "LOAddressAnswers %d", q, q->qname.c, DNSTypeName(q->qtype), ARDisplayString(m, rr),
4160                q->LOAddressAnswers);
4161        return;
4162    }
4163
4164    if (QuerySuppressed(q))
4165    {
4166        // If the query is suppressed, then we don't want to answer from the cache. But if this query is
4167        // supposed to time out, we still want to callback the clients. We do this only for TimeoutQuestions
4168        // that are timing out, which we know are answered with negative cache record when timing out.
4169        if (!q->TimeoutQuestion || rr->resrec.RecordType != kDNSRecordTypePacketNegative || (m->timenow - q->StopTime < 0))
4170            return;
4171    }
4172
4173    //  Set the record to immortal if appropriate
4174    if (AddRecord == QC_add && Question_uDNS(q) && rr->resrec.RecordType != kDNSRecordTypePacketNegative &&
4175        q->allowExpired != AllowExpired_None && rr->resrec.mortality == Mortality_Mortal ) rr->resrec.mortality = Mortality_Immortal; // Update a non-expired cache record to immortal if appropriate
4176
4177#if AWD_METRICS
4178    if ((AddRecord == QC_add) && Question_uDNS(q) && !followcname)
4179    {
4180        const domainname *  queryName;
4181        mDNSu32             responseLatencyMs;
4182        mDNSBool            isForCellular;
4183
4184        queryName = q->metrics.originalQName ? q->metrics.originalQName : &q->qname;
4185        isForCellular = (q->qDNSServer && q->qDNSServer->cellIntf);
4186        if (!q->metrics.answered)
4187        {
4188            if (q->metrics.querySendCount > 0)
4189            {
4190                responseLatencyMs = ((m->timenow - q->metrics.firstQueryTime) * 1000) / mDNSPlatformOneSecond;
4191            }
4192            else
4193            {
4194                responseLatencyMs = 0;
4195            }
4196
4197            MetricsUpdateDNSQueryStats(queryName, q->qtype, &rr->resrec, q->metrics.querySendCount, q->metrics.expiredAnswerState, responseLatencyMs, isForCellular);
4198            q->metrics.answered = mDNStrue;
4199        }
4200        if (q->metrics.querySendCount > 0)
4201        {
4202            MetricsUpdateDNSResolveStats(queryName, &rr->resrec, isForCellular);
4203        }
4204    }
4205#endif
4206    // Note: Use caution here. In the case of records with rr->DelayDelivery set, AnswerCurrentQuestionWithResourceRecord(... mDNStrue)
4207    // may be called twice, once when the record is received, and again when it's time to notify local clients.
4208    // If any counters or similar are added here, care must be taken to ensure that they are not double-incremented by this.
4209
4210    if (AddRecord == QC_add && !q->DuplicateOf && rr->CRActiveQuestion != q && rr->resrec.mortality != Mortality_Ghost)
4211    {
4212        if (!rr->CRActiveQuestion) m->rrcache_active++; // If not previously active, increment rrcache_active count
4213        debugf("AnswerCurrentQuestionWithResourceRecord: Updating CRActiveQuestion from %p to %p for cache record %s, CurrentAnswer %d",
4214               rr->CRActiveQuestion, q, CRDisplayString(m,rr), q->CurrentAnswers);
4215        rr->CRActiveQuestion = q;                       // We know q is non-null
4216        SetNextCacheCheckTimeForRecord(m, rr);
4217    }
4218
4219    // If this is:
4220    // (a) a no-cache add, where we've already done at least one 'QM' query, or
4221    // (b) a normal add, where we have at least one unique-type answer,
4222    // then there's no need to keep polling the network.
4223    // (If we have an answer in the cache, then we'll automatically ask again in time to stop it expiring.)
4224    // We do this for mDNS questions and uDNS one-shot questions, but not for
4225    // uDNS LongLived questions, because that would mess up our LLQ lease renewal timing.
4226    if ((AddRecord == QC_addnocache && !q->RequestUnicast) ||
4227        (AddRecord == QC_add && (q->ExpectUnique || (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask))))
4228        if (ActiveQuestion(q) && (mDNSOpaque16IsZero(q->TargetQID) || !q->LongLived))
4229        {
4230            ResetQuestionState(m, q);
4231        }
4232
4233    if (rr->DelayDelivery) return;      // We'll come back later when CacheRecordDeferredAdd() calls us
4234
4235#if USE_DNS64
4236    // If DNS64StateMachine() returns true, then the question was restarted as a different question, so return.
4237    if (!mDNSOpaque16IsZero(q->TargetQID) && DNS64StateMachine(m, q, &rr->resrec, AddRecord)) return;
4238#endif
4239
4240#ifdef USE_LIBIDN
4241    if (rr->resrec.RecordType == kDNSRecordTypePacketNegative)  // If negative answer, check if we need to try Punycode conversion
4242    {
4243        domainname newname;
4244        if (PerformNextPunycodeConversion(q, &newname))         // Itertative Punycode conversion succeeded, so reissue question with new name
4245        {
4246            UDPSocket *const sock = q->LocalSocket;             // Save old socket and transaction ID
4247            const mDNSOpaque16 id = q->TargetQID;
4248            q->LocalSocket = mDNSNULL;
4249            mDNS_StopQuery_internal(m, q);                      // Stop old query
4250            AssignDomainName(&q->qname, &newname);              // Update qname
4251            q->qnamehash = DomainNameHashValue(&q->qname);      // and namehash
4252            mDNS_StartQuery_internal(m, q);                     // Start new query
4253
4254            if (sock)                                           // Transplant saved socket, if appropriate
4255            {
4256                if (q->DuplicateOf) mDNSPlatformUDPClose(sock);
4257                else { q->LocalSocket = sock; q->TargetQID = id; }
4258            }
4259            return;                                             // All done for now; wait until we get the next answer
4260        }
4261    }
4262#endif // USE_LIBIDN
4263
4264    // Only deliver negative answers if client has explicitly requested them except when we are forcing a negative response
4265    // for the purpose of retrying search domains/timeout OR the question is suppressed
4266    if (rr->resrec.RecordType == kDNSRecordTypePacketNegative || (q->qtype != kDNSType_NSEC && RRAssertsNonexistence(&rr->resrec, q->qtype)))
4267        if (!AddRecord || (AddRecord != QC_suppressed && AddRecord != QC_forceresponse && !q->ReturnIntermed)) return;
4268
4269    // For CNAME results to non-CNAME questions, only inform the client if they explicitly requested that
4270    if (q->QuestionCallback && !q->NoAnswer && (!followcname || q->ReturnIntermed))
4271    {
4272        mDNS_DropLockBeforeCallback();      // Allow client (and us) to legally make mDNS API calls
4273        if (q->qtype != kDNSType_NSEC && RRAssertsNonexistence(&rr->resrec, q->qtype))
4274        {
4275            CacheRecord neg;
4276            MakeNegativeCacheRecord(m, &neg, &q->qname, q->qnamehash, q->qtype, q->qclass, 1, rr->resrec.InterfaceID, q->qDNSServer);
4277            q->QuestionCallback(m, q, &neg.resrec, AddRecord);
4278        }
4279        else
4280        {
4281#if USE_DNS64
4282            if (DNS64ShouldAnswerQuestion(q, &rr->resrec))
4283            {
4284                DNS64AnswerQuestion(m, q, &rr->resrec, AddRecord);
4285            }
4286            else
4287#endif
4288            {
4289                q->QuestionCallback(m, q, &rr->resrec, AddRecord);
4290            }
4291        }
4292        mDNS_ReclaimLockAfterCallback();    // Decrement mDNS_reentrancy to block mDNS API calls again
4293    }
4294    // If this is an "Add" operation and this question needs validation, validate the response.
4295    // In the case of negative responses, extra care should be taken. Negative cache records are
4296    // used for many purposes. For example,
4297    //
4298    // 1) Suppressing questions (SuppressUnusable)
4299    // 2) Timeout questions
4300    // 3) The name does not exist
4301    // 4) No DNS servers are available and we need a quick response for the application
4302    //
4303    // (1) and (2) are handled by "QC_add" check as AddRecord would be "QC_forceresponse" or "QC_suppressed"
4304    // in that case. For (3), it is possible that we don't get nsecs back but we still need to call
4305    // VerifySignature so that we can deliver the appropriate DNSSEC result. There is no point in verifying
4306    // signature for (4) and hence the explicit check for q->qDNSServer.
4307    //
4308    if (m->CurrentQuestion == q && (AddRecord == QC_add) && !q->ValidatingResponse && q->ValidationRequired &&
4309        q->ValidationState == DNSSECValRequired && q->qDNSServer)
4310    {
4311        q->ValidationState = DNSSECValInProgress;
4312        // Treat it as callback call as that's what dnssec code expects
4313        mDNS_DropLockBeforeCallback();      // Allow client (and us) to legally make mDNS API calls
4314        VerifySignature(m, mDNSNULL, q);
4315        mDNS_ReclaimLockAfterCallback();    // Decrement mDNS_reentrancy to block mDNS API calls again
4316        return;
4317    }
4318
4319    if ((m->CurrentQuestion == q) && !ValidatingQuestion(q))
4320    {
4321        // If we get a CNAME back while we are validating the response (i.e., CNAME for DS, DNSKEY, RRSIG),
4322        // don't follow them. If it is a ValidationRequired question, wait for the CNAME to be validated
4323        // first before following it
4324        if (followcname)  AnswerQuestionByFollowingCNAME(m, q, &rr->resrec);
4325
4326        // If we are returning expired RRs, then remember the first expired qname we we can start the query again
4327        if (rr->resrec.mortality == Mortality_Ghost && !q->firstExpiredQname.c[0] && (q->allowExpired == AllowExpired_AllowExpiredAnswers) && rr->resrec.RecordType != kDNSRecordTypePacketNegative)
4328        {
4329            debugf("AnswerCurrentQuestionWithResourceRecord: Keeping track of domain for expired RR %s for question %p", CRDisplayString(m,rr), q);
4330            // Note: question->qname is already changed at this point if following a CNAME
4331            AssignDomainName(&q->firstExpiredQname, rr->resrec.name);           // Update firstExpiredQname
4332        }
4333    }
4334}
4335
4336mDNSlocal void CacheRecordDeferredAdd(mDNS *const m, CacheRecord *rr)
4337{
4338    rr->DelayDelivery = 0;
4339    if (m->CurrentQuestion)
4340        LogMsg("CacheRecordDeferredAdd ERROR m->CurrentQuestion already set: %##s (%s)",
4341               m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
4342    m->CurrentQuestion = m->Questions;
4343    while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
4344    {
4345        DNSQuestion *q = m->CurrentQuestion;
4346        if (ResourceRecordAnswersQuestion(&rr->resrec, q))
4347            AnswerCurrentQuestionWithResourceRecord(m, rr, QC_add);
4348        if (m->CurrentQuestion == q)    // If m->CurrentQuestion was not auto-advanced, do it ourselves now
4349            m->CurrentQuestion = q->next;
4350    }
4351    m->CurrentQuestion = mDNSNULL;
4352}
4353
4354mDNSlocal mDNSs32 CheckForSoonToExpireRecords(mDNS *const m, const domainname *const name, const mDNSu32 namehash)
4355{
4356    const mDNSs32 threshold = m->timenow + mDNSPlatformOneSecond;  // See if there are any records expiring within one second
4357    const mDNSs32 start      = m->timenow - 0x10000000;
4358    mDNSs32 delay = start;
4359    CacheGroup *cg = CacheGroupForName(m, namehash, name);
4360    const CacheRecord *rr;
4361
4362    for (rr = cg ? cg->members : mDNSNULL; rr; rr=rr->next)
4363    {
4364        if (threshold - RRExpireTime(rr) >= 0)     // If we have records about to expire within a second
4365        {
4366            if (delay - RRExpireTime(rr) < 0)       // then delay until after they've been deleted
4367                delay = RRExpireTime(rr);
4368        }
4369    }
4370    if (delay - start > 0)
4371        return(NonZeroTime(delay));
4372    else
4373        return(0);
4374}
4375
4376// CacheRecordAdd is only called from CreateNewCacheEntry, *never* directly as a result of a client API call.
4377// If new questions are created as a result of invoking client callbacks, they will be added to
4378// the end of the question list, and m->NewQuestions will be set to indicate the first new question.
4379// rr is a new CacheRecord just received into our cache
4380// (kDNSRecordTypePacketAns/PacketAnsUnique/PacketAdd/PacketAddUnique).
4381// Note: CacheRecordAdd calls AnswerCurrentQuestionWithResourceRecord which can call a user callback,
4382// which may change the record list and/or question list.
4383// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
4384mDNSlocal void CacheRecordAdd(mDNS *const m, CacheRecord *rr)
4385{
4386    DNSQuestion *q;
4387
4388    // We stop when we get to NewQuestions -- if we increment their CurrentAnswers/LargeAnswers/UniqueAnswers
4389    // counters here we'll end up double-incrementing them when we do it again in AnswerNewQuestion().
4390    for (q = m->Questions; q && q != m->NewQuestions; q=q->next)
4391    {
4392        if (ResourceRecordAnswersQuestion(&rr->resrec, q))
4393        {
4394	    mDNSIPPort zp = zeroIPPort;
4395            // If this question is one that's actively sending queries, and it's received ten answers within one
4396            // second of sending the last query packet, then that indicates some radical network topology change,
4397            // so reset its exponential backoff back to the start. We must be at least at the eight-second interval
4398            // to do this. If we're at the four-second interval, or less, there's not much benefit accelerating
4399            // because we will anyway send another query within a few seconds. The first reset query is sent out
4400            // randomized over the next four seconds to reduce possible synchronization between machines.
4401            if (q->LastAnswerPktNum != m->PktNum)
4402            {
4403                q->LastAnswerPktNum = m->PktNum;
4404                if (mDNSOpaque16IsZero(q->TargetQID) && ActiveQuestion(q) && ++q->RecentAnswerPkts >= 10 &&
4405                    q->ThisQInterval > InitialQuestionInterval * QuestionIntervalStep3 && m->timenow - q->LastQTxTime < mDNSPlatformOneSecond)
4406                {
4407                    LogMsg("CacheRecordAdd: %##s (%s) got immediate answer burst (%d); restarting exponential backoff sequence (%d)",
4408                           q->qname.c, DNSTypeName(q->qtype), q->RecentAnswerPkts, q->ThisQInterval);
4409                    q->LastQTime      = m->timenow - InitialQuestionInterval + (mDNSs32)mDNSRandom((mDNSu32)mDNSPlatformOneSecond*4);
4410                    q->ThisQInterval  = InitialQuestionInterval;
4411                    SetNextQueryTime(m,q);
4412                }
4413            }
4414            verbosedebugf("CacheRecordAdd %p %##s (%s) %lu %#a:%d question %p", rr, rr->resrec.name->c,
4415                          DNSTypeName(rr->resrec.rrtype), rr->resrec.rroriginalttl, rr->resrec.rDNSServer ?
4416                          &rr->resrec.rDNSServer->addr : mDNSNULL, mDNSVal16(rr->resrec.rDNSServer ?
4417                                                                             rr->resrec.rDNSServer->port : zp), q);
4418            q->CurrentAnswers++;
4419
4420            q->unansweredQueries = 0;
4421            if (rr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers++;
4422            if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers++;
4423            if (q->CurrentAnswers > 4000)
4424            {
4425                static int msgcount = 0;
4426                if (msgcount++ < 10)
4427                    LogMsg("CacheRecordAdd: %##s (%s) has %d answers; shedding records to resist DOS attack",
4428                           q->qname.c, DNSTypeName(q->qtype), q->CurrentAnswers);
4429                rr->resrec.rroriginalttl = 0;
4430                rr->UnansweredQueries = MaxUnansweredQueries;
4431            }
4432        }
4433    }
4434
4435    if (!rr->DelayDelivery)
4436    {
4437        if (m->CurrentQuestion)
4438            LogMsg("CacheRecordAdd ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
4439        m->CurrentQuestion = m->Questions;
4440        while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
4441        {
4442            q = m->CurrentQuestion;
4443            if (ResourceRecordAnswersQuestion(&rr->resrec, q))
4444                AnswerCurrentQuestionWithResourceRecord(m, rr, QC_add);
4445            if (m->CurrentQuestion == q)    // If m->CurrentQuestion was not auto-advanced, do it ourselves now
4446                m->CurrentQuestion = q->next;
4447        }
4448        m->CurrentQuestion = mDNSNULL;
4449    }
4450
4451    SetNextCacheCheckTimeForRecord(m, rr);
4452}
4453
4454// NoCacheAnswer is only called from mDNSCoreReceiveResponse, *never* directly as a result of a client API call.
4455// If new questions are created as a result of invoking client callbacks, they will be added to
4456// the end of the question list, and m->NewQuestions will be set to indicate the first new question.
4457// rr is a new CacheRecord just received from the wire (kDNSRecordTypePacketAns/AnsUnique/Add/AddUnique)
4458// but we don't have any place to cache it. We'll deliver question 'add' events now, but we won't have any
4459// way to deliver 'remove' events in future, nor will we be able to include this in known-answer lists,
4460// so we immediately bump ThisQInterval up to MaxQuestionInterval to avoid pounding the network.
4461// Note: NoCacheAnswer calls AnswerCurrentQuestionWithResourceRecord which can call a user callback,
4462// which may change the record list and/or question list.
4463// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
4464mDNSlocal void NoCacheAnswer(mDNS *const m, CacheRecord *rr)
4465{
4466    LogMsg("No cache space: Delivering non-cached result for %##s", m->rec.r.resrec.name->c);
4467    if (m->CurrentQuestion)
4468        LogMsg("NoCacheAnswer ERROR m->CurrentQuestion already set: %##s (%s)", m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
4469    m->CurrentQuestion = m->Questions;
4470    // We do this for *all* questions, not stopping when we get to m->NewQuestions,
4471    // since we're not caching the record and we'll get no opportunity to do this later
4472    while (m->CurrentQuestion)
4473    {
4474        DNSQuestion *q = m->CurrentQuestion;
4475        if (ResourceRecordAnswersQuestion(&rr->resrec, q))
4476            AnswerCurrentQuestionWithResourceRecord(m, rr, QC_addnocache);  // QC_addnocache means "don't expect remove events for this"
4477        if (m->CurrentQuestion == q)    // If m->CurrentQuestion was not auto-advanced, do it ourselves now
4478            m->CurrentQuestion = q->next;
4479    }
4480    m->CurrentQuestion = mDNSNULL;
4481}
4482
4483// CacheRecordRmv is only called from CheckCacheExpiration, which is called from mDNS_Execute.
4484// Note that CacheRecordRmv is *only* called for records that are referenced by at least one active question.
4485// If new questions are created as a result of invoking client callbacks, they will be added to
4486// the end of the question list, and m->NewQuestions will be set to indicate the first new question.
4487// rr is an existing cache CacheRecord that just expired and is being deleted
4488// (kDNSRecordTypePacketAns/PacketAnsUnique/PacketAdd/PacketAddUnique).
4489// Note: CacheRecordRmv calls AnswerCurrentQuestionWithResourceRecord which can call a user callback,
4490// which may change the record list and/or question list.
4491// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
4492mDNSlocal void CacheRecordRmv(mDNS *const m, CacheRecord *rr)
4493{
4494    if (m->CurrentQuestion)
4495        LogMsg("CacheRecordRmv ERROR m->CurrentQuestion already set: %##s (%s)",
4496               m->CurrentQuestion->qname.c, DNSTypeName(m->CurrentQuestion->qtype));
4497    m->CurrentQuestion = m->Questions;
4498
4499    // We stop when we get to NewQuestions -- for new questions their CurrentAnswers/LargeAnswers/UniqueAnswers counters
4500    // will all still be zero because we haven't yet gone through the cache counting how many answers we have for them.
4501    while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
4502    {
4503        DNSQuestion *q = m->CurrentQuestion;
4504        // When a question enters suppressed state, we generate RMV events and generate a negative
4505        // response. A cache may be present that answers this question e.g., cache entry generated
4506        // before the question became suppressed. We need to skip the suppressed questions here as
4507        // the RMV event has already been generated.
4508        if (!QuerySuppressed(q) && ResourceRecordAnswersQuestion(&rr->resrec, q) &&
4509            (q->allowExpired == AllowExpired_None || rr->resrec.mortality == Mortality_Mortal))
4510        {
4511            verbosedebugf("CacheRecordRmv %p %s", rr, CRDisplayString(m, rr));
4512            q->FlappingInterface1 = mDNSNULL;
4513            q->FlappingInterface2 = mDNSNULL;
4514
4515            if (q->CurrentAnswers == 0) {
4516		mDNSIPPort zp = zeroIPPort;
4517                LogMsg("CacheRecordRmv ERROR!!: How can CurrentAnswers already be zero for %p %##s (%s) DNSServer %#a:%d",
4518                       q, q->qname.c, DNSTypeName(q->qtype), q->qDNSServer ? &q->qDNSServer->addr : mDNSNULL,
4519                       mDNSVal16(q->qDNSServer ? q->qDNSServer->port : zp));
4520	    }
4521            else
4522            {
4523                q->CurrentAnswers--;
4524                if (rr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers--;
4525                if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers--;
4526            }
4527
4528            // If we have dropped below the answer threshold for this mDNS question,
4529            // restart the queries at InitialQuestionInterval.
4530            if (mDNSOpaque16IsZero(q->TargetQID) && (q->BrowseThreshold > 0) && (q->CurrentAnswers < q->BrowseThreshold))
4531            {
4532                q->ThisQInterval = InitialQuestionInterval;
4533                q->LastQTime     = m->timenow - q->ThisQInterval;
4534                SetNextQueryTime(m,q);
4535                LogInfo("CacheRecordRmv: (%s) %##s dropped below threshold of %d answers",
4536                    DNSTypeName(q->qtype), q->qname.c, q->BrowseThreshold);
4537            }
4538            if (rr->resrec.rdata->MaxRDLength) // Never generate "remove" events for negative results
4539            {
4540                if ((q->CurrentAnswers == 0) && mDNSOpaque16IsZero(q->TargetQID))
4541                {
4542                    LogInfo("CacheRecordRmv: Last answer for %##s (%s) expired from cache; will reconfirm antecedents",
4543                            q->qname.c, DNSTypeName(q->qtype));
4544                    ReconfirmAntecedents(m, &q->qname, q->qnamehash, rr->resrec.InterfaceID, 0);
4545                }
4546                AnswerCurrentQuestionWithResourceRecord(m, rr, QC_rmv);
4547            }
4548        }
4549        if (m->CurrentQuestion == q)    // If m->CurrentQuestion was not auto-advanced, do it ourselves now
4550            m->CurrentQuestion = q->next;
4551    }
4552    m->CurrentQuestion = mDNSNULL;
4553}
4554
4555mDNSlocal void ReleaseCacheEntity(mDNS *const m, CacheEntity *e)
4556{
4557#if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING >= 1
4558    unsigned int i;
4559    for (i=0; i<sizeof(*e); i++) ((char*)e)[i] = 0xFF;
4560#endif
4561    e->next = m->rrcache_free;
4562    m->rrcache_free = e;
4563    m->rrcache_totalused--;
4564}
4565
4566mDNSlocal void ReleaseCacheGroup(mDNS *const m, CacheGroup **cp)
4567{
4568    CacheEntity *e = (CacheEntity *)(*cp);
4569    //LogMsg("ReleaseCacheGroup:  Releasing CacheGroup for %p, %##s", (*cp)->name->c, (*cp)->name->c);
4570    if ((*cp)->rrcache_tail != &(*cp)->members)
4571        LogMsg("ERROR: (*cp)->members == mDNSNULL but (*cp)->rrcache_tail != &(*cp)->members)");
4572    //if ((*cp)->name != (domainname*)((*cp)->namestorage))
4573    //  LogMsg("ReleaseCacheGroup: %##s, %p %p", (*cp)->name->c, (*cp)->name, (domainname*)((*cp)->namestorage));
4574    if ((*cp)->name != (domainname*)((*cp)->namestorage)) mDNSPlatformMemFree((*cp)->name);
4575    (*cp)->name = mDNSNULL;
4576    *cp = (*cp)->next;          // Cut record from list
4577    ReleaseCacheEntity(m, e);
4578}
4579
4580mDNSlocal void ReleaseAdditionalCacheRecords(mDNS *const m, CacheRecord **rp)
4581{
4582    while (*rp)
4583    {
4584        CacheRecord *rr = *rp;
4585        *rp = (*rp)->next;          // Cut record from list
4586        if (rr->resrec.rdata && rr->resrec.rdata != (RData*)&rr->smallrdatastorage)
4587        {
4588            mDNSPlatformMemFree(rr->resrec.rdata);
4589            rr->resrec.rdata = mDNSNULL;
4590        }
4591        // NSEC or SOA records that are not added to the CacheGroup do not share the name
4592        // of the CacheGroup.
4593        if (rr->resrec.name)
4594        {
4595            debugf("ReleaseAdditionalCacheRecords: freeing cached record %##s (%s)", rr->resrec.name->c, DNSTypeName(rr->resrec.rrtype));
4596            mDNSPlatformMemFree((void *)rr->resrec.name);
4597            rr->resrec.name = mDNSNULL;
4598        }
4599        // Don't count the NSEC3 records used by anonymous browse/reg
4600        if (!rr->resrec.InterfaceID)
4601        {
4602            m->rrcache_totalused_unicast -= rr->resrec.rdlength;
4603            if (DNSSECRecordType(rr->resrec.rrtype))
4604                BumpDNSSECStats(m, kStatsActionDecrement, kStatsTypeMemoryUsage, rr->resrec.rdlength);
4605        }
4606        ReleaseCacheEntity(m, (CacheEntity *)rr);
4607    }
4608}
4609
4610mDNSexport void ReleaseCacheRecord(mDNS *const m, CacheRecord *r)
4611{
4612    CacheGroup *cg;
4613
4614    //LogMsg("ReleaseCacheRecord: Releasing %s", CRDisplayString(m, r));
4615    if (r->resrec.rdata && r->resrec.rdata != (RData*)&r->smallrdatastorage) mDNSPlatformMemFree(r->resrec.rdata);
4616    r->resrec.rdata = mDNSNULL;
4617
4618    cg = CacheGroupForRecord(m, &r->resrec);