5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome/* -*- Mode: C; tab-width: 4 -*-
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome * Copyright (c) 2012-2013 Apple Inc. All rights reserved.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * Licensed under the Apache License, Version 2.0 (the "License");
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * you may not use this file except in compliance with the License.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * You may obtain a copy of the License at
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * Unless required by applicable law or agreed to in writing, software
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * distributed under the License is distributed on an "AS IS" BASIS,
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * See the License for the specific language governing permissions and
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * limitations under the License.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// Define ANONYMOUS_DISABLED to remove all the anonymous functionality
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// and use the stub functions implemented later in this file.
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soometypedef struct AnonInfoResourceRecord_struct AnonInfoResourceRecord;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSlocal mDNSBool InitializeNSEC3Record(ResourceRecord *rr, const mDNSu8 *AnonData, int len, mDNSu32 salt)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome rdataNSEC3 *nsec3 = (rdataNSEC3 *)rr->rdata->u.data;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // Construct the RDATA first and construct the owner name based on that.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("InitializeNSEC3Record: %x%x%x%x, name %##s", ptr[0], ptr[1], ptr[2], ptr[3], rr->name->c);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // Set the RDATA
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // hashLength, nxt, bitmap
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *tmp++ = NSEC_MCAST_WINDOW_SIZE; // window length
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSPlatformMemZero(tmp, NSEC_MCAST_WINDOW_SIZE);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome tmp[kDNSType_PTR >> 3] |= 128 >> (kDNSType_PTR & 7);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // Hash the base service name + salt + AnonData
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!NSEC3HashName(rr->name, nsec3, AnonData, len, hashName, &hlen))
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome LogMsg("InitializeNSEC3Record: NSEC3HashName failed for ##s", rr->name->c);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome LogMsg("InitializeNSEC3Record: hlen wrong %d", hlen);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSlocal ResourceRecord *ConstructNSEC3Record(const domainname *service, const mDNSu8 *AnonData, int len, mDNSu32 salt)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // We are just allocating an RData which has StandardAuthRDSize
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome LogMsg("ConstructNSEC3Record: StandardAuthRDSize %d smaller than MCAST_NSEC3_RDLENGTH %d", StandardAuthRDSize, MCAST_NSEC3_RDLENGTH);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // Allocate space for the name and RData.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome rr = mDNSPlatformMemAllocate(sizeof(ResourceRecord) + dlen + sizeof(RData));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome name = (domainname *)((mDNSu8 *)rr + sizeof(ResourceRecord));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome rr->rdata = (RData *)((mDNSu8 *)rr->name + dlen);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!InitializeNSEC3Record(rr, AnonData, len, salt))
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSlocal ResourceRecord *CopyNSEC3ResourceRecord(AnonymousInfo *si, const ResourceRecord *rr)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome LogMsg("CopyNSEC3ResourceRecord: rdlength %d smaller than MCAST_NSEC3_RDLENGTH %d", rr->rdlength, MCAST_NSEC3_RDLENGTH);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // Allocate space for the name and the rdata along with the ResourceRecord
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome neededLen = rr->rdlength + DomainNameLength(rr->name);
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome extraLen = (neededLen > sizeof(RDataBody)) ? (neededLen - sizeof(RDataBody)) : 0;
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome anonRR = (AnonInfoResourceRecord *)mDNSPlatformMemAllocate(sizeof(AnonInfoResourceRecord) + extraLen);
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome anonRR->rdatastorage.MaxRDLength = rr->rdlength;
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome mDNSPlatformMemCopy(anonRR->rdatastorage.u.data, rr->rdata->u.data, rr->rdlength);
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome name = (domainname *)(anonRR->rdatastorage.u.data + rr->rdlength);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// When a service is started or a browse is started with the Anonymous data, we allocate a new random
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// number and based on that allocate a new NSEC3 resource record whose hash is a function of random number (salt) and
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// the anonymous data.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// If we receive a packet with the NSEC3 option, we need to cache that along with the resource record so that we can
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// check against the question to see whether it answers them or not. In that case, we pass the "rr" that we received.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport AnonymousInfo *AllocateAnonInfo(const domainname *service, const mDNSu8 *data, int len, const ResourceRecord *rr)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ai = (AnonymousInfo *)mDNSPlatformMemAllocate(sizeof(AnonymousInfo));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSPlatformMemZero(ai, sizeof(AnonymousInfo));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ai->nsec3RR = ConstructNSEC3Record(service, data, len, ai->salt);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport void ReInitAnonInfo(AnonymousInfo **AnonInfo, const domainname *name)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *AnonInfo = AllocateAnonInfo(name, ai->AnonData, ai->AnonDataLen, mDNSNULL);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// This function should be used only if you know that the question and
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// the resource record belongs to the same set. The main usage is
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// in ProcessQuery where we find the question to be part of the same
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// set as the resource record, but it needs the AnonData to be
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// initialized so that it can walk the cache records to see if they
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// answer the question.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport void SetAnonData(DNSQuestion *q, ResourceRecord *rr, mDNSBool ForQuestion)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome LogMsg("SetAnonData: question %##s(%p), rr %##s(%p), NULL", q->qname.c, q->AnonInfo, rr->name->c, rr->AnonInfo);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("SetAnonData: question %##s(%p), rr %##s(%p)", q->qname.c, q->AnonInfo, rr->name->c, rr->AnonInfo);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome q->AnonInfo->AnonData = mDNSPlatformMemAllocate(rr->AnonInfo->AnonDataLen);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSPlatformMemCopy(q->AnonInfo->AnonData, rr->AnonInfo->AnonData, rr->AnonInfo->AnonDataLen);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome q->AnonInfo->AnonDataLen = rr->AnonInfo->AnonDataLen;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome rr->AnonInfo->AnonData = mDNSPlatformMemAllocate(q->AnonInfo->AnonDataLen);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSPlatformMemCopy(rr->AnonInfo->AnonData, q->AnonInfo->AnonData, q->AnonInfo->AnonDataLen);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome rr->AnonInfo->AnonDataLen = q->AnonInfo->AnonDataLen;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// returns -1 if the caller should ignore the result
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// returns 1 if the record answers the question
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// returns 0 if the record does not answer the question
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport int AnonInfoAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("AnonInfoAnswersQuestion: question qname %##s", q->qname.c);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // Currently only PTR records can have anonymous information
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // We allow anonymous questions to be answered by both normal services (without the
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // anonymous information) and anonymous services that are part of the same set. And
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // normal questions discover normal services and all anonymous services.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // The three cases have been enumerated clearly even though they all behave the
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // same way.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("AnonInfoAnswersQuestion: not a anonymous type question");
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("AnonInfoAnswersQuestion: Question %##s not answered using anonymous record %##s", q->qname.c, rr->name->c);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("AnonInfoAnswersQuestion: not a anonymous type record");
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // case 4: We have the anonymous information both in the question and the record. We need
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // two sets of information to validate.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // 1) Anonymous data that identifies the set/group
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // 2) NSEC3 record that contains the hash and the salt
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // If the question is a remote one, it does not have the anonymous information to validate (just
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // the NSEC3 record) and hence the anonymous data should come from the local resource record. If the
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // question is local, it can come from either of them and if there is a mismatch between the
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // question and record, it won't validate.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // Before a cache record is created, if there is a matching question i.e., part
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // of the same set, then when the cache is created we also set the anonymous
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // information. Otherwise, the cache record contains just the NSEC3 record and we
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // won't be here for that case.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // It is also possible that a local question is matched against the local AuthRecord
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // as that is also the case for which the AnonData would be non-NULL for both.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // We match questions against AuthRecords (rather than the cache) for LocalOnly case and
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // to see whether a .local query should be suppressed or not. The latter never happens
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // because PTR queries are never suppressed.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // If they don't belong to the same anonymous set, then no point in validating.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSPlatformMemCmp(qai->AnonData, rai->AnonData, qai->AnonDataLen) != 0)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("AnonInfoAnswersQuestion: AnonData mis-match for record %s question %##s ",
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome RRDisplayString(&mDNSStorage, rr), q->qname.c);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // AnonData matches i.e they belong to the same group and the same service.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome LogInfo("AnonInfoAnswersQuestion: Answering qname %##s, rname %##s, without validation", q->qname.c,
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("AnonInfoAnswersQuestion: question %p, record %p", qai->AnonData, rai->AnonData);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // If there is AnonData, then this is a local question. The
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // NSEC3 RR comes from the resource record which could be part
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // of the cache or local auth record. The cache entry could
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // be from a remote host or created when we heard our own
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // announcements. In any case, we use that to see if it matches
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // the question.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // Remote question or hearing our own question back
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // AnonData can be NULL for the cache entry and if we are hearing our own question back, AnonData is NULL for
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // that too and we can end up here for that case.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("AnonInfoAnswersQuestion: AnonData %p or nsec3RR %p, NULL for question %##s, record %s", AnonData, nsec3RR,
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome q->qname.c, RRDisplayString(&mDNSStorage, rr));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("AnonInfoAnswersQuestion: Validating question %##s, ResourceRecord %s", q->qname.c, RRDisplayString(&mDNSStorage, nsec3RR));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!NSEC3HashName(nsec3RR->name, nsec3, AnonData, AnonDataLen, hashName, &hlen))
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome LogMsg("AnonInfoAnswersQuestion: NSEC3HashName failed for ##s", nsec3RR->name->c);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome LogMsg("AnonInfoAnswersQuestion: hlen wrong %d", hlen);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome NSEC3Parse(nsec3RR, mDNSNULL, &nxtLength, &nxtName, mDNSNULL, mDNSNULL);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome LogMsg("AnonInfoAnswersQuestion: ERROR!! hlen %d not same as nxtLength %d", hlen, nxtLength);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome for (i = 0; i < nxtLength; i++)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("AnonInfoAnswersQuestion: mismatch output %x, digest %x, i %d", nxtName[i+1], hashName[i], i);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome LogInfo("AnonInfoAnswersQuestion: ResourceRecord %s matched question %##s (%s)", RRDisplayString(&mDNSStorage, nsec3RR), q->qname.c, DNSTypeName(q->qtype));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// Find a matching NSEC3 record for the name. We parse the questions and the records in the packet in order.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// Similarly we also parse the NSEC3 records in order and this mapping to the questions and records
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// respectively.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSlocal CacheRecord *FindMatchingNSEC3ForName(mDNS *const m, CacheRecord **nsec3, const domainname *name)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("FindMatchingNSEC3ForName: NSEC3 record %s matched %##s", CRDisplayString(m, cr), name->c);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport void InitializeAnonInfoForQuestion(mDNS *const m, CacheRecord **McastNSEC3Records, DNSQuestion *q)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome nsec3CR = FindMatchingNSEC3ForName(m, McastNSEC3Records, &q->qname);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome q->AnonInfo = AllocateAnonInfo(mDNSNULL, mDNSNULL, 0, &nsec3CR->resrec);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("InitializeAnonInfoForQuestion: Found a matching NSEC3 record %s, for %##s (%s)",
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome RRDisplayString(m, q->AnonInfo->nsec3RR), q->qname.c, DNSTypeName(q->qtype));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport void InitializeAnonInfoForCR(mDNS *const m, CacheRecord **McastNSEC3Records, CacheRecord *cr)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // If already initialized or not a PTR type, we don't have to do anything
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (cr->resrec.AnonInfo || cr->resrec.rrtype != kDNSType_PTR)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome nsec3CR = FindMatchingNSEC3ForName(m, McastNSEC3Records, cr->resrec.name);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome cr->resrec.AnonInfo = AllocateAnonInfo(mDNSNULL, mDNSNULL, 0, &nsec3CR->resrec);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("InitializeAnonInfoForCR: Found a matching NSEC3 record %s, for %##s (%s)",
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome RRDisplayString(m, cr->resrec.AnonInfo->nsec3RR), cr->resrec.name->c,
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport mDNSBool IdenticalAnonInfo(AnonymousInfo *a1, AnonymousInfo *a2)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // if a1 is NULL and a2 is not NULL AND vice-versa
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // return false as there is a change.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // Both could be NULL or non-NULL
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // The caller already verified that the owner name is the same.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // Check whether the RData is same.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!IdenticalSameNameRecord(a1->nsec3RR, a2->nsec3RR))
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport void CopyAnonInfoForCR(mDNS *const m, CacheRecord *crto, CacheRecord *crfrom)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome AnonymousInfo *aifrom = crfrom->resrec.AnonInfo;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome#else // !ANONYMOUS_DISABLED
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport void ReInitAnonInfo(AnonymousInfo **si, const domainname *name)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport AnonymousInfo * AllocateAnonInfo(const domainname *service, const mDNSu8 *AnonData, int len, const ResourceRecord *rr)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport void SetAnonData(DNSQuestion *q, ResourceRecord *rr, mDNSBool ForQuestion)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport int AnonInfoAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport void InitializeAnonInfoForQuestion(mDNS *const m, CacheRecord **McastNSEC3Records, DNSQuestion *q)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport void InitializeAnonInfoForCR(mDNS *const m, CacheRecord **McastNSEC3Records, CacheRecord *cr)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport void CopyAnonInfoForCR(mDNS *const m, CacheRecord *crto, CacheRecord *crfrom)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport mDNSBool IdenticalAnonInfo(AnonymousInfo *a1, AnonymousInfo *a2)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome#endif // !ANONYMOUS_DISABLED