source: rtems-libbsd/mDNSResponder/mDNSCore/anonymous.c

Last change on this file was 4c086a2, checked in by Sebastian Huber <sebastian.huber@…>, on Sep 19, 2018 at 6:56:09 AM

mDNSResponder: Update to v878.1.1

The sources can be obtained via:

https://opensource.apple.com/tarballs/mDNSResponder/mDNSResponder-878.1.1.tar.gz

Update #3522.

  • Property mode set to 100644
File size: 20.0 KB
Line 
1/* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2012-2013 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
18#include "mDNSEmbeddedAPI.h"
19#include "CryptoAlg.h"
20#include "anonymous.h"
21#include "DNSCommon.h"
22
23// Define ANONYMOUS_DISABLED to remove all the anonymous functionality
24// and use the stub functions implemented later in this file.
25
26#ifndef ANONYMOUS_DISABLED
27
28#define ANON_NSEC3_ITERATIONS        1
29
30struct AnonInfoResourceRecord_struct
31{
32    ResourceRecord resrec;
33    RData          rdatastorage;
34};
35
36typedef struct AnonInfoResourceRecord_struct AnonInfoResourceRecord;
37
38mDNSlocal mDNSBool InitializeNSEC3Record(ResourceRecord *rr, const mDNSu8 *AnonData, int len, mDNSu32 salt)
39{
40    const mDNSu8 *ptr;
41    rdataNSEC3 *nsec3 = (rdataNSEC3 *)rr->rdata->u.data;
42    mDNSu8 *tmp, *nxt;
43    unsigned short iter = ANON_NSEC3_ITERATIONS;
44    int hlen;
45    const mDNSu8 hashName[NSEC3_MAX_HASH_LEN];
46
47    // Construct the RDATA first and construct the owner name based on that.
48    ptr = (const mDNSu8 *)&salt;
49    debugf("InitializeNSEC3Record: %x%x%x%x, name %##s", ptr[0], ptr[1], ptr[2], ptr[3], rr->name->c);
50
51    // Set the RDATA
52    nsec3->alg = SHA1_DIGEST_TYPE;
53    nsec3->flags = 0;
54    nsec3->iterations = swap16(iter);
55    nsec3->saltLength = 4;
56    tmp = (mDNSu8 *)&nsec3->salt;
57    *tmp++ = ptr[0];
58    *tmp++ = ptr[1];
59    *tmp++ = ptr[2];
60    *tmp++ = ptr[3];
61
62    // hashLength, nxt, bitmap
63    *tmp++ = SHA1_HASH_LENGTH;    // hash length
64    nxt = tmp;
65    tmp += SHA1_HASH_LENGTH;
66    *tmp++ = 0; // window number
67    *tmp++ = NSEC_MCAST_WINDOW_SIZE; // window length
68    mDNSPlatformMemZero(tmp, NSEC_MCAST_WINDOW_SIZE);
69    tmp[kDNSType_PTR >> 3] |= 128 >> (kDNSType_PTR & 7);
70
71    // Hash the base service name + salt + AnonData
72    if (!NSEC3HashName(rr->name, nsec3, AnonData, len, hashName, &hlen))
73    {
74        LogMsg("InitializeNSEC3Record: NSEC3HashName failed for %##s", rr->name->c);
75        return mDNSfalse;
76    }
77    if (hlen != SHA1_HASH_LENGTH)
78    {
79        LogMsg("InitializeNSEC3Record: hlen wrong %d", hlen);
80        return mDNSfalse;
81    }
82    mDNSPlatformMemCopy(nxt, hashName, hlen);
83
84    return mDNStrue;
85}
86
87mDNSlocal ResourceRecord *ConstructNSEC3Record(const domainname *service, const mDNSu8 *AnonData, int len, mDNSu32 salt)
88{
89    ResourceRecord *rr;
90    int dlen;
91    domainname *name;
92
93    // We are just allocating an RData which has StandardAuthRDSize
94    if (StandardAuthRDSize < MCAST_NSEC3_RDLENGTH)
95    {
96        LogMsg("ConstructNSEC3Record: StandardAuthRDSize %d smaller than MCAST_NSEC3_RDLENGTH %d", StandardAuthRDSize, MCAST_NSEC3_RDLENGTH);
97        return mDNSNULL;
98    }
99
100    dlen = DomainNameLength(service);
101 
102    // Allocate space for the name and RData.
103    rr = mDNSPlatformMemAllocate(sizeof(ResourceRecord) + dlen + sizeof(RData));
104    if (!rr)
105        return mDNSNULL;
106    name = (domainname *)((mDNSu8 *)rr + sizeof(ResourceRecord));
107    rr->RecordType        = kDNSRecordTypePacketAuth;
108    rr->InterfaceID       = mDNSInterface_Any;
109    rr->name              = (const domainname *)name;
110    rr->rrtype            = kDNSType_NSEC3;
111    rr->rrclass           = kDNSClass_IN;
112    rr->rroriginalttl     = kStandardTTL;
113    rr->rDNSServer        = mDNSNULL;
114    rr->rdlength          = MCAST_NSEC3_RDLENGTH;
115    rr->rdestimate        = MCAST_NSEC3_RDLENGTH;
116    rr->rdata             = (RData *)((mDNSu8 *)rr->name + dlen);
117
118    AssignDomainName(name, service);
119    if (!InitializeNSEC3Record(rr, AnonData, len, salt))
120    {
121        mDNSPlatformMemFree(rr);
122        return mDNSNULL;
123    }
124    return rr;
125}
126
127mDNSlocal ResourceRecord *CopyNSEC3ResourceRecord(AnonymousInfo *si, const ResourceRecord *rr)
128{
129    AnonInfoResourceRecord *anonRR;
130    domainname *name;
131    mDNSu32 neededLen;
132    mDNSu32 extraLen;
133
134    if (rr->rdlength < MCAST_NSEC3_RDLENGTH)
135    {
136        LogMsg("CopyNSEC3ResourceRecord: rdlength %d smaller than MCAST_NSEC3_RDLENGTH %d", rr->rdlength, MCAST_NSEC3_RDLENGTH);
137        return mDNSNULL;
138    }
139    // Allocate space for the name and the rdata along with the ResourceRecord
140    neededLen = rr->rdlength + DomainNameLength(rr->name);
141    extraLen = (neededLen > sizeof(RDataBody)) ? (neededLen - sizeof(RDataBody)) : 0;
142    anonRR = (AnonInfoResourceRecord *)mDNSPlatformMemAllocate(sizeof(AnonInfoResourceRecord) + extraLen);
143    if (!anonRR)
144        return mDNSNULL;
145
146    anonRR->resrec = *rr;
147
148    anonRR->rdatastorage.MaxRDLength = rr->rdlength;
149    mDNSPlatformMemCopy(anonRR->rdatastorage.u.data, rr->rdata->u.data, rr->rdlength);
150
151    name = (domainname *)(anonRR->rdatastorage.u.data + rr->rdlength);
152    AssignDomainName(name, rr->name);
153
154    anonRR->resrec.name = name;
155    anonRR->resrec.rdata = &anonRR->rdatastorage;
156
157    si->nsec3RR = (ResourceRecord *)anonRR;
158
159    return si->nsec3RR;
160}
161
162// When a service is started or a browse is started with the Anonymous data, we allocate a new random
163// number and based on that allocate a new NSEC3 resource record whose hash is a function of random number (salt) and
164// the anonymous data.
165//
166// If we receive a packet with the NSEC3 option, we need to cache that along with the resource record so that we can
167// check against the question to see whether it answers them or not. In that case, we pass the "rr" that we received.
168mDNSexport  AnonymousInfo *AllocateAnonInfo(const domainname *service, const mDNSu8 *data, int len, const ResourceRecord *rr)
169{
170    AnonymousInfo *ai;
171    ai = (AnonymousInfo *)mDNSPlatformMemAllocate(sizeof(AnonymousInfo));
172    if (!ai)
173    {
174        return mDNSNULL;
175    }
176    mDNSPlatformMemZero(ai, sizeof(AnonymousInfo));
177    if (rr)
178    {
179        if (!CopyNSEC3ResourceRecord(ai, rr))
180        {
181            mDNSPlatformMemFree(ai);
182            return mDNSNULL;
183        }
184        return ai;
185    }
186    ai->salt = mDNSRandom(0xFFFFFFFF);
187    ai->AnonData = mDNSPlatformMemAllocate(len);
188    if (!ai->AnonData)
189    {
190        mDNSPlatformMemFree(ai);
191        return mDNSNULL;
192    }
193    ai->AnonDataLen = len;
194    mDNSPlatformMemCopy(ai->AnonData, data, len);
195    ai->nsec3RR = ConstructNSEC3Record(service, data, len, ai->salt);
196    if (!ai->nsec3RR)
197    {
198        mDNSPlatformMemFree(ai);
199        return mDNSNULL;
200    }
201    return ai;
202}
203
204mDNSexport void FreeAnonInfo(AnonymousInfo *ai)
205{
206    if (ai->nsec3RR)
207        mDNSPlatformMemFree(ai->nsec3RR);
208    if (ai->AnonData)
209        mDNSPlatformMemFree(ai->AnonData);
210    mDNSPlatformMemFree(ai);
211}
212
213mDNSexport void ReInitAnonInfo(AnonymousInfo **AnonInfo, const domainname *name)
214{
215    if (*AnonInfo)
216    {
217        AnonymousInfo *ai = *AnonInfo;
218        *AnonInfo = AllocateAnonInfo(name, ai->AnonData, ai->AnonDataLen, mDNSNULL);
219        if (!(*AnonInfo))
220            *AnonInfo = ai;
221        else
222            FreeAnonInfo(ai);
223    }
224}
225
226// This function should be used only if you know that the question and
227// the resource record belongs to the same set. The main usage is
228// in ProcessQuery where we find the question to be part of the same
229// set as the resource record, but it needs the AnonData to be
230// initialized so that it can walk the cache records to see if they
231// answer the question.
232mDNSexport void SetAnonData(DNSQuestion *q, ResourceRecord *rr, mDNSBool ForQuestion)
233{
234    if (!q->AnonInfo || !rr->AnonInfo)
235    {
236        LogMsg("SetAnonData: question %##s(%p), rr %##s(%p), NULL", q->qname.c, q->AnonInfo, rr->name->c, rr->AnonInfo);
237        return;
238    }
239   
240    debugf("SetAnonData: question %##s(%p), rr %##s(%p)", q->qname.c, q->AnonInfo, rr->name->c, rr->AnonInfo);
241    if (ForQuestion)
242    {
243        if (q->AnonInfo->AnonDataLen < rr->AnonInfo->AnonDataLen)
244        {
245            mDNSPlatformMemFree(q->AnonInfo->AnonData);
246            q->AnonInfo->AnonData = mDNSNULL;
247        }
248
249        if (!q->AnonInfo->AnonData)
250        {
251            q->AnonInfo->AnonData = mDNSPlatformMemAllocate(rr->AnonInfo->AnonDataLen);
252            if (!q->AnonInfo->AnonData)
253                return;
254        }
255        mDNSPlatformMemCopy(q->AnonInfo->AnonData, rr->AnonInfo->AnonData, rr->AnonInfo->AnonDataLen);
256        q->AnonInfo->AnonDataLen = rr->AnonInfo->AnonDataLen;
257    }
258    else
259    {
260        if (rr->AnonInfo->AnonDataLen < q->AnonInfo->AnonDataLen)
261        {
262            mDNSPlatformMemFree(rr->AnonInfo->AnonData);
263            rr->AnonInfo->AnonData = mDNSNULL;
264        }
265
266        if (!rr->AnonInfo->AnonData)
267        {
268            rr->AnonInfo->AnonData = mDNSPlatformMemAllocate(q->AnonInfo->AnonDataLen);
269            if (!rr->AnonInfo->AnonData)
270                return;
271        }
272        mDNSPlatformMemCopy(rr->AnonInfo->AnonData, q->AnonInfo->AnonData, q->AnonInfo->AnonDataLen);
273        rr->AnonInfo->AnonDataLen = q->AnonInfo->AnonDataLen;
274    }
275}
276
277mDNSlocal char *RRDisplayStringBuf(const ResourceRecord *const rr, char *const buffer)
278{
279    return GetRRDisplayString_rdb(rr, &rr->rdata->u, buffer);
280}
281
282// returns -1 if the caller should ignore the result
283// returns 1 if the record answers the question
284// returns 0 if the record does not answer the question
285mDNSexport int AnonInfoAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q)
286{
287    char MsgBuffer[MaxMsg];             // Temp storage used while building error log messages
288    ResourceRecord *nsec3RR;
289    int i;
290    AnonymousInfo *qai, *rai;
291    mDNSu8 *AnonData;
292    int AnonDataLen;
293    rdataNSEC3 *nsec3;
294    int hlen;
295    int nxtLength;
296    mDNSu8 *nxtName;
297    mDNSu8 hashName[NSEC3_MAX_HASH_LEN];
298    mDNSPlatformMemZero(hashName, sizeof(hashName));
299
300    debugf("AnonInfoAnswersQuestion: question qname %##s", q->qname.c);
301
302    // Currently only PTR records can have anonymous information
303    if (q->qtype != kDNSType_PTR)
304    {
305        return -1;
306    }
307
308    // We allow anonymous questions to be answered by both normal services (without the
309    // anonymous information) and anonymous services that are part of the same set. And
310    // normal questions discover normal services and all anonymous services.
311    //
312    // The three cases have been enumerated clearly even though they all behave the
313    // same way.
314    if (!q->AnonInfo)
315    {
316        debugf("AnonInfoAnswersQuestion: not a anonymous type question");
317        if (!rr->AnonInfo)
318        {
319            // case 1
320            return -1;
321        }
322        else
323        {
324            // case 2
325            debugf("AnonInfoAnswersQuestion: Question %##s not answered using anonymous record %##s", q->qname.c, rr->name->c);
326            return -1;
327        }
328    }
329    else
330    {
331        // case 3
332        if (!rr->AnonInfo)
333        {
334            debugf("AnonInfoAnswersQuestion: not a anonymous type record");
335            return -1;
336        }
337    }
338
339    // case 4: We have the anonymous information both in the question and the record. We need
340    // two sets of information to validate.
341    //
342    // 1) Anonymous data that identifies the set/group
343    // 2) NSEC3 record that contains the hash and the salt
344    //
345    // If the question is a remote one, it does not have the anonymous information to validate (just
346    // the NSEC3 record) and hence the anonymous data should come from the local resource record. If the
347    // question is local, it can come from either of them and if there is a mismatch between the
348    // question and record, it won't validate.
349
350    qai = q->AnonInfo;
351    rai = rr->AnonInfo;
352
353    if (qai->AnonData && rai->AnonData)
354    {
355        // Before a cache record is created, if there is a matching question i.e., part
356        // of the same set, then when the cache is created we also set the anonymous
357        // information. Otherwise, the cache record contains just the NSEC3 record and we
358        // won't be here for that case.
359        //
360        // It is also possible that a local question is matched against the local AuthRecord
361        // as that is also the case for which the AnonData would be non-NULL for both.
362        // We match questions against AuthRecords (rather than the cache) for LocalOnly case and
363        // to see whether a .local query should be suppressed or not. The latter never happens
364        // because PTR queries are never suppressed.
365
366        // If they don't belong to the same anonymous set, then no point in validating.
367        if ((qai->AnonDataLen != rai->AnonDataLen) ||
368            mDNSPlatformMemCmp(qai->AnonData, rai->AnonData, qai->AnonDataLen) != 0)
369        {
370            debugf("AnonInfoAnswersQuestion: AnonData mis-match for record  %s question %##s ",
371                RRDisplayStringBuf(rr, MsgBuffer), q->qname.c);
372            return 0;
373        }
374        // AnonData matches i.e they belong to the same group and the same service.
375        LogInfo("AnonInfoAnswersQuestion: Answering qname %##s, rname %##s, without validation", q->qname.c,
376            rr->name->c);
377        return 1;
378    }
379    else
380    {
381        debugf("AnonInfoAnswersQuestion: question %p, record %p", qai->AnonData, rai->AnonData);
382    }
383
384    if (qai->AnonData)
385    {
386        // If there is AnonData, then this is a local question. The
387        // NSEC3 RR comes from the resource record which could be part
388        // of the cache or local auth record. The cache entry could
389        // be from a remote host or created when we heard our own
390        // announcements. In any case, we use that to see if it matches
391        // the question.
392        AnonData = qai->AnonData;
393        AnonDataLen = qai->AnonDataLen;
394        nsec3RR = rai->nsec3RR;
395    }
396    else
397    {
398        // Remote question or hearing our own question back
399        AnonData = rai->AnonData;
400        AnonDataLen = rai->AnonDataLen;
401        nsec3RR = qai->nsec3RR;
402    }
403
404    if (!AnonData || !nsec3RR)
405    {
406        // AnonData can be NULL for the cache entry and if we are hearing our own question back, AnonData is NULL for
407        // that too and we can end up here for that case.
408        debugf("AnonInfoAnswersQuestion: AnonData %p or nsec3RR %p, NULL for question %##s, record %s", AnonData, nsec3RR,
409            q->qname.c, RRDisplayStringBuf(rr, MsgBuffer));
410        return 0;
411    }
412    debugf("AnonInfoAnswersQuestion: Validating question %##s, ResourceRecord %s", q->qname.c, RRDisplayStringBuf(nsec3RR, MsgBuffer));
413
414
415    nsec3 = (rdataNSEC3 *)nsec3RR->rdata->u.data;
416
417    if (!NSEC3HashName(nsec3RR->name, nsec3, AnonData, AnonDataLen, hashName, &hlen))
418    {
419        LogMsg("AnonInfoAnswersQuestion: NSEC3HashName failed for %##s", nsec3RR->name->c);
420        return mDNSfalse;
421    }
422    if (hlen != SHA1_HASH_LENGTH)
423    {
424        LogMsg("AnonInfoAnswersQuestion: hlen wrong %d", hlen);
425        return mDNSfalse;
426    }
427
428    NSEC3Parse(nsec3RR, mDNSNULL, &nxtLength, &nxtName, mDNSNULL, mDNSNULL);
429
430    if (hlen != nxtLength)
431    {
432        LogMsg("AnonInfoAnswersQuestion: ERROR!! hlen %d not same as nxtLength %d", hlen, nxtLength);
433        return mDNSfalse;
434    }
435
436    for (i = 0; i < nxtLength; i++)
437    {
438        if (nxtName[i] != hashName[i])
439        {
440            debugf("AnonInfoAnswersQuestion: mismatch output %x, digest %x, i %d", nxtName[i+1], hashName[i], i);
441            return 0;
442        }
443    }
444    LogInfo("AnonInfoAnswersQuestion: ResourceRecord %s matched question %##s (%s)", RRDisplayStringBuf(nsec3RR, MsgBuffer), q->qname.c, DNSTypeName(q->qtype));
445    return 1;
446}
447
448// Find a matching NSEC3 record for the name. We parse the questions and the records in the packet in order.
449// Similarly we also parse the NSEC3 records in order and this mapping to the questions and records
450// respectively.
451mDNSlocal CacheRecord *FindMatchingNSEC3ForName(mDNS *const m, CacheRecord **nsec3, const domainname *name)
452{
453    CacheRecord *cr;
454    CacheRecord **prev = nsec3;
455   
456    (void) m;
457
458    for (cr = *nsec3; cr; cr = cr->next)
459    {
460        if (SameDomainName(cr->resrec.name, name))
461        {
462            debugf("FindMatchingNSEC3ForName: NSEC3 record %s matched %##s", CRDisplayString(m, cr), name->c);
463            *prev = cr->next;
464            cr->next = mDNSNULL;
465            return cr;
466        }
467        prev = &cr->next;
468    }
469    return mDNSNULL;
470}
471
472mDNSexport void InitializeAnonInfoForQuestion(mDNS *const m, CacheRecord **McastNSEC3Records, DNSQuestion *q)
473{
474    CacheRecord *nsec3CR;
475
476    if (q->qtype != kDNSType_PTR)
477        return;
478
479    nsec3CR = FindMatchingNSEC3ForName(m, McastNSEC3Records, &q->qname);
480    if (nsec3CR)
481    {
482        q->AnonInfo = AllocateAnonInfo(mDNSNULL, mDNSNULL, 0, &nsec3CR->resrec);
483        if (q->AnonInfo)
484        {
485            debugf("InitializeAnonInfoForQuestion: Found a matching NSEC3 record %s, for %##s (%s)",
486                RRDisplayString(m, q->AnonInfo->nsec3RR), q->qname.c, DNSTypeName(q->qtype));
487        }
488        ReleaseCacheRecord(m, nsec3CR);
489    }
490}
491
492mDNSexport void InitializeAnonInfoForCR(mDNS *const m, CacheRecord **McastNSEC3Records, CacheRecord *cr)
493{
494    CacheRecord *nsec3CR;
495
496    if (!(*McastNSEC3Records))
497        return;
498
499    // If already initialized or not a PTR type, we don't have to do anything
500    if (cr->resrec.AnonInfo || cr->resrec.rrtype != kDNSType_PTR)
501        return;
502
503    nsec3CR = FindMatchingNSEC3ForName(m, McastNSEC3Records, cr->resrec.name);
504    if (nsec3CR)
505    {
506        cr->resrec.AnonInfo = AllocateAnonInfo(mDNSNULL, mDNSNULL, 0, &nsec3CR->resrec);
507        if (cr->resrec.AnonInfo)
508        {
509            debugf("InitializeAnonInfoForCR: Found a matching NSEC3 record %s, for %##s (%s)",
510                RRDisplayString(m, cr->resrec.AnonInfo->nsec3RR), cr->resrec.name->c,
511                DNSTypeName(cr->resrec.rrtype));
512        }
513        ReleaseCacheRecord(m, nsec3CR);
514    }
515}
516
517mDNSexport mDNSBool IdenticalAnonInfo(AnonymousInfo *a1, AnonymousInfo *a2)
518{
519    // if a1 is NULL and a2 is not NULL AND vice-versa
520    // return false as there is a change.
521    if ((a1 != mDNSNULL) != (a2 != mDNSNULL))
522        return mDNSfalse;
523
524    // Both could be NULL or non-NULL
525    if (a1 && a2)
526    {
527        // The caller already verified that the owner name is the same.
528        // Check whether the RData is same.
529        if (!IdenticalSameNameRecord(a1->nsec3RR, a2->nsec3RR))
530        {
531            debugf("IdenticalAnonInfo: nsec3RR mismatch");
532            return mDNSfalse;
533        }
534    }
535    return mDNStrue;
536}
537
538mDNSexport void CopyAnonInfoForCR(mDNS *const m, CacheRecord *crto, CacheRecord *crfrom)
539{
540    AnonymousInfo *aifrom = crfrom->resrec.AnonInfo;
541    AnonymousInfo *aito = crto->resrec.AnonInfo;
542
543    (void) m;
544
545    if (!aifrom)
546        return;
547
548    if (aito)
549    {
550        crto->resrec.AnonInfo = aifrom;
551        FreeAnonInfo(aito);
552        crfrom->resrec.AnonInfo = mDNSNULL;
553    }
554    else
555    {
556        FreeAnonInfo(aifrom);
557        crfrom->resrec.AnonInfo = mDNSNULL;
558    }
559}
560
561#else // !ANONYMOUS_DISABLED
562
563mDNSexport void ReInitAnonInfo(AnonymousInfo **si, const domainname *name)
564{
565        (void)si;
566        (void)name;
567}
568
569mDNSexport AnonymousInfo * AllocateAnonInfo(const domainname *service, const mDNSu8 *AnonData, int len, const ResourceRecord *rr)
570{
571        (void)service;
572        (void)AnonData;
573        (void)len;
574        (void)rr;
575
576        return mDNSNULL;
577}
578
579mDNSexport void FreeAnonInfo(AnonymousInfo *ai)
580{
581        (void)ai;
582}
583
584mDNSexport void SetAnonData(DNSQuestion *q, ResourceRecord *rr, mDNSBool ForQuestion)
585{
586        (void)q;
587        (void)rr;
588        (void)ForQuestion;
589}
590
591mDNSexport int AnonInfoAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q)
592{
593        (void)rr;
594        (void)q;
595
596        return mDNSfalse;
597}
598
599mDNSexport void InitializeAnonInfoForQuestion(mDNS *const m, CacheRecord **McastNSEC3Records, DNSQuestion *q)
600{
601        (void)m;
602        (void)McastNSEC3Records;
603        (void)q;
604}
605
606mDNSexport void InitializeAnonInfoForCR(mDNS *const m, CacheRecord **McastNSEC3Records, CacheRecord *cr)
607{
608        (void)m;
609        (void)McastNSEC3Records;
610        (void)cr;
611}
612
613mDNSexport void CopyAnonInfoForCR(mDNS *const m, CacheRecord *crto, CacheRecord *crfrom)
614{
615        (void)m;
616        (void)crto;
617        (void)crfrom;
618}
619
620mDNSexport mDNSBool IdenticalAnonInfo(AnonymousInfo *a1, AnonymousInfo *a2)
621{
622        (void)a1;
623        (void)a2;
624
625        return mDNStrue;
626}
627
628#endif // !ANONYMOUS_DISABLED
Note: See TracBrowser for help on using the repository browser.