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