]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSCore/mDNSClientAPI.h
mDNSResponder-58.tar.gz
[apple/mdnsresponder.git] / mDNSCore / mDNSClientAPI.h
1 /*
2 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22
23 Change History (most recent first):
24
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
31
32 Revision 1.113 2003/08/21 19:31:58 cheshire
33 Cosmetic: Swap order of fields
34
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
37
38 Revision 1.111 2003/08/21 02:21:50 cheshire
39 <rdar://problem/3386473> Efficiency: Reduce repeated queries
40
41 Revision 1.110 2003/08/20 23:39:31 cheshire
42 <rdar://problem/3344098> Review syslog messages, and remove as appropriate
43
44 Revision 1.109 2003/08/19 22:24:10 cheshire
45 Comment change
46
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
50
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.
58
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.
64
65 Revision 1.105 2003/08/19 02:33:37 cheshire
66 Update comments
67
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.
72
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
76
77 Revision 1.102 2003/08/16 03:39:00 cheshire
78 <rdar://problem/3338440> InterfaceID -1 indicates "local only"
79
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.
87
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
91
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
94
95 Revision 1.98 2003/08/12 19:56:23 cheshire
96 Update to APSL 2.0
97
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.
102
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
106
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.
110
111 Revision 1.94 2003/08/09 00:35:29 cheshire
112
113 Revision 1.93 2003/08/08 18:55:48 cheshire
114 <rdar://problem/3370365> Guard against time going backwards
115
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
118
119 Revision 1.91 2003/08/06 21:33:39 cheshire
120 Fix compiler warnings on PocketPC 2003 (Windows CE)
121
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)
124
125 Revision 1.89 2003/08/06 18:58:19 cheshire
126 Update comments
127
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)
132
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
135
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
139
140 Revision 1.85 2003/07/19 03:23:13 cheshire
141 <rdar://problem/2986147> mDNSResponder needs to receive and cache larger records
142
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
147
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
150
151 Revision 1.82 2003/07/17 17:35:04 cheshire
152 <rdar://problem/3325583> Rate-limit responses, to guard against packet flooding
153
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
157
158 Revision 1.80 2003/07/15 01:55:12 cheshire
159 <rdar://problem/3315777> Need to implement service registration with subtypes
160
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
164
165 Revision 1.78 2003/07/13 01:47:53 cheshire
166 Fix one error and one warning in the Windows build
167
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".
171
172 Revision 1.76 2003/07/11 01:28:00 cheshire
173 <rdar://problem/3161289> No more local.arpa
174
175 Revision 1.75 2003/07/02 21:19:45 cheshire
176 <rdar://problem/3313413> Update copyright notices, etc., in source code comments
177
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
180
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
186
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
189
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
192
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
195
196 Revision 1.69 2003/06/07 04:22:17 cheshire
197 Add MsgBuffer for error log and debug messages
198
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
201
202 Revision 1.67 2003/06/07 01:22:14 cheshire
203 <rdar://problem/3283516> mDNSResponder needs an mDNS_Reconfirm() function
204
205 Revision 1.66 2003/06/07 00:59:43 cheshire
206 <rdar://problem/3283454> Need some randomness to spread queries on the network
207
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
210
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.)
214
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.)
218
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
222
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
225
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
228
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
231
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
234
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
240
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
243
244 Revision 1.55 2003/05/26 00:47:30 cheshire
245 Comment clarification
246
247 Revision 1.54 2003/05/24 16:39:48 cheshire
248 <rdar://problem/3268631> SendResponses also needs to handle multihoming better
249
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.)
255
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 :-)
259
260 Revision 1.51 2003/05/21 20:14:55 cheshire
261 Fix comments and warnings
262
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.
270
271 Revision 1.49 2003/05/07 01:49:36 cheshire
272 Remove "const" in ConstructServiceName prototype
273
274 Revision 1.48 2003/05/07 00:18:44 cheshire
275 Fix typo: "kDNSQClass_Mask" should be "kDNSClass_Mask"
276
277 Revision 1.47 2003/05/06 00:00:46 cheshire
278 <rdar://problem/3248914> Rationalize naming of domainname manipulation functions
279
280 Revision 1.46 2003/04/30 20:39:09 cheshire
281 Add comment
282
283 Revision 1.45 2003/04/29 00:40:50 cheshire
284 Fix compiler warnings
285
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
288
289 Revision 1.43 2003/04/25 01:45:56 cheshire
290 <rdar://problem/3240002> mDNS_RegisterNoSuchService needs to include a host name
291
292 Revision 1.42 2003/04/15 20:58:31 jgraessl
293
294 Bug #: 3229014
295 Added a hash to lookup records in the cache.
296
297 Revision 1.41 2003/04/15 18:09:13 jgraessl
298
299 Bug #: 3228892
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.
303
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
307
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
311 Fixes:
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)
315
316 Revision 1.38 2003/03/15 04:40:36 cheshire
317 Change type called "mDNSOpaqueID" to the more descriptive name "mDNSInterfaceID"
318
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
322
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
326
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
332
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")
336
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
340
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
345
346 Revision 1.31 2003/01/29 02:46:37 cheshire
347 Fix for IPv6:
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.
352
353 Revision 1.30 2003/01/29 01:47:08 cheshire
354 Rename 'Active' to 'CRActive' or 'InterfaceActive' for improved clarity
355
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
359
360 Revision 1.28 2003/01/28 01:35:56 cheshire
361 Revise comment about ThisQInterval to reflect new semantics
362
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
368
369 Revision 1.26 2002/12/23 22:13:28 jgraessl
370
371 Reviewed by: Stuart Cheshire
372 Initial IPv6 support for mDNSResponder.
373
374 Revision 1.25 2002/09/21 20:44:49 zarzycki
375 Added APSL info
376
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
380
381 Revision 1.23 2002/09/19 21:25:34 cheshire
382 mDNS_snprintf() doesn't need to be in a separate file
383
384 Revision 1.22 2002/09/19 04:20:43 cheshire
385 Remove high-ascii characters that confuse some systems
386
387 Revision 1.21 2002/09/17 01:06:35 cheshire
388 Change mDNS_AdvertiseLocalAddresses to be a parameter to mDNS_Init()
389
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
392
393 */
394
395 #ifndef __mDNSClientAPI_h
396 #define __mDNSClientAPI_h
397
398 #include <stdarg.h> // stdarg.h is required for for va_list support for the mDNS_vsnprintf declaration
399 #include "mDNSDebug.h"
400
401 #ifdef __cplusplus
402 extern "C" {
403 #endif
404
405 // ***************************************************************************
406 // Function scope indicators
407
408 // If you see "mDNSlocal" before a function name, it means the function is not callable outside this file
409 #ifndef mDNSlocal
410 #define mDNSlocal static
411 #endif
412 // If you see "mDNSexport" before a symbol, it means the symbol is exported for use by clients
413 #ifndef mDNSexport
414 #define mDNSexport
415 #endif
416
417 // ***************************************************************************
418 #if 0
419 #pragma mark - DNS Resource Record class and type constants
420 #endif
421
422 typedef enum // From RFC 1035
423 {
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]
429
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
432
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"
435 } DNS_ClassValues;
436
437 typedef enum // From RFC 1035
438 {
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
455
456 kDNSType_AAAA = 28, // 28 IPv6 address
457 kDNSType_SRV = 33, // 33 Service record
458
459 kDNSQType_ANY = 255 // Not a DNS type, but a DNS query type, meaning "all types"
460 } DNS_TypeValues;
461
462 // ***************************************************************************
463 #if 0
464 #pragma mark - Simple types
465 #endif
466
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;
476
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;
481
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;
492
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)
496
497 enum
498 {
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
503 };
504
505 typedef struct
506 {
507 mDNSs32 type;
508 union { mDNSv6Addr v6; mDNSv4Addr v4; } ip;
509 } mDNSAddr;
510
511 enum { mDNSfalse = 0, mDNStrue = 1 };
512
513 #define mDNSNULL 0L
514
515 enum
516 {
517 mStatus_Waiting = 1,
518 mStatus_NoError = 0,
519
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
538 };
539
540 typedef mDNSs32 mStatus;
541
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
545
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
549
550 typedef struct { mDNSu8 c[256]; } UTF8str255; // Null-terminated C string
551
552 // ***************************************************************************
553 #if 0
554 #pragma mark - Resource Record structures
555 #endif
556
557 // Authoritative Resource Records:
558 // There are four basic types: Shared, Advisory, Unique, Known Unique
559
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
567 //
568 // * Advisory Resource Records are like Shared Resource Records, except they don't send a goodbye packet
569 //
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
576
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).
580
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?
585 //
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
590 // Advisory No No No
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
594
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
600
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.
603
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
609
610 enum
611 {
612 kDNSRecordTypeUnregistered = 0x00, // Not currently in any list
613 kDNSRecordTypeDeregistering = 0x01, // Shared record about to announce its departure and leave the list
614
615 kDNSRecordTypeUnique = 0x02, // Will become a kDNSRecordTypeVerified when probing is complete
616
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
621
622 kDNSRecordTypeUniqueMask = (kDNSRecordTypeUnique | kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique),
623 kDNSRecordTypeActiveMask = (kDNSRecordTypeAdvisory | kDNSRecordTypeShared | kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique),
624
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
629
630 kDNSRecordTypePacketAnsMask = 0x40, // True for PacketAns and PacketAnsUnique
631 kDNSRecordTypePacketUniqueMask = 0x20 // True for PacketAddUnique and PacketAnsUnique
632 };
633
634 typedef struct { mDNSu16 priority; mDNSu16 weight; mDNSIPPort port; domainname target; } rdataSRV;
635 typedef struct { mDNSu16 preference; domainname exchange; } rdataMX;
636
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
641
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
653
654 typedef union
655 {
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
663 } RDataBody;
664
665 typedef struct
666 {
667 mDNSu16 MaxRDLength; // Amount of storage allocated for rdata (usually sizeof(RDataBody))
668 RDataBody u;
669 } RData;
670 #define sizeofRDataHeader (sizeof(RData) - sizeof(RDataBody))
671
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;
678
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);
681
682 // Note:
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);
687
688 struct ResourceRecord_struct
689 {
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)
695 domainname name;
696 mDNSu16 rrtype;
697 mDNSu16 rrclass;
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
705 };
706
707 struct AuthRecord_struct
708 {
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
713
714 AuthRecord *next; // Next in list; first element of structure for efficiency reasons
715 ResourceRecord resrec;
716
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
725
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
750
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
755 };
756
757 struct CacheRecord_struct
758 {
759 CacheRecord *next; // Next in list; first element of structure for efficiency reasons
760 ResourceRecord resrec;
761
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
776
777 struct { mDNSu16 MaxRDLength; mDNSu8 data[InlineCacheRDSize]; } rdatastorage; // Storage for small records is right here
778 };
779
780 typedef struct
781 {
782 CacheRecord r;
783 mDNSu8 _extradata[MaximumRDSize-InlineCacheRDSize]; // Glue on the necessary number of extra bytes
784 } LargeCacheRecord;
785
786 typedef struct NetworkInterfaceInfo_struct NetworkInterfaceInfo;
787
788 struct NetworkInterfaceInfo_struct
789 {
790 // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
791 NetworkInterfaceInfo *next;
792
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
800
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
804 AuthRecord RR_HINFO;
805
806 // Client API fields: The client must set up these fields *before* calling mDNS_RegisterInterface()
807 mDNSInterfaceID InterfaceID;
808 mDNSAddr ip;
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
811 };
812
813 typedef struct ExtraResourceRecord_struct ExtraResourceRecord;
814 struct ExtraResourceRecord_struct
815 {
816 ExtraResourceRecord *next;
817 AuthRecord r;
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
821 };
822
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
827 {
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
834 mDNSu32 NumSubTypes;
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
844 };
845
846 // ***************************************************************************
847 #if 0
848 #pragma mark - Question structures
849 #endif
850
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
856
857 typedef struct
858 {
859 mDNSs32 Time;
860 mDNSInterfaceID InterfaceID;
861 mDNSs32 Type; // v4 or v6?
862 } DupSuppressInfo;
863
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
867 {
868 // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
869 DNSQuestion *next;
870 mDNSu32 qnamehash;
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
886
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
889 domainname qname;
890 mDNSu16 qtype;
891 mDNSu16 qclass;
892 mDNSQuestionCallback *QuestionCallback;
893 void *QuestionContext;
894 };
895
896 typedef struct
897 {
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.
900 domainname name;
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
904 mDNSu16 TXTlen;
905 mDNSu8 TXTinfo[2048]; // Additional demultiplexing information (e.g. LPR queue name)
906 } ServiceInfo;
907
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
912 {
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.
919 DNSQuestion qSRV;
920 DNSQuestion qTXT;
921 DNSQuestion qAv4;
922 DNSQuestion qAv6;
923 mDNSu8 GotSRV;
924 mDNSu8 GotTXT;
925 mDNSu8 GotADD;
926 mDNSu32 Answers;
927 ServiceInfo *info;
928 mDNSServiceInfoQueryCallback *ServiceInfoQueryCallback;
929 void *ServiceInfoQueryContext;
930 };
931
932 // ***************************************************************************
933 #if 0
934 #pragma mark - Main mDNS object, used to hold all the mDNS state
935 #endif
936
937 typedef void mDNSCallback(mDNS *const m, mStatus result);
938
939 #define CACHE_HASH_SLOTS 499
940
941 enum
942 {
943 mDNS_KnownBug_PhantomInterfaces = 1
944 };
945
946 struct mDNS_struct
947 {
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.
952
953 mDNS_PlatformSupport *p; // Pointer to platform-specific data of indeterminite size
954 mDNSu32 KnownBugs;
955 mDNSBool AdvertiseLocalAddresses;
956 mStatus mDNSPlatformStatus;
957 mDNSCallback *MainCallback;
958 void *MainContext;
959
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;
966 mDNSu8 lock_Records;
967 char MsgBuffer[80]; // Temp storage used while building error log messages
968
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)
984
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];
998
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;
1015 };
1016
1017 // ***************************************************************************
1018 #if 0
1019 #pragma mark - Useful Static Constants
1020 #endif
1021
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;
1028
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;
1036
1037 // ***************************************************************************
1038 #if 0
1039 #pragma mark - Main Client Functions
1040 #endif
1041
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
1046 //
1047 // Call mDNS_Close to tidy up before exiting
1048 //
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).
1053 //
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
1057 //
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.
1065
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);
1079
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);
1085
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);
1090
1091 // ***************************************************************************
1092 #if 0
1093 #pragma mark - Platform support functions that are accessible to the client layer too
1094 #endif
1095
1096 extern mDNSs32 mDNSPlatformOneSecond;
1097 extern mDNSs32 mDNSPlatformTimeNow(void);
1098
1099 // ***************************************************************************
1100 #if 0
1101 #pragma mark - General utility and helper functions
1102 #endif
1103
1104 // mDNS_RegisterService is a single call to register the set of resource records associated with a given named service.
1105 //
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.
1111 //
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.
1116 //
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.
1120
1121 extern void mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mDNSInterfaceID InterfaceID,
1122 mDNSu16 rrtype, mDNSu32 ttl, mDNSu8 RecordType, mDNSRecordCallback Callback, void *Context);
1123
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);
1133
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
1139
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
1144
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);
1147
1148 typedef enum
1149 {
1150 mDNS_DomainTypeBrowse = 0,
1151 mDNS_DomainTypeBrowseDefault = 1,
1152 mDNS_DomainTypeRegistration = 2,
1153 mDNS_DomainTypeRegistrationDefault = 3
1154 } mDNS_DomainType;
1155
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
1160
1161 // ***************************************************************************
1162 #if 0
1163 #pragma mark - DNS name utility functions
1164 #endif
1165
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.
1170
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);
1174
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);
1178
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);
1188
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);
1196
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), '\\')
1204
1205 extern void ConvertUTF8PstringToRFC1034HostLabel(const mDNSu8 UTF8Name[], domainlabel *const hostlabel);
1206
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);
1209
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))
1220
1221 // ***************************************************************************
1222 #if 0
1223 #pragma mark - Other utility functions
1224 #endif
1225
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);
1233
1234 #ifdef __cplusplus
1235 }
1236 #endif
1237
1238 #endif