1 | /* -*- Mode: C; tab-width: 4 -*- |
---|
2 | * |
---|
3 | * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. |
---|
4 | * |
---|
5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
---|
6 | * you may not use this file except in compliance with the License. |
---|
7 | * You may obtain a copy of the License at |
---|
8 | * |
---|
9 | * http://www.apache.org/licenses/LICENSE-2.0 |
---|
10 | * |
---|
11 | * Unless required by applicable law or agreed to in writing, software |
---|
12 | * distributed under the License is distributed on an "AS IS" BASIS, |
---|
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
---|
14 | * See the License for the specific language governing permissions and |
---|
15 | * limitations under the License. |
---|
16 | */ |
---|
17 | |
---|
18 | #ifndef __DNSCOMMON_H_ |
---|
19 | #define __DNSCOMMON_H_ |
---|
20 | |
---|
21 | #include "mDNSEmbeddedAPI.h" |
---|
22 | |
---|
23 | #ifdef __cplusplus |
---|
24 | extern "C" { |
---|
25 | #endif |
---|
26 | |
---|
27 | //************************************************************************************************************* |
---|
28 | // Macros |
---|
29 | |
---|
30 | // Note: The C preprocessor stringify operator ('#') makes a string from its argument, without macro expansion |
---|
31 | // e.g. If "version" is #define'd to be "4", then STRINGIFY_AWE(version) will return the string "version", not "4" |
---|
32 | // To expand "version" to its value before making the string, use STRINGIFY(version) instead |
---|
33 | #define STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) # s |
---|
34 | #define STRINGIFY(s) STRINGIFY_ARGUMENT_WITHOUT_EXPANSION(s) |
---|
35 | |
---|
36 | // *************************************************************************** |
---|
37 | #if COMPILER_LIKES_PRAGMA_MARK |
---|
38 | #pragma mark - DNS Protocol Constants |
---|
39 | #endif |
---|
40 | |
---|
41 | typedef enum |
---|
42 | { |
---|
43 | kDNSFlag0_QR_Mask = 0x80, // Query or response? |
---|
44 | kDNSFlag0_QR_Query = 0x00, |
---|
45 | kDNSFlag0_QR_Response = 0x80, |
---|
46 | |
---|
47 | kDNSFlag0_OP_Mask = 0x78, // Operation type |
---|
48 | kDNSFlag0_OP_StdQuery = 0x00, |
---|
49 | kDNSFlag0_OP_Iquery = 0x08, |
---|
50 | kDNSFlag0_OP_Status = 0x10, |
---|
51 | kDNSFlag0_OP_Unused3 = 0x18, |
---|
52 | kDNSFlag0_OP_Notify = 0x20, |
---|
53 | kDNSFlag0_OP_Update = 0x28, |
---|
54 | |
---|
55 | kDNSFlag0_QROP_Mask = kDNSFlag0_QR_Mask | kDNSFlag0_OP_Mask, |
---|
56 | |
---|
57 | kDNSFlag0_AA = 0x04, // Authoritative Answer? |
---|
58 | kDNSFlag0_TC = 0x02, // Truncated? |
---|
59 | kDNSFlag0_RD = 0x01, // Recursion Desired? |
---|
60 | kDNSFlag1_RA = 0x80, // Recursion Available? |
---|
61 | |
---|
62 | kDNSFlag1_Zero = 0x40, // Reserved; must be zero |
---|
63 | kDNSFlag1_AD = 0x20, // Authentic Data [RFC 2535] |
---|
64 | kDNSFlag1_CD = 0x10, // Checking Disabled [RFC 2535] |
---|
65 | |
---|
66 | kDNSFlag1_RC_Mask = 0x0F, // Response code |
---|
67 | kDNSFlag1_RC_NoErr = 0x00, |
---|
68 | kDNSFlag1_RC_FormErr = 0x01, |
---|
69 | kDNSFlag1_RC_ServFail = 0x02, |
---|
70 | kDNSFlag1_RC_NXDomain = 0x03, |
---|
71 | kDNSFlag1_RC_NotImpl = 0x04, |
---|
72 | kDNSFlag1_RC_Refused = 0x05, |
---|
73 | kDNSFlag1_RC_YXDomain = 0x06, |
---|
74 | kDNSFlag1_RC_YXRRSet = 0x07, |
---|
75 | kDNSFlag1_RC_NXRRSet = 0x08, |
---|
76 | kDNSFlag1_RC_NotAuth = 0x09, |
---|
77 | kDNSFlag1_RC_NotZone = 0x0A |
---|
78 | } DNS_Flags; |
---|
79 | |
---|
80 | typedef enum |
---|
81 | { |
---|
82 | TSIG_ErrBadSig = 16, |
---|
83 | TSIG_ErrBadKey = 17, |
---|
84 | TSIG_ErrBadTime = 18 |
---|
85 | } TSIG_ErrorCode; |
---|
86 | |
---|
87 | // *************************************************************************** |
---|
88 | #if COMPILER_LIKES_PRAGMA_MARK |
---|
89 | #pragma mark - |
---|
90 | #pragma mark - General Utility Functions |
---|
91 | #endif |
---|
92 | |
---|
93 | extern NetworkInterfaceInfo *GetFirstActiveInterface(NetworkInterfaceInfo *intf); |
---|
94 | extern mDNSInterfaceID GetNextActiveInterfaceID(const NetworkInterfaceInfo *intf); |
---|
95 | |
---|
96 | extern mDNSu32 mDNSRandom(mDNSu32 max); // Returns pseudo-random result from zero to max inclusive |
---|
97 | |
---|
98 | // *************************************************************************** |
---|
99 | #if COMPILER_LIKES_PRAGMA_MARK |
---|
100 | #pragma mark - |
---|
101 | #pragma mark - Domain Name Utility Functions |
---|
102 | #endif |
---|
103 | |
---|
104 | #define mDNSSubTypeLabel "\x04_sub" |
---|
105 | |
---|
106 | #define mDNSIsDigit(X) ((X) >= '0' && (X) <= '9') |
---|
107 | #define mDNSIsUpperCase(X) ((X) >= 'A' && (X) <= 'Z') |
---|
108 | #define mDNSIsLowerCase(X) ((X) >= 'a' && (X) <= 'z') |
---|
109 | #define mDNSIsLetter(X) (mDNSIsUpperCase(X) || mDNSIsLowerCase(X)) |
---|
110 | |
---|
111 | #define mDNSValidHostChar(X, notfirst, notlast) (mDNSIsLetter(X) || mDNSIsDigit(X) || ((notfirst) && (notlast) && (X) == '-') ) |
---|
112 | |
---|
113 | extern mDNSu16 CompressedDomainNameLength(const domainname *const name, const domainname *parent); |
---|
114 | extern int CountLabels(const domainname *d); |
---|
115 | extern const domainname *SkipLeadingLabels(const domainname *d, int skip); |
---|
116 | |
---|
117 | extern mDNSu32 TruncateUTF8ToLength(mDNSu8 *string, mDNSu32 length, mDNSu32 max); |
---|
118 | extern mDNSBool LabelContainsSuffix(const domainlabel *const name, const mDNSBool RichText); |
---|
119 | extern mDNSu32 RemoveLabelSuffix(domainlabel *name, mDNSBool RichText); |
---|
120 | extern void AppendLabelSuffix(domainlabel *const name, mDNSu32 val, const mDNSBool RichText); |
---|
121 | #define ValidateDomainName(N) (DomainNameLength(N) <= MAX_DOMAIN_NAME) |
---|
122 | |
---|
123 | // *************************************************************************** |
---|
124 | #if COMPILER_LIKES_PRAGMA_MARK |
---|
125 | #pragma mark - |
---|
126 | #pragma mark - Resource Record Utility Functions |
---|
127 | #endif |
---|
128 | |
---|
129 | // IdenticalResourceRecord returns true if two resources records have |
---|
130 | // the same name, type, class, and identical rdata (InterfaceID and TTL may differ) |
---|
131 | |
---|
132 | // IdenticalSameNameRecord is the same, except it skips the expensive SameDomainName() check, |
---|
133 | // which is at its most expensive and least useful in cases where we know in advance that the names match |
---|
134 | |
---|
135 | // Note: The dominant use of IdenticalResourceRecord is from ProcessQuery(), handling known-answer lists. In this case |
---|
136 | // it's common to have a whole bunch or records with exactly the same name (e.g. "_http._tcp.local") but different RDATA. |
---|
137 | // The SameDomainName() check is expensive when the names match, and in this case *all* the names match, so we |
---|
138 | // used to waste a lot of CPU time verifying that the names match, only then to find that the RDATA is different. |
---|
139 | // We observed mDNSResponder spending 30% of its total CPU time on this single task alone. |
---|
140 | // By swapping the checks so that we check the RDATA first, we can quickly detect when it's different |
---|
141 | // (99% of the time) and then bail out before we waste time on the expensive SameDomainName() check. |
---|
142 | |
---|
143 | #define IdenticalResourceRecord(r1,r2) ( \ |
---|
144 | (r1)->rrtype == (r2)->rrtype && \ |
---|
145 | (r1)->rrclass == (r2)->rrclass && \ |
---|
146 | (r1)->namehash == (r2)->namehash && \ |
---|
147 | (r1)->rdlength == (r2)->rdlength && \ |
---|
148 | (r1)->rdatahash == (r2)->rdatahash && \ |
---|
149 | SameRDataBody((r1), &(r2)->rdata->u, SameDomainName) && \ |
---|
150 | SameDomainName((r1)->name, (r2)->name)) |
---|
151 | |
---|
152 | #define IdenticalSameNameRecord(r1,r2) ( \ |
---|
153 | (r1)->rrtype == (r2)->rrtype && \ |
---|
154 | (r1)->rrclass == (r2)->rrclass && \ |
---|
155 | (r1)->rdlength == (r2)->rdlength && \ |
---|
156 | (r1)->rdatahash == (r2)->rdatahash && \ |
---|
157 | SameRDataBody((r1), &(r2)->rdata->u, SameDomainName)) |
---|
158 | |
---|
159 | // A given RRType answers a QuestionType if RRType is CNAME, or types match, or QuestionType is ANY, |
---|
160 | // or the RRType is NSEC and positively asserts the nonexistence of the type being requested |
---|
161 | #define RRTypeAnswersQuestionType(R,Q) ((R)->rrtype == kDNSType_CNAME || (R)->rrtype == (Q) || (Q) == kDNSQType_ANY || RRAssertsNonexistence((R),(Q))) |
---|
162 | // Unicast NSEC records have the NSEC bit set whereas the multicast NSEC ones don't |
---|
163 | #define UNICAST_NSEC(rr) ((rr)->rrtype == kDNSType_NSEC && RRAssertsExistence((rr), kDNSType_NSEC)) |
---|
164 | |
---|
165 | extern mDNSu32 RDataHashValue(const ResourceRecord *const rr); |
---|
166 | extern mDNSBool SameRDataBody(const ResourceRecord *const r1, const RDataBody *const r2, DomainNameComparisonFn *samename); |
---|
167 | extern mDNSBool SameNameRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q); |
---|
168 | extern mDNSBool ResourceRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q); |
---|
169 | extern mDNSBool AnyTypeRecordAnswersQuestion (const ResourceRecord *const rr, const DNSQuestion *const q); |
---|
170 | extern mDNSBool ResourceRecordAnswersUnicastResponse(const ResourceRecord *const rr, const DNSQuestion *const q); |
---|
171 | extern mDNSBool LocalOnlyRecordAnswersQuestion(AuthRecord *const rr, const DNSQuestion *const q); |
---|
172 | extern mDNSu16 GetRDLength(const ResourceRecord *const rr, mDNSBool estimate); |
---|
173 | extern mDNSBool ValidateRData(const mDNSu16 rrtype, const mDNSu16 rdlength, const RData *const rd); |
---|
174 | extern mStatus DNSNameToLowerCase(domainname *d, domainname *result); |
---|
175 | |
---|
176 | #define GetRRDomainNameTarget(RR) ( \ |
---|
177 | ((RR)->rrtype == kDNSType_NS || (RR)->rrtype == kDNSType_CNAME || (RR)->rrtype == kDNSType_PTR || (RR)->rrtype == kDNSType_DNAME) ? &(RR)->rdata->u.name : \ |
---|
178 | ((RR)->rrtype == kDNSType_MX || (RR)->rrtype == kDNSType_AFSDB || (RR)->rrtype == kDNSType_RT || (RR)->rrtype == kDNSType_KX ) ? &(RR)->rdata->u.mx.exchange : \ |
---|
179 | ((RR)->rrtype == kDNSType_SRV ) ? &(RR)->rdata->u.srv.target : mDNSNULL ) |
---|
180 | |
---|
181 | #define LocalRecordReady(X) ((X)->resrec.RecordType != kDNSRecordTypeUnique) |
---|
182 | |
---|
183 | // *************************************************************************** |
---|
184 | #if COMPILER_LIKES_PRAGMA_MARK |
---|
185 | #pragma mark - |
---|
186 | #pragma mark - DNS Message Creation Functions |
---|
187 | #endif |
---|
188 | |
---|
189 | extern void InitializeDNSMessage(DNSMessageHeader *h, mDNSOpaque16 id, mDNSOpaque16 flags); |
---|
190 | extern const mDNSu8 *FindCompressionPointer(const mDNSu8 *const base, const mDNSu8 *const end, const mDNSu8 *const domname); |
---|
191 | extern mDNSu8 *putDomainNameAsLabels(const DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, const domainname *const name); |
---|
192 | extern mDNSu8 *putRData(const DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, const ResourceRecord *const rr); |
---|
193 | |
---|
194 | // If we have a single large record to put in the packet, then we allow the packet to be up to 9K bytes, |
---|
195 | // but in the normal case we try to keep the packets below 1500 to avoid IP fragmentation on standard Ethernet |
---|
196 | |
---|
197 | #define AllowedRRSpace(msg) (((msg)->h.numAnswers || (msg)->h.numAuthorities || (msg)->h.numAdditionals) ? NormalMaxDNSMessageData : AbsoluteMaxDNSMessageData) |
---|
198 | |
---|
199 | extern mDNSu8 *PutResourceRecordTTLWithLimit(DNSMessage *const msg, mDNSu8 *ptr, mDNSu16 *count, ResourceRecord *rr, mDNSu32 ttl, const mDNSu8 *limit); |
---|
200 | |
---|
201 | #define PutResourceRecordTTL(msg, ptr, count, rr, ttl) \ |
---|
202 | PutResourceRecordTTLWithLimit((msg), (ptr), (count), (rr), (ttl), (msg)->data + AllowedRRSpace(msg)) |
---|
203 | |
---|
204 | #define PutResourceRecordTTLJumbo(msg, ptr, count, rr, ttl) \ |
---|
205 | PutResourceRecordTTLWithLimit((msg), (ptr), (count), (rr), (ttl), (msg)->data + AbsoluteMaxDNSMessageData) |
---|
206 | |
---|
207 | #define PutResourceRecord(MSG, P, C, RR) PutResourceRecordTTL((MSG), (P), (C), (RR), (RR)->rroriginalttl) |
---|
208 | |
---|
209 | // The PutRR_OS variants assume a local variable 'm', put build the packet at m->omsg, |
---|
210 | // and assume local variables 'OwnerRecordSpace' & 'TraceRecordSpace' indicating how many bytes (if any) to reserve to add an OWNER/TRACER option at the end |
---|
211 | #define PutRR_OS_TTL(ptr, count, rr, ttl) \ |
---|
212 | PutResourceRecordTTLWithLimit(&m->omsg, (ptr), (count), (rr), (ttl), m->omsg.data + AllowedRRSpace(&m->omsg) - OwnerRecordSpace - TraceRecordSpace) |
---|
213 | |
---|
214 | #define PutRR_OS(P, C, RR) PutRR_OS_TTL((P), (C), (RR), (RR)->rroriginalttl) |
---|
215 | |
---|
216 | extern mDNSu8 *putQuestion(DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, const domainname *const name, mDNSu16 rrtype, mDNSu16 rrclass); |
---|
217 | extern mDNSu8 *putZone(DNSMessage *const msg, mDNSu8 *ptr, mDNSu8 *limit, const domainname *zone, mDNSOpaque16 zoneClass); |
---|
218 | extern mDNSu8 *putPrereqNameNotInUse(const domainname *const name, DNSMessage *const msg, mDNSu8 *const ptr, mDNSu8 *const end); |
---|
219 | extern mDNSu8 *putDeletionRecord(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *rr); |
---|
220 | extern mDNSu8 *putDeletionRecordWithLimit(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *rr, mDNSu8 *limit); |
---|
221 | extern mDNSu8 *putDeleteRRSetWithLimit(DNSMessage *msg, mDNSu8 *ptr, const domainname *name, mDNSu16 rrtype, mDNSu8 *limit); |
---|
222 | extern mDNSu8 *putDeleteAllRRSets(DNSMessage *msg, mDNSu8 *ptr, const domainname *name); |
---|
223 | extern mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *ptr, mDNSu32 lease); |
---|
224 | extern mDNSu8 *putUpdateLeaseWithLimit(DNSMessage *msg, mDNSu8 *ptr, mDNSu32 lease, mDNSu8 *limit); |
---|
225 | |
---|
226 | extern mDNSu8 *putHINFO(const mDNS *const m, DNSMessage *const msg, mDNSu8 *ptr, DomainAuthInfo *authInfo, mDNSu8 *limit); |
---|
227 | extern mDNSu8 *putDNSSECOption(DNSMessage *msg, mDNSu8 *end, mDNSu8 *limit); |
---|
228 | extern int baseEncode(char *buffer, int blen, const mDNSu8 *data, int len, int encAlg); |
---|
229 | extern void NSEC3Parse(const ResourceRecord *const rr, mDNSu8 **salt, int *hashLength, mDNSu8 **nxtName, int *bitmaplen, mDNSu8 **bitmap); |
---|
230 | |
---|
231 | extern const mDNSu8 *NSEC3HashName(const domainname *name, rdataNSEC3 *nsec3, const mDNSu8 *AnonData, int AnonDataLen, |
---|
232 | const mDNSu8 hash[NSEC3_MAX_HASH_LEN], int *dlen); |
---|
233 | |
---|
234 | // *************************************************************************** |
---|
235 | #if COMPILER_LIKES_PRAGMA_MARK |
---|
236 | #pragma mark - |
---|
237 | #pragma mark - DNS Message Parsing Functions |
---|
238 | #endif |
---|
239 | |
---|
240 | #define AuthHashSlot(X) (DomainNameHashValue(X) % AUTH_HASH_SLOTS) |
---|
241 | #define HashSlot(X) (DomainNameHashValue(X) % CACHE_HASH_SLOTS) |
---|
242 | extern mDNSu32 DomainNameHashValue(const domainname *const name); |
---|
243 | extern void SetNewRData(ResourceRecord *const rr, RData *NewRData, mDNSu16 rdlength); |
---|
244 | extern const mDNSu8 *skipDomainName(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end); |
---|
245 | extern const mDNSu8 *getDomainName(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end, |
---|
246 | domainname *const name); |
---|
247 | extern const mDNSu8 *skipResourceRecord(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end); |
---|
248 | extern const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage * const msg, const mDNSu8 *ptr, |
---|
249 | const mDNSu8 * end, const mDNSInterfaceID InterfaceID, mDNSu8 RecordType, LargeCacheRecord *const largecr); |
---|
250 | extern mDNSBool SetRData(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *end, |
---|
251 | LargeCacheRecord *const largecr, mDNSu16 rdlength); |
---|
252 | extern const mDNSu8 *skipQuestion(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end); |
---|
253 | extern const mDNSu8 *getQuestion(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end, const mDNSInterfaceID InterfaceID, |
---|
254 | DNSQuestion *question); |
---|
255 | extern const mDNSu8 *LocateAnswers(const DNSMessage *const msg, const mDNSu8 *const end); |
---|
256 | extern const mDNSu8 *LocateAuthorities(const DNSMessage *const msg, const mDNSu8 *const end); |
---|
257 | extern const mDNSu8 *LocateAdditionals(const DNSMessage *const msg, const mDNSu8 *const end); |
---|
258 | extern const mDNSu8 *LocateOptRR(const DNSMessage *const msg, const mDNSu8 *const end, int minsize); |
---|
259 | extern const rdataOPT *GetLLQOptData(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end); |
---|
260 | extern mDNSu32 GetPktLease(mDNS *m, DNSMessage *msg, const mDNSu8 *end); |
---|
261 | extern void DumpPacket(mDNS *const m, mStatus status, mDNSBool sent, char *transport, |
---|
262 | const mDNSAddr *srcaddr, mDNSIPPort srcport, |
---|
263 | const mDNSAddr *dstaddr, mDNSIPPort dstport, const DNSMessage *const msg, const mDNSu8 *const end); |
---|
264 | extern mDNSBool RRAssertsNonexistence(const ResourceRecord *const rr, mDNSu16 type); |
---|
265 | extern mDNSBool RRAssertsExistence(const ResourceRecord *const rr, mDNSu16 type); |
---|
266 | extern mDNSBool BitmapTypeCheck(mDNSu8 *bmap, int bitmaplen, mDNSu16 type); |
---|
267 | |
---|
268 | extern mDNSu16 swap16(mDNSu16 x); |
---|
269 | extern mDNSu32 swap32(mDNSu32 x); |
---|
270 | |
---|
271 | // *************************************************************************** |
---|
272 | #if COMPILER_LIKES_PRAGMA_MARK |
---|
273 | #pragma mark - |
---|
274 | #pragma mark - Packet Sending Functions |
---|
275 | #endif |
---|
276 | |
---|
277 | extern mStatus mDNSSendDNSMessage(mDNS *const m, DNSMessage *const msg, mDNSu8 *end, |
---|
278 | mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, |
---|
279 | mDNSIPPort dstport, TCPSocket *sock, DomainAuthInfo *authInfo, |
---|
280 | mDNSBool useBackgroundTrafficClass); |
---|
281 | |
---|
282 | // *************************************************************************** |
---|
283 | #if COMPILER_LIKES_PRAGMA_MARK |
---|
284 | #pragma mark - |
---|
285 | #pragma mark - RR List Management & Task Management |
---|
286 | #endif |
---|
287 | |
---|
288 | extern void ShowTaskSchedulingError(mDNS *const m); |
---|
289 | extern void mDNS_Lock_(mDNS *const m, const char * const functionname); |
---|
290 | extern void mDNS_Unlock_(mDNS *const m, const char * const functionname); |
---|
291 | |
---|
292 | #if defined(_WIN32) |
---|
293 | #define __func__ __FUNCTION__ |
---|
294 | #endif |
---|
295 | |
---|
296 | #define mDNS_Lock(X) mDNS_Lock_((X), __func__) |
---|
297 | |
---|
298 | #define mDNS_Unlock(X) mDNS_Unlock_((X), __func__) |
---|
299 | |
---|
300 | #define mDNS_CheckLock(X) \ |
---|
301 | if ((X)->mDNS_busy != (X)->mDNS_reentrancy+1) LogMsg("%s: Lock not held! mDNS_busy (%ld) mDNS_reentrancy (%ld)", __func__, (X)->mDNS_busy, (X)->mDNS_reentrancy) |
---|
302 | |
---|
303 | #define mDNS_DropLockBeforeCallback() do { m->mDNS_reentrancy++; \ |
---|
304 | if (m->mDNS_busy != m->mDNS_reentrancy) LogMsg("%s: Locking Failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", __func__, m->mDNS_busy, m->mDNS_reentrancy); \ |
---|
305 | } while (0) |
---|
306 | |
---|
307 | #define mDNS_ReclaimLockAfterCallback() do { \ |
---|
308 | if (m->mDNS_busy != m->mDNS_reentrancy) LogMsg("%s: Unlocking Failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", __func__, m->mDNS_busy, m->mDNS_reentrancy); \ |
---|
309 | m->mDNS_reentrancy--; } while (0) |
---|
310 | |
---|
311 | #ifdef __cplusplus |
---|
312 | } |
---|
313 | #endif |
---|
314 | |
---|
315 | #endif // __DNSCOMMON_H_ |
---|