2 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 Change History (most recent first):
25 $Log: mDNSClientAPI.h,v $
26 Revision 1.114 2003/08/29 19:44:15 cheshire
27 <rdar://problem/3400967> Traffic reduction: Eliminate synchronized QUs when a new service appears
28 1. Use m->RandomQueryDelay to impose a random delay in the range 0-500ms on queries
29 that already have at least one unique answer in the cache
30 2. For these queries, go straight to QM, skipping QU
32 Revision 1.113 2003/08/21 19:31:58 cheshire
33 Cosmetic: Swap order of fields
35 Revision 1.112 2003/08/21 19:27:36 cheshire
36 <rdar://problem/3387878> Traffic reduction: No need to announce record for longer than TTL
38 Revision 1.111 2003/08/21 02:21:50 cheshire
39 <rdar://problem/3386473> Efficiency: Reduce repeated queries
41 Revision 1.110 2003/08/20 23:39:31 cheshire
42 <rdar://problem/3344098> Review syslog messages, and remove as appropriate
44 Revision 1.109 2003/08/19 22:24:10 cheshire
47 Revision 1.108 2003/08/19 22:20:00 cheshire
48 <rdar://problem/3376721> Don't use IPv6 on interfaces that have a routable IPv4 address configured
49 More minor refinements
51 Revision 1.107 2003/08/19 06:48:25 cheshire
52 <rdar://problem/3376552> Guard against excessive record updates
53 Each record starts with 10 UpdateCredits.
54 Every update consumes one UpdateCredit.
55 UpdateCredits are replenished at a rate of one one per minute, up to a maximum of 10.
56 As the number of UpdateCredits declines, the number of announcements is similarly scaled back.
57 When fewer than 5 UpdateCredits remain, the first announcement is also delayed by an increasing amount.
59 Revision 1.106 2003/08/19 04:49:28 cheshire
60 <rdar://problem/3368159> Interaction between v4, v6 and dual-stack hosts not working quite right
61 1. A dual-stack host should only suppress its own query if it sees the same query from other hosts on BOTH IPv4 and IPv6.
62 2. When we see the first v4 (or first v6) member of a group, we re-trigger questions and probes on that interface.
63 3. When we see the last v4 (or v6) member of a group go away, we revalidate all the records received on that interface.
65 Revision 1.105 2003/08/19 02:33:37 cheshire
68 Revision 1.104 2003/08/19 02:31:11 cheshire
69 <rdar://problem/3378386> mDNSResponder overenthusiastic with final expiration queries
70 Final expiration queries now only mark the question for sending on the particular interface
71 pertaining to the record that's expiring.
73 Revision 1.103 2003/08/18 19:05:44 cheshire
74 <rdar://problem/3382423> UpdateRecord not working right
75 Added "newrdlength" field to hold new length of updated rdata
77 Revision 1.102 2003/08/16 03:39:00 cheshire
78 <rdar://problem/3338440> InterfaceID -1 indicates "local only"
80 Revision 1.101 2003/08/15 20:16:02 cheshire
81 <rdar://problem/3366590> mDNSResponder takes too much RPRVT
82 We want to avoid touching the rdata pages, so we don't page them in.
83 1. RDLength was stored with the rdata, which meant touching the page just to find the length.
84 Moved this from the RData to the ResourceRecord object.
85 2. To avoid unnecessarily touching the rdata just to compare it,
86 compute a hash of the rdata and store the hash in the ResourceRecord object.
88 Revision 1.100 2003/08/14 19:29:04 cheshire
89 <rdar://problem/3378473> Include cache records in SIGINFO output
90 Moved declarations of DNSTypeName() and GetRRDisplayString to mDNSClientAPI.h so daemon.c can use them
92 Revision 1.99 2003/08/14 02:17:05 cheshire
93 <rdar://problem/3375491> Split generic ResourceRecord type into two separate types: AuthRecord and CacheRecord
95 Revision 1.98 2003/08/12 19:56:23 cheshire
98 Revision 1.97 2003/08/12 14:59:27 cheshire
99 <rdar://problem/3374490> Rate-limiting blocks some legitimate responses
100 When setting LastMCTime also record LastMCInterface. When checking LastMCTime to determine
101 whether to suppress the response, also check LastMCInterface to see if it matches.
103 Revision 1.96 2003/08/12 13:57:04 cheshire
104 <rdar://problem/3323817> Improve cache performance
105 Changed the number of hash table slots from 37 to 499
107 Revision 1.95 2003/08/09 00:55:02 cheshire
108 <rdar://problem/3366553> mDNSResponder is taking 20-30% of the CPU
109 Don't scan the whole cache after every packet.
111 Revision 1.94 2003/08/09 00:35:29 cheshire
113 Revision 1.93 2003/08/08 18:55:48 cheshire
114 <rdar://problem/3370365> Guard against time going backwards
116 Revision 1.92 2003/08/08 18:36:04 cheshire
117 <rdar://problem/3344154> Only need to revalidate on interface removal on platforms that have the PhantomInterfaces bug
119 Revision 1.91 2003/08/06 21:33:39 cheshire
120 Fix compiler warnings on PocketPC 2003 (Windows CE)
122 Revision 1.90 2003/08/06 20:30:17 cheshire
123 Add structure definition for rdataMX (not currently used, but good to have it for completeness)
125 Revision 1.89 2003/08/06 18:58:19 cheshire
128 Revision 1.88 2003/07/24 23:45:44 cheshire
129 To eliminate compiler warnings, changed definition of mDNSBool from
130 "unsigned char" to "int", since "int" is in fact truly the type that C uses
131 for the result of comparison operators (a<b) and logical operators (a||b)
133 Revision 1.87 2003/07/22 23:57:20 cheshire
134 Move platform-layer function prototypes from mDNSClientAPI.h to mDNSPlatformFunctions.h where they belong
136 Revision 1.86 2003/07/20 03:52:02 ksekar
137 Bug #: <rdar://problem/3320722>: Feature: New Rendezvous APIs (#7875) (mDNSResponder component)
138 Added error type for incompatibility between daemon and client versions
140 Revision 1.85 2003/07/19 03:23:13 cheshire
141 <rdar://problem/2986147> mDNSResponder needs to receive and cache larger records
143 Revision 1.84 2003/07/18 23:52:12 cheshire
144 To improve consistency of field naming, global search-and-replace:
145 NextProbeTime -> NextScheduledProbe
146 NextResponseTime -> NextScheduledResponse
148 Revision 1.83 2003/07/18 00:29:59 cheshire
149 <rdar://problem/3268878> Remove mDNSResponder version from packet header and use HINFO record instead
151 Revision 1.82 2003/07/17 17:35:04 cheshire
152 <rdar://problem/3325583> Rate-limit responses, to guard against packet flooding
154 Revision 1.81 2003/07/16 05:01:36 cheshire
155 Add fields 'LargeAnswers' and 'ExpectUnicastResponse' in preparation for
156 <rdar://problem/3315761> Need to implement "unicast response" request, using top bit of qclass
158 Revision 1.80 2003/07/15 01:55:12 cheshire
159 <rdar://problem/3315777> Need to implement service registration with subtypes
161 Revision 1.79 2003/07/13 02:28:00 cheshire
162 <rdar://problem/3325166> SendResponses didn't all its responses
163 Delete all references to RRInterfaceActive -- it's now superfluous
165 Revision 1.78 2003/07/13 01:47:53 cheshire
166 Fix one error and one warning in the Windows build
168 Revision 1.77 2003/07/11 01:32:38 cheshire
169 Syntactic cleanup (no change to funcationality): Now that we only have one host name,
170 rename field "hostname1" to "hostname", and field "RR_A1" to "RR_A".
172 Revision 1.76 2003/07/11 01:28:00 cheshire
173 <rdar://problem/3161289> No more local.arpa
175 Revision 1.75 2003/07/02 21:19:45 cheshire
176 <rdar://problem/3313413> Update copyright notices, etc., in source code comments
178 Revision 1.74 2003/07/02 02:41:23 cheshire
179 <rdar://problem/2986146> mDNSResponder needs to start with a smaller cache and then grow it as needed
181 Revision 1.73 2003/06/10 04:24:39 cheshire
182 <rdar://problem/3283637> React when we observe other people query unsuccessfully for a record that's in our cache
183 Some additional refinements:
184 Don't try to do this for unicast-response queries
185 better tracking of Qs and KAs in multi-packet KA lists
187 Revision 1.72 2003/06/10 01:46:27 cheshire
188 Add better comments explaining how these data structures are intended to be used from the client layer
190 Revision 1.71 2003/06/07 06:45:05 cheshire
191 <rdar://problem/3283666> No need for multiple machines to all be sending the same queries
193 Revision 1.70 2003/06/07 04:50:53 cheshire
194 <rdar://problem/3283637> React when we observe other people query unsuccessfully for a record that's in our cache
196 Revision 1.69 2003/06/07 04:22:17 cheshire
197 Add MsgBuffer for error log and debug messages
199 Revision 1.68 2003/06/07 01:46:38 cheshire
200 <rdar://problem/3283540> When query produces zero results, call mDNS_Reconfirm() on any antecedent records
202 Revision 1.67 2003/06/07 01:22:14 cheshire
203 <rdar://problem/3283516> mDNSResponder needs an mDNS_Reconfirm() function
205 Revision 1.66 2003/06/07 00:59:43 cheshire
206 <rdar://problem/3283454> Need some randomness to spread queries on the network
208 Revision 1.65 2003/06/06 21:41:11 cheshire
209 For consistency, mDNS_StopQuery() should return an mStatus result, just like all the other mDNSCore routines
211 Revision 1.64 2003/06/06 21:38:55 cheshire
212 Renamed 'NewData' as 'FreshData' (The data may not be new data, just a refresh of data that we
213 already had in our cache. This refreshes our TTL on the data, but the data itself stays the same.)
215 Revision 1.63 2003/06/06 17:20:14 cheshire
216 For clarity, rename question fields name/rrtype/rrclass as qname/qtype/qclass
217 (Global search-and-replace; no functional change to code execution.)
219 Revision 1.62 2003/06/04 01:25:33 cheshire
220 <rdar://problem/3274950> Cannot perform multi-packet known-answer suppression messages
221 Display time interval between first and subsequent queries
223 Revision 1.61 2003/06/03 05:02:16 cheshire
224 <rdar://problem/3277080> Duplicate registrations not handled as efficiently as they should be
226 Revision 1.60 2003/05/31 00:09:49 cheshire
227 <rdar://problem/3274862> Add ability to discover what services are on a network
229 Revision 1.59 2003/05/29 06:11:35 cheshire
230 <rdar://problem/3272214>: Report if there appear to be too many "Resolve" callbacks
232 Revision 1.58 2003/05/29 05:48:06 cheshire
233 Minor fix for when generating printf warnings: mDNS_snprintf arguments are now 3,4
235 Revision 1.57 2003/05/26 03:21:27 cheshire
236 Tidy up address structure naming:
237 mDNSIPAddr => mDNSv4Addr (for consistency with mDNSv6Addr)
238 mDNSAddr.addr.ipv4 => mDNSAddr.ip.v4
239 mDNSAddr.addr.ipv6 => mDNSAddr.ip.v6
241 Revision 1.56 2003/05/26 03:01:27 cheshire
242 <rdar://problem/3268904> sprintf/vsprintf-style functions are unsafe; use snprintf/vsnprintf instead
244 Revision 1.55 2003/05/26 00:47:30 cheshire
245 Comment clarification
247 Revision 1.54 2003/05/24 16:39:48 cheshire
248 <rdar://problem/3268631> SendResponses also needs to handle multihoming better
250 Revision 1.53 2003/05/23 02:15:37 cheshire
251 Fixed misleading use of the term "duplicate suppression" where it should have
252 said "known answer suppression". (Duplicate answer suppression is something
253 different, and duplicate question suppression is yet another thing, so the use
254 of the completely vague term "duplicate suppression" was particularly bad.)
256 Revision 1.52 2003/05/22 02:29:22 cheshire
257 <rdar://problem/2984918> SendQueries needs to handle multihoming better
258 Complete rewrite of SendQueries. Works much better now :-)
260 Revision 1.51 2003/05/21 20:14:55 cheshire
261 Fix comments and warnings
263 Revision 1.50 2003/05/14 07:08:36 cheshire
264 <rdar://problem/3159272> mDNSResponder should be smarter about reconfigurations
265 Previously, when there was any network configuration change, mDNSResponder
266 would tear down the entire list of active interfaces and start again.
267 That was very disruptive, and caused the entire cache to be flushed,
268 and caused lots of extra network traffic. Now it only removes interfaces
269 that have really gone, and only adds new ones that weren't there before.
271 Revision 1.49 2003/05/07 01:49:36 cheshire
272 Remove "const" in ConstructServiceName prototype
274 Revision 1.48 2003/05/07 00:18:44 cheshire
275 Fix typo: "kDNSQClass_Mask" should be "kDNSClass_Mask"
277 Revision 1.47 2003/05/06 00:00:46 cheshire
278 <rdar://problem/3248914> Rationalize naming of domainname manipulation functions
280 Revision 1.46 2003/04/30 20:39:09 cheshire
283 Revision 1.45 2003/04/29 00:40:50 cheshire
284 Fix compiler warnings
286 Revision 1.44 2003/04/26 02:41:56 cheshire
287 <rdar://problem/3241281> Change timenow from a local variable to a structure member
289 Revision 1.43 2003/04/25 01:45:56 cheshire
290 <rdar://problem/3240002> mDNS_RegisterNoSuchService needs to include a host name
292 Revision 1.42 2003/04/15 20:58:31 jgraessl
295 Added a hash to lookup records in the cache.
297 Revision 1.41 2003/04/15 18:09:13 jgraessl
300 Reviewed by: Stuart Cheshire
301 Added code to keep track of when the next cache item will expire so we can
302 call TidyRRCache only when necessary.
304 Revision 1.40 2003/03/29 01:55:19 cheshire
305 <rdar://problem/3212360> mDNSResponder sometimes suffers false self-conflicts when it sees its own packets
306 Solution: Major cleanup of packet timing and conflict handling rules
308 Revision 1.39 2003/03/27 03:30:55 cheshire
309 <rdar://problem/3210018> Name conflicts not handled properly, resulting in memory corruption, and eventual crash
310 Problem was that HostNameCallback() was calling mDNS_DeregisterInterface(), which is not safe in a callback
312 1. Make mDNS_DeregisterInterface() safe to call from a callback
313 2. Make HostNameCallback() use mDNS_DeadvertiseInterface() instead
314 (it never really needed to deregister the interface at all)
316 Revision 1.38 2003/03/15 04:40:36 cheshire
317 Change type called "mDNSOpaqueID" to the more descriptive name "mDNSInterfaceID"
319 Revision 1.37 2003/03/14 21:34:11 cheshire
320 <rdar://problem/3176950> Can't setup and print to Lexmark PS printers via Airport Extreme
321 Increase size of cache rdata from 512 to 768
323 Revision 1.36 2003/03/05 03:38:35 cheshire
324 Bug #: 3185731 Bogus error message in console: died or deallocated, but no record of client can be found!
325 Fixed by leaving client in list after conflict, until client explicitly deallocates
327 Revision 1.35 2003/02/21 02:47:54 cheshire
328 Bug #: 3099194 mDNSResponder needs performance improvements
329 Several places in the code were calling CacheRRActive(), which searched the entire
330 question list every time, to see if this cache resource record answers any question.
331 Instead, we now have a field "CRActiveQuestion" in the resource record structure
333 Revision 1.34 2003/02/21 01:54:08 cheshire
334 Bug #: 3099194 mDNSResponder needs performance improvements
335 Switched to using new "mDNS_Execute" model (see "Implementer Notes.txt")
337 Revision 1.33 2003/02/20 06:48:32 cheshire
338 Bug #: 3169535 Xserve RAID needs to do interface-specific registrations
339 Reviewed by: Josh Graessley, Bob Bradley
341 Revision 1.32 2003/01/31 03:35:59 cheshire
342 Bug #: 3147097 mDNSResponder sometimes fails to find the correct results
343 When there were *two* active questions in the list, they were incorrectly
344 finding *each other* and *both* being marked as duplicates of another question
346 Revision 1.31 2003/01/29 02:46:37 cheshire
348 A physical interface is identified solely by its InterfaceID (not by IP and type).
349 On a given InterfaceID, mDNSCore may send both v4 and v6 multicasts.
350 In cases where the requested outbound protocol (v4 or v6) is not supported on
351 that InterfaceID, the platform support layer should simply discard that packet.
353 Revision 1.30 2003/01/29 01:47:08 cheshire
354 Rename 'Active' to 'CRActive' or 'InterfaceActive' for improved clarity
356 Revision 1.29 2003/01/28 05:23:43 cheshire
357 Bug #: 3147097 mDNSResponder sometimes fails to find the correct results
358 Add 'Active' flag for interfaces
360 Revision 1.28 2003/01/28 01:35:56 cheshire
361 Revise comment about ThisQInterval to reflect new semantics
363 Revision 1.27 2003/01/13 23:49:42 jgraessl
364 Merged changes for the following fixes in to top of tree:
365 3086540 computer name changes not handled properly
366 3124348 service name changes are not properly handled
367 3124352 announcements sent in pairs, failing chattiness test
369 Revision 1.26 2002/12/23 22:13:28 jgraessl
371 Reviewed by: Stuart Cheshire
372 Initial IPv6 support for mDNSResponder.
374 Revision 1.25 2002/09/21 20:44:49 zarzycki
377 Revision 1.24 2002/09/19 23:47:35 cheshire
378 Added mDNS_RegisterNoSuchService() function for assertion of non-existance
379 of a particular named service
381 Revision 1.23 2002/09/19 21:25:34 cheshire
382 mDNS_snprintf() doesn't need to be in a separate file
384 Revision 1.22 2002/09/19 04:20:43 cheshire
385 Remove high-ascii characters that confuse some systems
387 Revision 1.21 2002/09/17 01:06:35 cheshire
388 Change mDNS_AdvertiseLocalAddresses to be a parameter to mDNS_Init()
390 Revision 1.20 2002/09/16 18:41:41 cheshire
391 Merge in license terms from Quinn's copy, in preparation for Darwin release
395 #ifndef __mDNSClientAPI_h
396 #define __mDNSClientAPI_h
398 #include <stdarg.h> // stdarg.h is required for for va_list support for the mDNS_vsnprintf declaration
399 #include "mDNSDebug.h"
405 // ***************************************************************************
406 // Function scope indicators
408 // If you see "mDNSlocal" before a function name, it means the function is not callable outside this file
410 #define mDNSlocal static
412 // If you see "mDNSexport" before a symbol, it means the symbol is exported for use by clients
417 // ***************************************************************************
419 #pragma mark - DNS Resource Record class and type constants
422 typedef enum // From RFC 1035
424 kDNSClass_IN
= 1, // Internet
425 kDNSClass_CS
= 2, // CSNET
426 kDNSClass_CH
= 3, // CHAOS
427 kDNSClass_HS
= 4, // Hesiod
428 kDNSClass_NONE
= 254, // Used in DNS UPDATE [RFC 2136]
430 kDNSClass_Mask
= 0x7FFF,// Multicast DNS uses the bottom 15 bits to identify the record class...
431 kDNSClass_UniqueRRSet
= 0x8000,// ... and the top bit indicates that all other cached records are now invalid
433 kDNSQClass_ANY
= 255, // Not a DNS class, but a DNS query class, meaning "all classes"
434 kDNSQClass_UnicastResponse
= 0x8000 // Top bit set in a question means "unicast response acceptable"
437 typedef enum // From RFC 1035
439 kDNSType_A
= 1, // 1 Address
440 kDNSType_NS
, // 2 Name Server
441 kDNSType_MD
, // 3 Mail Destination
442 kDNSType_MF
, // 4 Mail Forwarder
443 kDNSType_CNAME
, // 5 Canonical Name
444 kDNSType_SOA
, // 6 Start of Authority
445 kDNSType_MB
, // 7 Mailbox
446 kDNSType_MG
, // 8 Mail Group
447 kDNSType_MR
, // 9 Mail Rename
448 kDNSType_NULL
, // 10 NULL RR
449 kDNSType_WKS
, // 11 Well-known-service
450 kDNSType_PTR
, // 12 Domain name pointer
451 kDNSType_HINFO
, // 13 Host information
452 kDNSType_MINFO
, // 14 Mailbox information
453 kDNSType_MX
, // 15 Mail Exchanger
454 kDNSType_TXT
, // 16 Arbitrary text string
456 kDNSType_AAAA
= 28, // 28 IPv6 address
457 kDNSType_SRV
= 33, // 33 Service record
459 kDNSQType_ANY
= 255 // Not a DNS type, but a DNS query type, meaning "all types"
462 // ***************************************************************************
464 #pragma mark - Simple types
467 // mDNS defines its own names for these common types to simplify portability across
468 // multiple platforms that may each have their own (different) names for these types.
469 typedef int mDNSBool
;
470 typedef signed char mDNSs8
;
471 typedef unsigned char mDNSu8
;
472 typedef signed short mDNSs16
;
473 typedef unsigned short mDNSu16
;
474 typedef signed long mDNSs32
;
475 typedef unsigned long mDNSu32
;
477 // To enforce useful type checking, we make mDNSInterfaceID be a pointer to a dummy struct
478 // This way, mDNSInterfaceIDs can be assigned, and compared with each other, but not with other types
479 // Declaring the type to be the typical generic "void *" would lack this type checking
480 typedef struct { void *dummy
; } *mDNSInterfaceID
;
482 // These types are for opaque two- and four-byte identifiers.
483 // The "NotAnInteger" fields of the unions allow the value to be conveniently passed around in a
484 // register for the sake of efficiency, and compared for equality or inequality, but don't forget --
485 // just because it is in a register doesn't mean it is an integer. Operations like greater than,
486 // less than, add, multiply, increment, decrement, etc., are undefined for opaque identifiers,
487 // and if you make the mistake of trying to do those using the NotAnInteger field, then you'll
488 // find you get code that doesn't work consistently on big-endian and little-endian machines.
489 typedef union { mDNSu8 b
[2]; mDNSu16 NotAnInteger
; } mDNSOpaque16
;
490 typedef union { mDNSu8 b
[4]; mDNSu32 NotAnInteger
; } mDNSOpaque32
;
491 typedef union { mDNSu8 b
[16]; mDNSu16 w
[8]; mDNSu32 l
[4]; } mDNSOpaque128
;
493 typedef mDNSOpaque16 mDNSIPPort
; // An IP port is a two-byte opaque identifier (not an integer)
494 typedef mDNSOpaque32 mDNSv4Addr
; // An IP address is a four-byte opaque identifier (not an integer)
495 typedef mDNSOpaque128 mDNSv6Addr
; // An IPv6 address is a 16-byte opaque identifier (not an integer)
499 mDNSAddrType_None
= 0,
500 mDNSAddrType_IPv4
= 4,
501 mDNSAddrType_IPv6
= 6,
502 mDNSAddrType_Unknown
= ~0 // Special marker value used in known answer list recording
508 union { mDNSv6Addr v6
; mDNSv4Addr v4
; } ip
;
511 enum { mDNSfalse
= 0, mDNStrue
= 1 };
520 // mDNS Error codes are in the range FFFE FF00 (-65792) to FFFE FFFF (-65537)
521 mStatus_UnknownErr
= -65537, // 0xFFFE FFFF
522 mStatus_NoSuchNameErr
= -65538,
523 mStatus_NoMemoryErr
= -65539,
524 mStatus_BadParamErr
= -65540,
525 mStatus_BadReferenceErr
= -65541,
526 mStatus_BadStateErr
= -65542,
527 mStatus_BadFlagsErr
= -65543,
528 mStatus_UnsupportedErr
= -65544,
529 mStatus_NotInitializedErr
= -65545,
530 mStatus_NoCache
= -65546,
531 mStatus_AlreadyRegistered
= -65547,
532 mStatus_NameConflict
= -65548,
533 mStatus_Invalid
= -65549,
534 mStatus_GrowCache
= -65550,
535 mStatus_Incompatible
= -65551,
536 mStatus_ConfigChanged
= -65791,
537 mStatus_MemFree
= -65792 // 0xFFFE FF00
540 typedef mDNSs32 mStatus
;
542 // RFC 1034/1035 specify that a domain label consists of a length byte plus up to 63 characters
543 #define MAX_DOMAIN_LABEL 63
544 typedef struct { mDNSu8 c
[ 64]; } domainlabel
; // One label: length byte and up to 63 characters
546 // RFC 1034/1035 specify that a domain name, including length bytes, data bytes, and terminating zero, may be up to 255 bytes long
547 #define MAX_DOMAIN_NAME 255
548 typedef struct { mDNSu8 c
[256]; } domainname
; // Up to 255 bytes of length-prefixed domainlabels
550 typedef struct { mDNSu8 c
[256]; } UTF8str255
; // Null-terminated C string
552 // ***************************************************************************
554 #pragma mark - Resource Record structures
557 // Authoritative Resource Records:
558 // There are four basic types: Shared, Advisory, Unique, Known Unique
560 // * Shared Resource Records do not have to be unique
561 // -- Shared Resource Records are used for DNS-SD service PTRs
562 // -- It is okay for several hosts to have RRs with the same name but different RDATA
563 // -- We use a random delay on responses to reduce collisions when all the hosts respond to the same query
564 // -- These RRs typically have moderately high TTLs (e.g. one hour)
565 // -- These records are announced on startup and topology changes for the benefit of passive listeners
566 // -- These records send a goodbye packet when deregistering
568 // * Advisory Resource Records are like Shared Resource Records, except they don't send a goodbye packet
570 // * Unique Resource Records should be unique among hosts within any given mDNS scope
571 // -- The majority of Resource Records are of this type
572 // -- If two entities on the network have RRs with the same name but different RDATA, this is a conflict
573 // -- Responses may be sent immediately, because only one host should be responding to any particular query
574 // -- These RRs typically have low TTLs (e.g. ten seconds)
575 // -- On startup and after topology changes, a host issues queries to verify uniqueness
577 // * Known Unique Resource Records are treated like Unique Resource Records, except that mDNS does
578 // not have to verify their uniqueness because this is already known by other means (e.g. the RR name
579 // is derived from the host's IP or Ethernet address, which is already known to be a unique identifier).
581 // Summary of properties of different record types:
582 // Probe? Does this record type send probes before announcing?
583 // Conflict? Does this record type react if we observe an apparent conflict?
584 // Goodbye? Does this record type send a goodbye packet on departure?
586 // Probe? Conflict? Goodbye? Notes
587 // Unregistered Should not appear in any list (sanity check value)
588 // Shared No No Yes e.g. Service PTR record
589 // Deregistering No No Yes Shared record about to announce its departure and leave the list
591 // Unique Yes Yes No Record intended to be unique -- will probe to verify
592 // Verified Yes Yes No Record has completed probing, and is verified unique
593 // KnownUnique No Yes No Record is assumed by other means to be unique
595 // Valid lifecycle of a record:
596 // Unregistered -> Shared -> Deregistering -(goodbye)-> Unregistered
597 // Unregistered -> Advisory -> Unregistered
598 // Unregistered -> Unique -(probe)-> Verified -> Unregistered
599 // Unregistered -> KnownUnique -> Unregistered
601 // Each Authoritative kDNSRecordType has only one bit set. This makes it easy to quickly see if a record
602 // is one of a particular set of types simply by performing the appropriate bitwise masking operation.
604 // Cache Resource Records (received from the network):
605 // There are four basic types: Answer, Unique Answer, Additional, Unique Additional
606 // Bit 7 (the top bit) of kDNSRecordType is always set for Cache Resource Records; always clear for Authoritative Resource Records
607 // Bit 6 (value 0x40) is set for answer records; clear for additional records
608 // Bit 5 (value 0x20) is set for records received with the kDNSClass_UniqueRRSet
612 kDNSRecordTypeUnregistered
= 0x00, // Not currently in any list
613 kDNSRecordTypeDeregistering
= 0x01, // Shared record about to announce its departure and leave the list
615 kDNSRecordTypeUnique
= 0x02, // Will become a kDNSRecordTypeVerified when probing is complete
617 kDNSRecordTypeAdvisory
= 0x04, // Like Shared, but no goodbye packet
618 kDNSRecordTypeShared
= 0x08, // Shared means record name does not have to be unique -- use random delay on responses
619 kDNSRecordTypeVerified
= 0x10, // Unique means mDNS should check that name is unique (and then send immediate responses)
620 kDNSRecordTypeKnownUnique
= 0x20, // Known Unique means mDNS can assume name is unique without checking
622 kDNSRecordTypeUniqueMask
= (kDNSRecordTypeUnique
| kDNSRecordTypeVerified
| kDNSRecordTypeKnownUnique
),
623 kDNSRecordTypeActiveMask
= (kDNSRecordTypeAdvisory
| kDNSRecordTypeShared
| kDNSRecordTypeVerified
| kDNSRecordTypeKnownUnique
),
625 kDNSRecordTypePacketAdd
= 0x80, // Received in the Additional Section of a DNS Response
626 kDNSRecordTypePacketAddUnique
= 0xA0, // Received in the Additional Section of a DNS Response with kDNSClass_UniqueRRSet set
627 kDNSRecordTypePacketAns
= 0xC0, // Received in the Answer Section of a DNS Response
628 kDNSRecordTypePacketAnsUnique
= 0xE0, // Received in the Answer Section of a DNS Response with kDNSClass_UniqueRRSet set
630 kDNSRecordTypePacketAnsMask
= 0x40, // True for PacketAns and PacketAnsUnique
631 kDNSRecordTypePacketUniqueMask
= 0x20 // True for PacketAddUnique and PacketAnsUnique
634 typedef struct { mDNSu16 priority
; mDNSu16 weight
; mDNSIPPort port
; domainname target
; } rdataSRV
;
635 typedef struct { mDNSu16 preference
; domainname exchange
; } rdataMX
;
637 // StandardAuthRDSize is 264 (256+8), which is large enough to hold a maximum-sized SRV record
638 // MaximumRDSize is 8K the absolute maximum we support (at least for now)
639 #define StandardAuthRDSize 264
640 #define MaximumRDSize 8192
642 // InlineCacheRDSize is 64
643 // Records received from the network with rdata this size or less have their rdata stored right in the CacheRecord object
644 // Records received from the network with rdata larger than this have additional storage allocated for the rdata
645 // A quick unscientific sample from a busy network at Apple with lots of machines revealed this:
646 // 1461 records in cache
647 // 292 were one-byte TXT records
648 // 136 were four-byte A records
649 // 184 were sixteen-byte AAAA records
650 // 780 were various PTR, TXT and SRV records from 12-64 bytes
651 // Only 69 records had rdata bigger than 64 bytes
652 #define InlineCacheRDSize 64
656 mDNSu8 data
[StandardAuthRDSize
];
657 mDNSv4Addr ip
; // For 'A' record
658 mDNSv6Addr ipv6
; // For 'AAAA' record
659 domainname name
; // For PTR and CNAME records
660 UTF8str255 txt
; // For TXT record
661 rdataSRV srv
; // For SRV record
662 rdataMX mx
; // For MX record
667 mDNSu16 MaxRDLength
; // Amount of storage allocated for rdata (usually sizeof(RDataBody))
670 #define sizeofRDataHeader (sizeof(RData) - sizeof(RDataBody))
672 typedef struct AuthRecord_struct AuthRecord
;
673 typedef struct CacheRecord_struct CacheRecord
;
674 typedef struct ResourceRecord_struct ResourceRecord
;
675 typedef struct DNSQuestion_struct DNSQuestion
;
676 typedef struct mDNS_struct mDNS
;
677 typedef struct mDNS_PlatformSupport_struct mDNS_PlatformSupport
;
679 // Note: Within an mDNSRecordCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Close(), mDNS_Execute()
680 typedef void mDNSRecordCallback(mDNS
*const m
, AuthRecord
*const rr
, mStatus result
);
683 // Restrictions: An mDNSRecordUpdateCallback may not make any mDNS API calls.
684 // The intent of this callback is to allow the client to free memory, if necessary.
685 // The internal data structures of the mDNS code may not be in a state where mDNS API calls may be made safely.
686 typedef void mDNSRecordUpdateCallback(mDNS
*const m
, AuthRecord
*const rr
, RData
*OldRData
);
688 struct ResourceRecord_struct
690 mDNSu8 RecordType
; // See enum above
691 mDNSInterfaceID InterfaceID
; // Set if this RR is specific to one interface
692 // For records received off the wire, InterfaceID is *always* set to the receiving interface
693 // For our authoritative records, InterfaceID is usually zero, except for those few records
694 // that are interface-specific (e.g. address records, especially linklocal addresses)
698 mDNSu32 rroriginalttl
; // In seconds
699 mDNSu16 rdlength
; // Size of the raw rdata, in bytes
700 mDNSu16 rdestimate
; // Upper bound on size of rdata after name compression
701 mDNSu32 namehash
; // Name-based (i.e. case insensitive) hash of name
702 mDNSu32 rdatahash
; // 32-bit hash of the raw rdata
703 mDNSu32 rdnamehash
; // Set if this rdata contains a domain name (e.g. PTR, SRV, CNAME etc.)
704 RData
*rdata
; // Pointer to storage for this rdata
707 struct AuthRecord_struct
709 // For examples of how to set up this structure for use in mDNS_Register(),
710 // see mDNS_AdvertiseInterface() or mDNS_RegisterService().
711 // Basically, resrec and persistent metadata need to be set up before calling mDNS_Register().
712 // mDNS_SetupResourceRecord() is avaliable as a helper routine to set up most fields to sensible default values for you
714 AuthRecord
*next
; // Next in list; first element of structure for efficiency reasons
715 ResourceRecord resrec
;
717 // Persistent metadata for Authoritative Records
718 AuthRecord
*Additional1
; // Recommended additional record to include in response
719 AuthRecord
*Additional2
; // Another additional
720 AuthRecord
*DependentOn
; // This record depends on another for its uniqueness checking
721 AuthRecord
*RRSet
; // This unique record is part of an RRSet
722 mDNSRecordCallback
*RecordCallback
; // Callback function to call for state changes
723 void *RecordContext
; // Context parameter for the callback function
724 mDNSu8 HostTarget
; // Set if the target of this record (PTR, CNAME, SRV, etc.) is our host name
726 // Transient state for Authoritative Records
727 mDNSu8 Acknowledged
; // Set if we've given the success callback to the client
728 mDNSu8 ProbeCount
; // Number of probes remaining before this record is valid (kDNSRecordTypeUnique)
729 mDNSu8 AnnounceCount
; // Number of announcements remaining (kDNSRecordTypeShared)
730 mDNSu8 IncludeInProbe
; // Set if this RR is being put into a probe right now
731 mDNSInterfaceID ImmedAnswer
; // Someone on this interface issued a query we need to answer (all-ones for all interfaces)
732 mDNSInterfaceID ImmedAdditional
; // Hint that we might want to also send this record, just to be helpful
733 mDNSInterfaceID SendRNow
; // The interface this query is being sent on right now
734 mDNSv4Addr v4Requester
; // Recent v4 query for this record, or all-ones if more than one recent query
735 mDNSv6Addr v6Requester
; // Recent v6 query for this record, or all-ones if more than one recent query
736 AuthRecord
*NextResponse
; // Link to the next element in the chain of responses to generate
737 const mDNSu8
*NR_AnswerTo
; // Set if this record was selected by virtue of being a direct answer to a question
738 AuthRecord
*NR_AdditionalTo
; // Set if this record was selected by virtue of being additional to another
739 mDNSs32 ThisAPInterval
; // In platform time units: Current interval for announce/probe
740 mDNSs32 AnnounceUntil
; // In platform time units: Creation time + TTL
741 mDNSs32 LastAPTime
; // In platform time units: Last time we sent announcement/probe
742 mDNSs32 LastMCTime
; // Last time we multicast this record (used to guard against packet-storm attacks)
743 mDNSInterfaceID LastMCInterface
; // Interface this record was multicast on at the time LastMCTime was recorded
744 RData
*NewRData
; // Set if we are updating this record with new rdata
745 mDNSu16 newrdlength
; // ... and the length of the new RData
746 mDNSRecordUpdateCallback
*UpdateCallback
;
747 mDNSu32 UpdateCredits
; // Token-bucket rate limiting of excessive updates
748 mDNSs32 NextUpdateCredit
; // Time next token is added to bucket
749 mDNSs32 UpdateBlocked
; // Set if update delaying is in effect
751 RData rdatastorage
; // Normally the storage is right here, except for oversized records
752 // rdatastorage MUST be the last thing in the structure -- when using oversized AuthRecords, extra bytes
753 // are appended after the end of the AuthRecord, logically augmenting the size of the rdatastorage
754 // DO NOT ADD ANY MORE FIELDS HERE
757 struct CacheRecord_struct
759 CacheRecord
*next
; // Next in list; first element of structure for efficiency reasons
760 ResourceRecord resrec
;
762 // Transient state for Cache Records
763 CacheRecord
*NextInKAList
; // Link to the next element in the chain of known answers to send
764 mDNSs32 TimeRcvd
; // In platform time units
765 mDNSs32 NextRequiredQuery
; // In platform time units
766 mDNSs32 LastUsed
; // In platform time units
767 mDNSu32 UseCount
; // Number of times this RR has been used to answer a question
768 DNSQuestion
*CRActiveQuestion
; // Points to an active question referencing this answer
769 mDNSu32 UnansweredQueries
; // Number of times we've issued a query for this record without getting an answer
770 mDNSs32 LastUnansweredTime
; // In platform time units; last time we incremented UnansweredQueries
771 mDNSu32 MPUnansweredQ
; // Multi-packet query handling: Number of times we've seen a query for this record
772 mDNSs32 MPLastUnansweredQT
; // Multi-packet query handling: Last time we incremented MPUnansweredQ
773 mDNSu32 MPUnansweredKA
; // Multi-packet query handling: Number of times we've seen this record in a KA list
774 mDNSBool MPExpectingKA
; // Multi-packet query handling: Set when we increment MPUnansweredQ; allows one KA
775 CacheRecord
*NextInCFList
; // Set if this is in the list of records we just received with the cache flush bit set
777 struct { mDNSu16 MaxRDLength
; mDNSu8 data
[InlineCacheRDSize
]; } rdatastorage
; // Storage for small records is right here
783 mDNSu8 _extradata
[MaximumRDSize
-InlineCacheRDSize
]; // Glue on the necessary number of extra bytes
786 typedef struct NetworkInterfaceInfo_struct NetworkInterfaceInfo
;
788 struct NetworkInterfaceInfo_struct
790 // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
791 NetworkInterfaceInfo
*next
;
793 mDNSBool InterfaceActive
; // InterfaceActive is set if interface is sending & receiving packets
794 // InterfaceActive is clear if interface is here to represent an address with A
795 // and/or AAAA records, but there is already an earlier representative for this
796 // physical interface which will be used for the actual sending & receiving
797 // packets (this status may change as interfaces are added and removed)
798 mDNSBool IPv4Available
; // If InterfaceActive, set if v4 available on this InterfaceID
799 mDNSBool IPv6Available
; // If InterfaceActive, set if v6 available on this InterfaceID
801 // Standard AuthRecords that every Responder host should have (one per active IP address)
802 AuthRecord RR_A
; // 'A' or 'AAAA' (address) record for our ".local" name
803 AuthRecord RR_PTR
; // PTR (reverse lookup) record
806 // Client API fields: The client must set up these fields *before* calling mDNS_RegisterInterface()
807 mDNSInterfaceID InterfaceID
;
809 mDNSBool Advertise
; // Set Advertise to false if you are only searching on this interface
810 mDNSBool TxAndRx
; // Set to false if not sending and receiving packets on this interface
813 typedef struct ExtraResourceRecord_struct ExtraResourceRecord
;
814 struct ExtraResourceRecord_struct
816 ExtraResourceRecord
*next
;
818 // Note: Add any additional fields *before* the AuthRecord in this structure, not at the end.
819 // In some cases clients can allocate larger chunks of memory and set r->rdata->MaxRDLength to indicate
820 // that this extra memory is available, which would result in any fields after the AuthRecord getting smashed
823 // Note: Within an mDNSServiceCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Close(), mDNS_Execute()
824 typedef struct ServiceRecordSet_struct ServiceRecordSet
;
825 typedef void mDNSServiceCallback(mDNS
*const m
, ServiceRecordSet
*const sr
, mStatus result
);
826 struct ServiceRecordSet_struct
828 // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
829 // No fields need to be set up by the client prior to calling mDNS_RegisterService();
830 // all required data is passed as parameters to that function.
831 mDNSServiceCallback
*ServiceCallback
;
832 void *ServiceContext
;
833 ExtraResourceRecord
*Extras
; // Optional list of extra AuthRecords attached to this service registration
835 AuthRecord
*SubTypes
;
836 mDNSBool Conflict
; // Set if this record set was forcibly deregistered because of a conflict
837 domainname Host
; // Set if this service record does not use the standard target host name
838 AuthRecord RR_ADV
; // e.g. _services._mdns._udp.local. PTR _printer._tcp.local.
839 AuthRecord RR_PTR
; // e.g. _printer._tcp.local. PTR Name._printer._tcp.local.
840 AuthRecord RR_SRV
; // e.g. Name._printer._tcp.local. SRV 0 0 port target
841 AuthRecord RR_TXT
; // e.g. Name._printer._tcp.local. TXT PrintQueueName
842 // Don't add any fields after AuthRecord RR_TXT.
843 // This is where the implicit extra space goes if we allocate a ServiceRecordSet containing an oversized RR_TXT record
846 // ***************************************************************************
848 #pragma mark - Question structures
851 // We record the last eight instances of each duplicate query
852 // This gives us v4/v6 on each of Ethernet/AirPort and Firewire, and two free slots "for future expansion"
853 // If the host has more active interfaces that this it is not fatal -- duplicate question suppression will degrade gracefully.
854 // Since we will still remember the last eight, the busiest interfaces will still get the effective duplicate question suppression.
855 #define DupSuppressInfoSize 8
860 mDNSInterfaceID InterfaceID
;
861 mDNSs32 Type
; // v4 or v6?
864 // Note: Within an mDNSQuestionCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Close(), mDNS_Execute()
865 typedef void mDNSQuestionCallback(mDNS
*const m
, DNSQuestion
*question
, const ResourceRecord
*const answer
, mDNSBool AddRecord
);
866 struct DNSQuestion_struct
868 // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
871 mDNSs32 LastQTime
; // Last scheduled tranmission of this Q on *all* applicable interfaces
872 mDNSs32 ThisQInterval
; // LastQTime + ThisQInterval is the next scheduled tranmission of this Q
873 // ThisQInterval > 0 for an active question;
874 // ThisQInterval = 0 for a suspended question that's still in the list
875 // ThisQInterval = -1 for a cancelled question that's been removed from the list
876 mDNSu32 RecentAnswers
; // Number of answers since the last time we sent this query
877 mDNSu32 CurrentAnswers
; // Number of records currently in the cache that answer this question
878 mDNSu32 LargeAnswers
; // Number of answers with rdata > 1024 bytes
879 mDNSu32 UniqueAnswers
; // Number of answers received with kDNSClass_UniqueRRSet bit set
880 DNSQuestion
*DuplicateOf
;
881 DNSQuestion
*NextInDQList
;
882 DupSuppressInfo DupSuppress
[DupSuppressInfoSize
];
883 mDNSInterfaceID SendQNow
; // The interface this query is being sent on right now
884 mDNSBool SendOnAll
; // Set if we're sending this question on all active interfaces
885 mDNSs32 LastQTxTime
; // Last time this Q was sent on one (but not necessarily all) interfaces
887 // Client API fields: The client must set up these fields *before* calling mDNS_StartQuery()
888 mDNSInterfaceID InterfaceID
; // Non-zero if you want to issue link-local queries only on a single specific IP interface
892 mDNSQuestionCallback
*QuestionCallback
;
893 void *QuestionContext
;
898 // Client API fields: The client must set up name and InterfaceID *before* calling mDNS_StartResolveService()
899 // When the callback is invoked, ip, port, TXTlen and TXTinfo will have been filled in with the results learned from the network.
901 mDNSInterfaceID InterfaceID
; // ID of the interface the response was received on
902 mDNSAddr ip
; // Remote (destination) IP address where this service can be accessed
903 mDNSIPPort port
; // Port where this service can be accessed
905 mDNSu8 TXTinfo
[2048]; // Additional demultiplexing information (e.g. LPR queue name)
908 // Note: Within an mDNSServiceInfoQueryCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Close(), mDNS_Execute()
909 typedef struct ServiceInfoQuery_struct ServiceInfoQuery
;
910 typedef void mDNSServiceInfoQueryCallback(mDNS
*const m
, ServiceInfoQuery
*query
);
911 struct ServiceInfoQuery_struct
913 // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
914 // No fields need to be set up by the client prior to calling mDNS_StartResolveService();
915 // all required data is passed as parameters to that function.
916 // The ServiceInfoQuery structure memory is working storage for mDNSCore to discover the requested information
917 // and place it in the ServiceInfo structure. After the client has called mDNS_StopResolveService(), it may
918 // dispose of the ServiceInfoQuery structure while retaining the results in the ServiceInfo structure.
928 mDNSServiceInfoQueryCallback
*ServiceInfoQueryCallback
;
929 void *ServiceInfoQueryContext
;
932 // ***************************************************************************
934 #pragma mark - Main mDNS object, used to hold all the mDNS state
937 typedef void mDNSCallback(mDNS
*const m
, mStatus result
);
939 #define CACHE_HASH_SLOTS 499
943 mDNS_KnownBug_PhantomInterfaces
= 1
948 // Internal state fields. These hold the main internal state of mDNSCore;
949 // the client layer needn't be concerned with them.
950 // No fields need to be set up by the client prior to calling mDNS_Init();
951 // all required data is passed as parameters to that function.
953 mDNS_PlatformSupport
*p
; // Pointer to platform-specific data of indeterminite size
955 mDNSBool AdvertiseLocalAddresses
;
956 mStatus mDNSPlatformStatus
;
957 mDNSCallback
*MainCallback
;
960 // For debugging: To catch and report locking failures
961 mDNSu32 mDNS_busy
; // Incremented between mDNS_Lock/mDNS_Unlock section
962 mDNSu32 mDNS_reentrancy
; // Incremented when calling a client callback
963 mDNSu8 mDNS_shutdown
; // Set when we're shutting down, allows us to skip some unnecessary steps
964 mDNSu8 lock_rrcache
; // For debugging: Set at times when these lists may not be modified
965 mDNSu8 lock_Questions
;
967 char MsgBuffer
[80]; // Temp storage used while building error log messages
969 // Task Scheduling variables
970 mDNSs32 timenow
; // The time that this particular activation of the mDNS code started
971 mDNSs32 timenow_last
; // The time the last time we ran
972 mDNSs32 timenow_adjust
; // Correction applied if we ever discover time went backwards
973 mDNSs32 NextScheduledEvent
; // Derived from values below
974 mDNSs32 SuppressSending
; // Don't send *any* packets during this time
975 mDNSs32 NextCacheCheck
; // Next time to refresh cache record before it expires
976 mDNSs32 NextScheduledQuery
; // Next time to send query in its exponential backoff sequence
977 mDNSs32 NextScheduledProbe
; // Next time to probe for new authoritative record
978 mDNSs32 NextScheduledResponse
; // Next time to send authoritative record(s) in responses
979 mDNSs32 ExpectUnicastResponse
; // Set when we send a query with the kDNSQClass_UnicastResponse bit set
980 mDNSs32 RandomQueryDelay
; // For de-synchronization of query packets on the wire
981 mDNSBool SendDeregistrations
; // Set if we need to send deregistrations (immediately)
982 mDNSBool SendImmediateAnswers
; // Set if we need to send answers (immediately -- or as soon as SuppressSending clears)
983 mDNSBool SleepState
; // Set if we're sleeping (send no more packets)
985 // These fields only required for mDNS Searcher...
986 DNSQuestion
*Questions
; // List of all registered questions, active and inactive
987 DNSQuestion
*NewQuestions
; // Fresh questions not yet answered from cache
988 DNSQuestion
*CurrentQuestion
; // Next question about to be examined in AnswerLocalQuestions()
989 DNSQuestion
*LocalOnlyQuestions
; // Questions with InterfaceID set to ~0 ("local only")
990 DNSQuestion
*NewLocalOnlyQuestions
; // Fresh local-only questions not yet answered
991 mDNSu32 rrcache_size
; // Total number of available cache entries
992 mDNSu32 rrcache_totalused
; // Number of cache entries currently occupied
993 mDNSu32 rrcache_active
; // Number of cache entries currently occupied by records that answer active questions
994 mDNSu32 rrcache_report
;
995 CacheRecord
*rrcache_free
;
996 CacheRecord
*rrcache_hash
[CACHE_HASH_SLOTS
];
997 mDNSu32 rrcache_used
[CACHE_HASH_SLOTS
];
999 // Fields below only required for mDNS Responder...
1000 domainlabel nicelabel
; // Rich text label encoded using canonically precomposed UTF-8
1001 domainlabel hostlabel
; // Conforms to RFC 1034 "letter-digit-hyphen" ARPANET host name rules
1002 domainname hostname
; // Host Name, e.g. "Foo.local."
1003 UTF8str255 HIHardware
;
1004 UTF8str255 HISoftware
;
1005 AuthRecord
*ResourceRecords
;
1006 AuthRecord
*DuplicateRecords
; // Records currently 'on hold' because they are duplicates of existing records
1007 AuthRecord
*LocalOnlyRecords
; // Local records registered with InterfaceID set to ~0 ("local only")
1008 AuthRecord
*NewLocalOnlyRecords
; // Fresh local-only records not yet delivered to local-only questions
1009 mDNSBool DiscardLocalOnlyRecords
;// Set when we have "remove" events we need to deliver to local-only questions
1010 AuthRecord
*CurrentRecord
; // Next AuthRecord about to be examined
1011 NetworkInterfaceInfo
*HostInterfaces
;
1012 mDNSs32 ProbeFailTime
;
1013 mDNSs32 NumFailedProbes
;
1014 mDNSs32 SuppressProbes
;
1017 // ***************************************************************************
1019 #pragma mark - Useful Static Constants
1022 extern const mDNSIPPort zeroIPPort
;
1023 extern const mDNSv4Addr zeroIPAddr
;
1024 extern const mDNSv6Addr zerov6Addr
;
1025 extern const mDNSv4Addr onesIPv4Addr
;
1026 extern const mDNSv6Addr onesIPv6Addr
;
1027 extern const mDNSInterfaceID mDNSInterface_Any
;
1029 extern const mDNSIPPort UnicastDNSPort
;
1030 extern const mDNSIPPort MulticastDNSPort
;
1031 extern const mDNSv4Addr AllDNSAdminGroup
;
1032 extern const mDNSv4Addr AllDNSLinkGroup
;
1033 extern const mDNSv6Addr AllDNSLinkGroupv6
;
1034 extern const mDNSAddr AllDNSLinkGroup_v4
;
1035 extern const mDNSAddr AllDNSLinkGroup_v6
;
1037 // ***************************************************************************
1039 #pragma mark - Main Client Functions
1042 // Every client should call mDNS_Init, passing in storage for the mDNS object, mDNS_PlatformSupport object, and rrcache.
1043 // The rrcachesize parameter is the size of (i.e. number of entries in) the rrcache array passed in.
1044 // When mDNS has finished setting up the client's callback is called
1045 // A client can also spin and poll the mDNSPlatformStatus field to see when it changes from mStatus_Waiting to mStatus_NoError
1047 // Call mDNS_Close to tidy up before exiting
1049 // Call mDNS_Register with a completed AuthRecord object to register a resource record
1050 // If the resource record type is kDNSRecordTypeUnique (or kDNSknownunique) then if a conflicting resource record is discovered,
1051 // the resource record's mDNSRecordCallback will be called with error code mStatus_NameConflict. The callback should deregister
1052 // the record, and may then try registering the record again after picking a new name (e.g. by automatically appending a number).
1054 // Call mDNS_StartQuery to initiate a query. mDNS will proceed to issue Multicast DNS query packets, and any time a response
1055 // is received containing a record which matches the question, the DNSQuestion's mDNSAnswerCallback function will be called
1056 // Call mDNS_StopQuery when no more answers are required
1058 // The mDNS routines are intentionally not thread-safe -- adding locking operations would add overhead that may not
1059 // be necessary or appropriate on every platform. Instead, code in a pre-emptive environment calling any mDNS routine
1060 // (except mDNS_Init and mDNS_Close) is responsible for doing the necessary synchronization to ensure that mDNS code is
1061 // not re-entered. This includes both client software above mDNS, and the platform support code below. For example, if
1062 // the support code on a particular platform implements timer callbacks at interrupt time, then clients on that platform
1063 // need to disable interrupts or do similar concurrency control to ensure that the mDNS code is not entered by an
1064 // interrupt-time timer callback while in the middle of processing a client call.
1066 extern mStatus
mDNS_Init (mDNS
*const m
, mDNS_PlatformSupport
*const p
,
1067 CacheRecord
*rrcachestorage
, mDNSu32 rrcachesize
,
1068 mDNSBool AdvertiseLocalAddresses
,
1069 mDNSCallback
*Callback
, void *Context
);
1070 #define mDNS_Init_NoCache mDNSNULL
1071 #define mDNS_Init_ZeroCacheSize 0
1072 #define mDNS_Init_AdvertiseLocalAddresses mDNStrue
1073 #define mDNS_Init_DontAdvertiseLocalAddresses mDNSfalse
1074 #define mDNS_Init_NoInitCallback mDNSNULL
1075 #define mDNS_Init_NoInitCallbackContext mDNSNULL
1076 extern void mDNS_GrowCache (mDNS
*const m
, CacheRecord
*storage
, mDNSu32 numrecords
);
1077 extern void mDNS_Close (mDNS
*const m
);
1078 extern mDNSs32
mDNS_Execute (mDNS
*const m
);
1080 extern mStatus
mDNS_Register (mDNS
*const m
, AuthRecord
*const rr
);
1081 extern mStatus
mDNS_Update (mDNS
*const m
, AuthRecord
*const rr
, mDNSu32 newttl
,
1082 const mDNSu16 newrdlength
,
1083 RData
*const newrdata
, mDNSRecordUpdateCallback
*Callback
);
1084 extern mStatus
mDNS_Deregister(mDNS
*const m
, AuthRecord
*const rr
);
1086 extern mStatus
mDNS_StartQuery(mDNS
*const m
, DNSQuestion
*const question
);
1087 extern mStatus
mDNS_StopQuery (mDNS
*const m
, DNSQuestion
*const question
);
1088 extern mStatus
mDNS_Reconfirm (mDNS
*const m
, CacheRecord
*const cacherr
);
1089 extern mStatus
mDNS_ReconfirmByValue(mDNS
*const m
, ResourceRecord
*const rr
);
1091 // ***************************************************************************
1093 #pragma mark - Platform support functions that are accessible to the client layer too
1096 extern mDNSs32 mDNSPlatformOneSecond
;
1097 extern mDNSs32
mDNSPlatformTimeNow(void);
1099 // ***************************************************************************
1101 #pragma mark - General utility and helper functions
1104 // mDNS_RegisterService is a single call to register the set of resource records associated with a given named service.
1106 // mDNS_StartResolveService is single call which is equivalent to multiple calls to mDNS_StartQuery,
1107 // to find the IP address, port number, and demultiplexing information for a given named service.
1108 // As with mDNS_StartQuery, it executes asynchronously, and calls the ServiceInfoQueryCallback when the answer is
1109 // found. After the service is resolved, the client should call mDNS_StopResolveService to complete the transaction.
1110 // The client can also call mDNS_StopResolveService at any time to abort the transaction.
1112 // mDNS_GetBrowseDomains is a special case of the mDNS_StartQuery call, where the resulting answers
1113 // are a list of PTR records indicating (in the rdata) domains that are recommended for browsing.
1114 // After getting the list of domains to browse, call mDNS_StopQuery to end the search.
1115 // mDNS_GetDefaultBrowseDomain returns the name of the domain that should be highlighted by default.
1117 // mDNS_GetRegistrationDomains and mDNS_GetDefaultRegistrationDomain are the equivalent calls to get the list
1118 // of one or more domains that should be offered to the user as choices for where they may register their service,
1119 // and the default domain in which to register in the case where the user has made no selection.
1121 extern void mDNS_SetupResourceRecord(AuthRecord
*rr
, RData
*RDataStorage
, mDNSInterfaceID InterfaceID
,
1122 mDNSu16 rrtype
, mDNSu32 ttl
, mDNSu8 RecordType
, mDNSRecordCallback Callback
, void *Context
);
1124 extern mStatus
mDNS_RegisterService (mDNS
*const m
, ServiceRecordSet
*sr
,
1125 const domainlabel
*const name
, const domainname
*const type
, const domainname
*const domain
,
1126 const domainname
*const host
, mDNSIPPort port
, const mDNSu8 txtinfo
[], mDNSu16 txtlen
,
1127 AuthRecord
*SubTypes
, mDNSu32 NumSubTypes
,
1128 const mDNSInterfaceID InterfaceID
, mDNSServiceCallback Callback
, void *Context
);
1129 extern mStatus
mDNS_AddRecordToService(mDNS
*const m
, ServiceRecordSet
*sr
, ExtraResourceRecord
*extra
, RData
*rdata
, mDNSu32 ttl
);
1130 extern mStatus
mDNS_RemoveRecordFromService(mDNS
*const m
, ServiceRecordSet
*sr
, ExtraResourceRecord
*extra
);
1131 extern mStatus
mDNS_RenameAndReregisterService(mDNS
*const m
, ServiceRecordSet
*const sr
, const domainlabel
*newname
);
1132 extern mStatus
mDNS_DeregisterService(mDNS
*const m
, ServiceRecordSet
*sr
);
1134 extern mStatus
mDNS_RegisterNoSuchService(mDNS
*const m
, AuthRecord
*const rr
,
1135 const domainlabel
*const name
, const domainname
*const type
, const domainname
*const domain
,
1136 const domainname
*const host
,
1137 const mDNSInterfaceID InterfaceID
, mDNSRecordCallback Callback
, void *Context
);
1138 #define mDNS_DeregisterNoSuchService mDNS_Deregister
1140 extern mStatus
mDNS_StartBrowse(mDNS
*const m
, DNSQuestion
*const question
,
1141 const domainname
*const srv
, const domainname
*const domain
,
1142 const mDNSInterfaceID InterfaceID
, mDNSQuestionCallback
*Callback
, void *Context
);
1143 #define mDNS_StopBrowse mDNS_StopQuery
1145 extern mStatus
mDNS_StartResolveService(mDNS
*const m
, ServiceInfoQuery
*query
, ServiceInfo
*info
, mDNSServiceInfoQueryCallback
*Callback
, void *Context
);
1146 extern void mDNS_StopResolveService (mDNS
*const m
, ServiceInfoQuery
*query
);
1150 mDNS_DomainTypeBrowse
= 0,
1151 mDNS_DomainTypeBrowseDefault
= 1,
1152 mDNS_DomainTypeRegistration
= 2,
1153 mDNS_DomainTypeRegistrationDefault
= 3
1156 extern mStatus
mDNS_GetDomains(mDNS
*const m
, DNSQuestion
*const question
, mDNS_DomainType DomainType
, const mDNSInterfaceID InterfaceID
, mDNSQuestionCallback
*Callback
, void *Context
);
1157 #define mDNS_StopGetDomains mDNS_StopQuery
1158 extern mStatus
mDNS_AdvertiseDomains(mDNS
*const m
, AuthRecord
*rr
, mDNS_DomainType DomainType
, const mDNSInterfaceID InterfaceID
, char *domname
);
1159 #define mDNS_StopAdvertiseDomains mDNS_Deregister
1161 // ***************************************************************************
1163 #pragma mark - DNS name utility functions
1166 // In order to expose the full capabilities of the DNS protocol (which allows any arbitrary eight-bit values
1167 // in domain name labels, including unlikely characters like ascii nulls and even dots) all the mDNS APIs
1168 // work with DNS's native length-prefixed strings. For convenience in C, the following utility functions
1169 // are provided for converting between C's null-terminated strings and DNS's length-prefixed strings.
1171 // Comparison functions
1172 extern mDNSBool
SameDomainLabel(const mDNSu8
*a
, const mDNSu8
*b
);
1173 extern mDNSBool
SameDomainName(const domainname
*const d1
, const domainname
*const d2
);
1175 // Get total length of domain name, in native DNS format, including terminal root label
1176 // (e.g. length of "com." is 5 (length byte, three data bytes, final zero)
1177 extern mDNSu16
DomainNameLength(const domainname
*const name
);
1179 // Append functions to append one or more labels to an existing native format domain name:
1180 // AppendLiteralLabelString adds a single label from a literal C string, with no escape character interpretation.
1181 // AppendDNSNameString adds zero or more labels from a C string using conventional DNS dots-and-escaping interpretation
1182 // AppendDomainLabel adds a single label from a native format domainlabel
1183 // AppendDomainName adds zero or more labels from a native format domainname
1184 extern mDNSu8
*AppendLiteralLabelString(domainname
*const name
, const char *cstr
);
1185 extern mDNSu8
*AppendDNSNameString (domainname
*const name
, const char *cstr
);
1186 extern mDNSu8
*AppendDomainLabel (domainname
*const name
, const domainlabel
*const label
);
1187 extern mDNSu8
*AppendDomainName (domainname
*const name
, const domainname
*const append
);
1189 // Convert from null-terminated string to native DNS format:
1190 // The DomainLabel form makes a single label from a literal C string, with no escape character interpretation.
1191 // The DomainName form makes native format domain name from a C string using conventional DNS interpretation:
1192 // dots separate labels, and within each label, '\.' represents a literal dot, '\\' represents a literal
1193 // backslash and backslash with three decimal digits (e.g. \000) represents an arbitrary byte value.
1194 extern mDNSBool
MakeDomainLabelFromLiteralString(domainlabel
*const label
, const char *cstr
);
1195 extern mDNSu8
*MakeDomainNameFromDNSNameString (domainname
*const name
, const char *cstr
);
1197 // Convert native format domainlabel or domainname back to C string format
1198 extern char *ConvertDomainLabelToCString_withescape(const domainlabel
*const name
, char *cstr
, char esc
);
1199 #define ConvertDomainLabelToCString_unescaped(D,C) ConvertDomainLabelToCString_withescape((D), (C), 0)
1200 #define ConvertDomainLabelToCString(D,C) ConvertDomainLabelToCString_withescape((D), (C), '\\')
1201 extern char *ConvertDomainNameToCString_withescape(const domainname
*const name
, char *cstr
, char esc
);
1202 #define ConvertDomainNameToCString_unescaped(D,C) ConvertDomainNameToCString_withescape((D), (C), 0)
1203 #define ConvertDomainNameToCString(D,C) ConvertDomainNameToCString_withescape((D), (C), '\\')
1205 extern void ConvertUTF8PstringToRFC1034HostLabel(const mDNSu8 UTF8Name
[], domainlabel
*const hostlabel
);
1207 extern mDNSu8
*ConstructServiceName(domainname
*const fqdn
, const domainlabel
*name
, const domainname
*type
, const domainname
*const domain
);
1208 extern mDNSBool
DeconstructServiceName(const domainname
*const fqdn
, domainlabel
*const name
, domainname
*const type
, domainname
*const domain
);
1210 // Note: Some old functions have been replaced by more sensibly-named versions.
1211 // You can uncomment the hash-defines below if you don't want to have to change your source code right away.
1212 // When updating your code, note that (unlike the old versions) *all* the new routines take the target object
1213 // as their first parameter.
1214 //#define ConvertCStringToDomainName(SRC,DST) MakeDomainNameFromDNSNameString((DST),(SRC))
1215 //#define ConvertCStringToDomainLabel(SRC,DST) MakeDomainLabelFromLiteralString((DST),(SRC))
1216 //#define AppendStringLabelToName(DST,SRC) AppendLiteralLabelString((DST),(SRC))
1217 //#define AppendStringNameToName(DST,SRC) AppendDNSNameString((DST),(SRC))
1218 //#define AppendDomainLabelToName(DST,SRC) AppendDomainLabel((DST),(SRC))
1219 //#define AppendDomainNameToName(DST,SRC) AppendDomainName((DST),(SRC))
1221 // ***************************************************************************
1223 #pragma mark - Other utility functions
1226 extern mDNSu32
mDNS_vsnprintf(char *sbuffer
, mDNSu32 buflen
, const char *fmt
, va_list arg
);
1227 extern mDNSu32
mDNS_snprintf(char *sbuffer
, mDNSu32 buflen
, const char *fmt
, ...) IS_A_PRINTF_STYLE_FUNCTION(3,4);
1228 extern char *DNSTypeName(mDNSu16 rrtype
);
1229 extern char *GetRRDisplayString_rdb(mDNS
*const m
, const ResourceRecord
*rr
, RDataBody
*rd
);
1230 #define GetRRDisplayString(m, rr) GetRRDisplayString_rdb((m), &(rr)->resrec, &(rr)->resrec.rdata->u)
1231 extern mDNSBool
mDNSSameAddress(const mDNSAddr
*ip1
, const mDNSAddr
*ip2
);
1232 extern void IncrementLabelSuffix(domainlabel
*name
, mDNSBool RichText
);