xref: /titanic_51/usr/src/cmd/cmd-inet/usr.lib/mdnsd/DNSCommon.h (revision 0f1702c5201310f0529cd5abb77652e5e9b241b6)
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     Change History (most recent first):
18 
19 $Log: DNSCommon.h,v $
20 Revision 1.34.2.1  2006/08/29 06:24:22  cheshire
21 Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0
22 
23 Revision 1.34  2006/03/18 21:47:56  cheshire
24 <rdar://problem/4073825> Improve logic for delaying packets after repeated interface transitions
25 
26 Revision 1.33  2006/03/10 21:51:41  cheshire
27 <rdar://problem/4111464> After record update, old record sometimes remains in cache
28 Split out SameRDataBody() into a separate routine so it can be called from other code
29 
30 Revision 1.32  2005/03/21 00:33:51  shersche
31 <rdar://problem/4021486> Fix build warnings on Win32 platform
32 
33 Revision 1.31  2005/02/18 00:43:11  cheshire
34 <rdar://problem/4010245> mDNSResponder should auto-truncate service names that are too long
35 
36 Revision 1.30  2005/01/19 03:12:44  cheshire
37 Move LocalRecordReady() macro from mDNS.c to DNSCommon.h
38 
39 Revision 1.29  2004/12/15 02:11:22  ksekar
40 <rdar://problem/3917317> Don't check for Dynamic DNS hostname uniqueness
41 
42 Revision 1.28  2004/12/06 21:15:22  ksekar
43 <rdar://problem/3884386> mDNSResponder crashed in CheckServiceRegistrations
44 
45 Revision 1.27  2004/12/03 07:20:50  ksekar
46 <rdar://problem/3674208> Wide-Area: Registration of large TXT record fails
47 
48 Revision 1.26  2004/12/03 05:18:33  ksekar
49 <rdar://problem/3810596> mDNSResponder needs to return more specific TSIG errors
50 
51 Revision 1.25  2004/10/26 03:52:02  cheshire
52 Update checkin comments
53 
54 Revision 1.24  2004/10/23 01:16:00  cheshire
55 <rdar://problem/3851677> uDNS operations not always reliable on multi-homed hosts
56 
57 Revision 1.23  2004/10/03 23:18:58  cheshire
58 Move address comparison macros from DNSCommon.h to mDNSEmbeddedAPI.h
59 
60 Revision 1.22  2004/09/30 00:24:56  ksekar
61 <rdar://problem/3695802> Dynamically update default registration domains on config change
62 
63 Revision 1.21  2004/09/17 01:08:48  cheshire
64 Renamed mDNSClientAPI.h to mDNSEmbeddedAPI.h
65   The name "mDNSClientAPI.h" is misleading to new developers looking at this code. The interfaces
66   declared in that file are ONLY appropriate to single-address-space embedded applications.
67   For clients on general-purpose computers, the interfaces defined in dns_sd.h should be used.
68 
69 Revision 1.20  2004/09/17 00:49:51  cheshire
70 Get rid of now-unused GetResourceRecord -- the correct (safe) routine to use
71 is GetLargeResourceRecord
72 
73 Revision 1.19  2004/09/16 21:59:15  cheshire
74 For consistency with zerov6Addr, rename zeroIPAddr to zerov4Addr
75 
76 Revision 1.18  2004/09/16 02:29:39  cheshire
77 Moved mDNS_Lock/mDNS_Unlock to DNSCommon.c; Added necessary locking around
78 uDNS_ReceiveMsg, uDNS_StartQuery, uDNS_UpdateRecord, uDNS_RegisterService
79 
80 Revision 1.17  2004/09/14 23:27:46  cheshire
81 Fix compile errors
82 
83 Revision 1.16  2004/08/13 23:46:58  cheshire
84 "asyncronous" -> "asynchronous"
85 
86 Revision 1.15  2004/08/10 23:19:14  ksekar
87 <rdar://problem/3722542>: DNS Extension daemon for Wide Area Service Discovery
88 Moved routines/constants to allow extern access for garbage collection daemon
89 
90 Revision 1.14  2004/05/28 23:42:36  ksekar
91 <rdar://problem/3258021>: Feature: DNS server->client notification on record changes (#7805)
92 
93 Revision 1.13  2004/05/18 23:51:25  cheshire
94 Tidy up all checkin comments to use consistent "<rdar://problem/xxxxxxx>" format for bug numbers
95 
96 Revision 1.12  2004/04/22 04:03:59  cheshire
97 Headers should use "extern" declarations, not "mDNSexport"
98 
99 Revision 1.11  2004/04/14 23:09:28  ksekar
100 Support for TSIG signed dynamic updates.
101 
102 Revision 1.10  2004/03/13 01:57:33  ksekar
103 <rdar://problem/3192546>: DynDNS: Dynamic update of service records
104 
105 Revision 1.9  2004/02/21 08:56:58  bradley
106 Wrap prototypes with extern "C" for C++ builds.
107 
108 Revision 1.8  2004/02/06 23:04:18  ksekar
109 Basic Dynamic Update support via mDNS_Register (dissabled via
110 UNICAST_REGISTRATION #define)
111 
112 Revision 1.7  2004/02/03 19:47:36  ksekar
113 Added an asynchronous state machine mechanism to uDNS.c, including
114 calls to find the parent zone for a domain name.  Changes include code
115 in repository previously dissabled via "#if 0 incomplete".  Codepath
116 is currently unused, and will be called to create update records, etc.
117 
118 Revision 1.6  2004/01/27 20:15:22  cheshire
119 <rdar://problem/3541288>: Time to prune obsolete code for listening on port 53
120 
121 Revision 1.5  2004/01/24 03:40:56  cheshire
122 Move mDNSAddrIsDNSMulticast() from DNSCommon.h to mDNSEmbeddedAPI.h so embedded clients can use it
123 
124 Revision 1.4  2004/01/24 03:38:27  cheshire
125 Fix minor syntactic error: Headers should use "extern" declarations, not "mDNSexport"
126 
127 Revision 1.3  2004/01/23 23:23:14  ksekar
128 Added TCP support for truncated unicast messages.
129 
130 Revision 1.2  2004/01/21 21:12:23  cheshire
131 Add missing newline at end of file to make Unix tools happier
132 
133 Revision 1.1  2003/12/13 03:05:27  ksekar
134 <rdar://problem/3192548>: DynDNS: Unicast query of service records
135 
136 
137  */
138 
139 #pragma ident	"%Z%%M%	%I%	%E% SMI"
140 
141 #ifndef __DNSCOMMON_H_
142 #define __DNSCOMMON_H_
143 
144 #include "mDNSEmbeddedAPI.h"
145 
146 #ifdef	__cplusplus
147 	extern "C" {
148 #endif
149 
150 
151 // ***************************************************************************
152 #if COMPILER_LIKES_PRAGMA_MARK
153 #pragma mark - DNS Protocol Constants
154 #endif
155 
156 typedef enum
157 	{
158 	kDNSFlag0_QR_Mask     = 0x80,		// Query or response?
159 	kDNSFlag0_QR_Query    = 0x00,
160 	kDNSFlag0_QR_Response = 0x80,
161 
162 	kDNSFlag0_OP_Mask     = 0x78,		// Operation type
163 	kDNSFlag0_OP_StdQuery = 0x00,
164 	kDNSFlag0_OP_Iquery   = 0x08,
165 	kDNSFlag0_OP_Status   = 0x10,
166 	kDNSFlag0_OP_Unused3  = 0x18,
167 	kDNSFlag0_OP_Notify   = 0x20,
168 	kDNSFlag0_OP_Update   = 0x28,
169 
170 	kDNSFlag0_QROP_Mask   = kDNSFlag0_QR_Mask | kDNSFlag0_OP_Mask,
171 
172 	kDNSFlag0_AA          = 0x04,		// Authoritative Answer?
173 	kDNSFlag0_TC          = 0x02,		// Truncated?
174 	kDNSFlag0_RD          = 0x01,		// Recursion Desired?
175 	kDNSFlag1_RA          = 0x80,		// Recursion Available?
176 
177 	kDNSFlag1_Zero        = 0x40,		// Reserved; must be zero
178 	kDNSFlag1_AD          = 0x20,		// Authentic Data [RFC 2535]
179 	kDNSFlag1_CD          = 0x10,		// Checking Disabled [RFC 2535]
180 
181 	kDNSFlag1_RC          = 0x0F,		// Response code
182 	kDNSFlag1_RC_NoErr    = 0x00,
183 	kDNSFlag1_RC_FmtErr   = 0x01,
184 	kDNSFlag1_RC_SrvErr   = 0x02,
185 	kDNSFlag1_RC_NXDomain = 0x03,
186 	kDNSFlag1_RC_NotImpl  = 0x04,
187 	kDNSFlag1_RC_Refused  = 0x05,
188 	kDNSFlag1_RC_YXDomain = 0x06,
189 	kDNSFlag1_RC_YXRRSet  = 0x07,
190 	kDNSFlag1_RC_NXRRSet  = 0x08,
191 	kDNSFlag1_RC_NotAuth  = 0x09,
192 	kDNSFlag1_RC_NotZone  = 0x0A
193 	} DNS_Flags;
194 
195 typedef enum
196 	{
197 	TSIG_ErrBadSig  = 16,
198 	TSIG_ErrBadKey  = 17,
199 	TSIG_ErrBadTime = 18
200 	} TSIG_ErrorCode;
201 
202 
203 // ***************************************************************************
204 #if COMPILER_LIKES_PRAGMA_MARK
205 #pragma mark -
206 #pragma mark - General Utility Functions
207 #endif
208 
209 extern const NetworkInterfaceInfo *GetFirstActiveInterface(const NetworkInterfaceInfo *intf);
210 extern mDNSInterfaceID GetNextActiveInterfaceID(const NetworkInterfaceInfo *intf);
211 
212 extern mDNSu32 mDNSRandom(mDNSu32 max);
213 extern mDNSu32 mDNSRandomFromFixedSeed(mDNSu32 seed, mDNSu32 max);
214 
215 
216 // ***************************************************************************
217 #if COMPILER_LIKES_PRAGMA_MARK
218 #pragma mark -
219 #pragma mark - Domain Name Utility Functions
220 #endif
221 
222 #define mdnsIsDigit(X)     ((X) >= '0' && (X) <= '9')
223 #define mDNSIsUpperCase(X) ((X) >= 'A' && (X) <= 'Z')
224 #define mDNSIsLowerCase(X) ((X) >= 'a' && (X) <= 'z')
225 #define mdnsIsLetter(X)    (mDNSIsUpperCase(X) || mDNSIsLowerCase(X))
226 
227 #define mdnsValidHostChar(X, notfirst, notlast) (mdnsIsLetter(X) || mdnsIsDigit(X) || ((notfirst) && (notlast) && (X) == '-') )
228 
229 extern mDNSu16 CompressedDomainNameLength(const domainname *const name, const domainname *parent);
230 
231 extern mDNSu32 TruncateUTF8ToLength(mDNSu8 *string, mDNSu32 length, mDNSu32 max);
232 extern mDNSBool LabelContainsSuffix(const domainlabel *const name, const mDNSBool RichText);
233 extern mDNSu32 RemoveLabelSuffix(domainlabel *name, mDNSBool RichText);
234 extern void AppendLabelSuffix(domainlabel *name, mDNSu32 val, mDNSBool RichText);
235 extern void mDNS_HostNameCallback(mDNS *const m, AuthRecord *const rr, mStatus result);
236 #define ValidateDomainName(N) (DomainNameLength(N) <= MAX_DOMAIN_NAME)
237 
238 
239 // ***************************************************************************
240 #if COMPILER_LIKES_PRAGMA_MARK
241 #pragma mark -
242 #pragma mark - Resource Record Utility Functions
243 #endif
244 
245 extern mDNSu32 RDataHashValue(mDNSu16 const rdlength, const RDataBody *const rdb);
246 
247 extern mDNSBool SameRDataBody(const ResourceRecord *const r1, const RDataBody *const r2);
248 extern mDNSBool SameRData(const ResourceRecord *const r1, const ResourceRecord *const r2);
249 
250 extern mDNSBool ResourceRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
251 
252 extern mDNSBool SameResourceRecord(ResourceRecord *r1, ResourceRecord *r2);
253 
254 extern mDNSu16 GetRDLength(const ResourceRecord *const rr, mDNSBool estimate);
255 
256 #define GetRRDomainNameTarget(RR) (                                                                          \
257 	((RR)->rrtype == kDNSType_CNAME || (RR)->rrtype == kDNSType_PTR || (RR)->rrtype == kDNSType_NS)          \
258 	                                                                 ? &(RR)->rdata->u.name       :          \
259 	((RR)->rrtype == kDNSType_SRV                                  ) ? &(RR)->rdata->u.srv.target : mDNSNULL )
260 
261 extern mDNSBool ValidateRData(const mDNSu16 rrtype, const mDNSu16 rdlength, const RData *const rd);
262 #define LocalRecordReady(X) ((X)->resrec.RecordType != kDNSRecordTypeUnique && (X)->resrec.RecordType != kDNSRecordTypeDeregistering)
263 
264 
265 // ***************************************************************************
266 #if COMPILER_LIKES_PRAGMA_MARK
267 #pragma mark -
268 #pragma mark -
269 #pragma mark - DNS Message Creation Functions
270 #endif
271 
272 extern void InitializeDNSMessage(DNSMessageHeader *h, mDNSOpaque16 id, mDNSOpaque16 flags);
273 extern const mDNSu8 *FindCompressionPointer(const mDNSu8 *const base, const mDNSu8 *const end, const mDNSu8 *const domname);
274 
275 extern mDNSu8 *putDomainNameAsLabels(const DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, const domainname *const name);
276 
277 extern mDNSu8 *putRData(const DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, ResourceRecord *rr);
278 
279 // If we have a single large record to put in the packet, then we allow the packet to be up to 9K bytes,
280 // but in the normal case we try to keep the packets below 1500 to avoid IP fragmentation on standard Ethernet
281 
282 extern mDNSu8 *PutResourceRecordTTLWithLimit(DNSMessage *const msg, mDNSu8 *ptr, mDNSu16 *count, ResourceRecord *rr, mDNSu32 ttl, const mDNSu8 *limit);
283 
284 #define PutResourceRecordTTL(msg, ptr, count, rr, ttl) PutResourceRecordTTLWithLimit((msg), (ptr), (count), (rr), (ttl), \
285 	((msg)->h.numAnswers || (msg)->h.numAuthorities || (msg)->h.numAdditionals) ? (msg)->data + NormalMaxDNSMessageData : (msg)->data + AbsoluteMaxDNSMessageData)
286 
287 #define PutResourceRecordTTLJumbo(msg, ptr, count, rr, ttl) PutResourceRecordTTLWithLimit((msg), (ptr), (count), (rr), (ttl), \
288 	(msg)->data + AbsoluteMaxDNSMessageData)
289 
290 extern mDNSu8 *PutResourceRecordCappedTTL(DNSMessage *const msg, mDNSu8 *ptr, mDNSu16 *count, ResourceRecord *rr, mDNSu32 maxttl);
291 
292 extern mDNSu8 *putEmptyResourceRecord(DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, mDNSu16 *count, const AuthRecord *rr);
293 
294 extern mDNSu8 *putQuestion(DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, const domainname *const name, mDNSu16 rrtype, mDNSu16 rrclass);
295 
296 extern mDNSu8 *putZone(DNSMessage *const msg, mDNSu8 *ptr, mDNSu8 *limit, const domainname *zone, mDNSOpaque16 zoneClass);
297 
298 extern mDNSu8 *putPrereqNameNotInUse(domainname *name, DNSMessage *msg, mDNSu8 *ptr, mDNSu8 *end);
299 
300 extern mDNSu8 *putDeletionRecord(DNSMessage *msg, mDNSu8 *ptr, ResourceRecord *rr);
301 
302 extern  mDNSu8 *putDeleteRRSet(DNSMessage *msg, mDNSu8 *ptr, const domainname *name, mDNSu16 rrtype);
303 
304 extern mDNSu8 *putDeleteAllRRSets(DNSMessage *msg, mDNSu8 *ptr, const domainname *name);
305 
306 extern mDNSu8 *putUpdateLease(DNSMessage *msg, mDNSu8 *end, mDNSu32 lease);
307 
308 #define PutResourceRecord(MSG, P, C, RR) PutResourceRecordTTL((MSG), (P), (C), (RR), (RR)->rroriginalttl)
309 
310 
311 // ***************************************************************************
312 #if COMPILER_LIKES_PRAGMA_MARK
313 #pragma mark -
314 #pragma mark - DNS Message Parsing Functions
315 #endif
316 
317 extern mDNSu32 DomainNameHashValue(const domainname *const name);
318 
319 extern void SetNewRData(ResourceRecord *const rr, RData *NewRData, mDNSu16 rdlength);
320 
321 
322 extern const mDNSu8 *skipDomainName(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end);
323 
324 extern const mDNSu8 *getDomainName(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end,
325 	domainname *const name);
326 
327 extern const mDNSu8 *skipResourceRecord(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end);
328 
329 extern const mDNSu8 *GetLargeResourceRecord(mDNS *const m, const DNSMessage * const msg, const mDNSu8 *ptr,
330     const mDNSu8 * end, const mDNSInterfaceID InterfaceID, mDNSu8 RecordType, LargeCacheRecord *largecr);
331 
332 extern const mDNSu8 *skipQuestion(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end);
333 
334 extern const mDNSu8 *getQuestion(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end, const mDNSInterfaceID InterfaceID,
335 	DNSQuestion *question);
336 
337 extern const mDNSu8 *LocateAnswers(const DNSMessage *const msg, const mDNSu8 *const end);
338 
339 extern const mDNSu8 *LocateAuthorities(const DNSMessage *const msg, const mDNSu8 *const end);
340 
341 extern const mDNSu8 *LocateAdditionals(const DNSMessage *const msg, const mDNSu8 *const end);
342 
343 
344 // ***************************************************************************
345 #if COMPILER_LIKES_PRAGMA_MARK
346 #pragma mark -
347 #pragma mark -
348 #pragma mark - Packet Sending Functions
349 #endif
350 
351 extern mStatus mDNSSendDNSMessage(const mDNS *const m, DNSMessage *const msg, mDNSu8 *end,
352 	mDNSInterfaceID InterfaceID, const mDNSAddr *dst, mDNSIPPort dstport, int sd, uDNS_AuthInfo *authInfo);
353 
354 
355 // ***************************************************************************
356 #if COMPILER_LIKES_PRAGMA_MARK
357 #pragma mark -
358 #pragma mark - RR List Management & Task Management
359 #endif
360 
361 extern void mDNS_Lock(mDNS *const m);
362 extern void mDNS_Unlock(mDNS *const m);
363 
364 #ifdef	__cplusplus
365 	}
366 #endif
367 
368 #endif // __DNSCOMMON_H_
369