]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSCore/mDNSEmbeddedAPI.h
mDNSResponder-58.8.1.tar.gz
[apple/mdnsresponder.git] / mDNSCore / mDNSEmbeddedAPI.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: mDNSEmbeddedAPI.h,v $
26 Revision 1.114.2.9 2004/04/22 03:17:35 cheshire
27 Fix use of "struct __attribute__((__packed__))" so it only applies on GCC >= 2.9
28
29 Revision 1.114.2.8 2004/03/30 06:55:37 cheshire
30 Gave name to anonymous struct, to avoid errors on certain compilers.
31 (Thanks to ramaprasad.kr@hp.com for reporting this.)
32
33 Revision 1.114.2.7 2004/03/09 02:31:27 cheshire
34 Remove erroneous underscore in 'packed_struct' (makes no difference now, but might in future)
35
36 Revision 1.114.2.6 2004/03/02 02:55:25 cheshire
37 <rdar://problem/3549576> Properly support "_services._dns-sd._udp" meta-queries
38
39 Revision 1.114.2.5 2004/02/18 23:35:17 cheshire
40 <rdar://problem/3488559>: Hard code domain enumeration functions to return ".local" only
41 Also make mDNS_StopGetDomains() a no-op too, so that we don't get warning messages in syslog
42
43 Revision 1.114.2.4 2004/01/28 23:29:20 cheshire
44 Fix structure packing (only affects third-party Darwin developers)
45
46 Revision 1.114.2.3 2003/12/05 00:03:34 cheshire
47 <rdar://problem/3487869> Use buffer size MAX_ESCAPED_DOMAIN_NAME instead of 256
48
49 Revision 1.114.2.2 2003/12/04 23:30:00 cheshire
50 Add "#define MAX_ESCAPED_DOMAIN_NAME 1005", needed for Posix folder to build
51
52 Revision 1.114.2.1 2003/12/03 11:07:58 cheshire
53 <rdar://problem/3457718>: Stop and start of a service uses old ip address (with old port number)
54
55 Revision 1.114 2003/08/29 19:44:15 cheshire
56 <rdar://problem/3400967> Traffic reduction: Eliminate synchronized QUs when a new service appears
57 1. Use m->RandomQueryDelay to impose a random delay in the range 0-500ms on queries
58 that already have at least one unique answer in the cache
59 2. For these queries, go straight to QM, skipping QU
60
61 Revision 1.113 2003/08/21 19:31:58 cheshire
62 Cosmetic: Swap order of fields
63
64 Revision 1.112 2003/08/21 19:27:36 cheshire
65 <rdar://problem/3387878> Traffic reduction: No need to announce record for longer than TTL
66
67 Revision 1.111 2003/08/21 02:21:50 cheshire
68 <rdar://problem/3386473> Efficiency: Reduce repeated queries
69
70 Revision 1.110 2003/08/20 23:39:31 cheshire
71 <rdar://problem/3344098> Review syslog messages, and remove as appropriate
72
73 Revision 1.109 2003/08/19 22:24:10 cheshire
74 Comment change
75
76 Revision 1.108 2003/08/19 22:20:00 cheshire
77 <rdar://problem/3376721> Don't use IPv6 on interfaces that have a routable IPv4 address configured
78 More minor refinements
79
80 Revision 1.107 2003/08/19 06:48:25 cheshire
81 <rdar://problem/3376552> Guard against excessive record updates
82 Each record starts with 10 UpdateCredits.
83 Every update consumes one UpdateCredit.
84 UpdateCredits are replenished at a rate of one one per minute, up to a maximum of 10.
85 As the number of UpdateCredits declines, the number of announcements is similarly scaled back.
86 When fewer than 5 UpdateCredits remain, the first announcement is also delayed by an increasing amount.
87
88 Revision 1.106 2003/08/19 04:49:28 cheshire
89 <rdar://problem/3368159> Interaction between v4, v6 and dual-stack hosts not working quite right
90 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.
91 2. When we see the first v4 (or first v6) member of a group, we re-trigger questions and probes on that interface.
92 3. When we see the last v4 (or v6) member of a group go away, we revalidate all the records received on that interface.
93
94 Revision 1.105 2003/08/19 02:33:37 cheshire
95 Update comments
96
97 Revision 1.104 2003/08/19 02:31:11 cheshire
98 <rdar://problem/3378386> mDNSResponder overenthusiastic with final expiration queries
99 Final expiration queries now only mark the question for sending on the particular interface
100 pertaining to the record that's expiring.
101
102 Revision 1.103 2003/08/18 19:05:44 cheshire
103 <rdar://problem/3382423> UpdateRecord not working right
104 Added "newrdlength" field to hold new length of updated rdata
105
106 Revision 1.102 2003/08/16 03:39:00 cheshire
107 <rdar://problem/3338440> InterfaceID -1 indicates "local only"
108
109 Revision 1.101 2003/08/15 20:16:02 cheshire
110 <rdar://problem/3366590> mDNSResponder takes too much RPRVT
111 We want to avoid touching the rdata pages, so we don't page them in.
112 1. RDLength was stored with the rdata, which meant touching the page just to find the length.
113 Moved this from the RData to the ResourceRecord object.
114 2. To avoid unnecessarily touching the rdata just to compare it,
115 compute a hash of the rdata and store the hash in the ResourceRecord object.
116
117 Revision 1.100 2003/08/14 19:29:04 cheshire
118 <rdar://problem/3378473> Include cache records in SIGINFO output
119 Moved declarations of DNSTypeName() and GetRRDisplayString to mDNSEmbeddedAPI.h so daemon.c can use them
120
121 Revision 1.99 2003/08/14 02:17:05 cheshire
122 <rdar://problem/3375491> Split generic ResourceRecord type into two separate types: AuthRecord and CacheRecord
123
124 Revision 1.98 2003/08/12 19:56:23 cheshire
125 Update to APSL 2.0
126
127 Revision 1.97 2003/08/12 14:59:27 cheshire
128 <rdar://problem/3374490> Rate-limiting blocks some legitimate responses
129 When setting LastMCTime also record LastMCInterface. When checking LastMCTime to determine
130 whether to suppress the response, also check LastMCInterface to see if it matches.
131
132 Revision 1.96 2003/08/12 13:57:04 cheshire
133 <rdar://problem/3323817> Improve cache performance
134 Changed the number of hash table slots from 37 to 499
135
136 Revision 1.95 2003/08/09 00:55:02 cheshire
137 <rdar://problem/3366553> mDNSResponder is taking 20-30% of the CPU
138 Don't scan the whole cache after every packet.
139
140 Revision 1.94 2003/08/09 00:35:29 cheshire
141
142 Revision 1.93 2003/08/08 18:55:48 cheshire
143 <rdar://problem/3370365> Guard against time going backwards
144
145 Revision 1.92 2003/08/08 18:36:04 cheshire
146 <rdar://problem/3344154> Only need to revalidate on interface removal on platforms that have the PhantomInterfaces bug
147
148 Revision 1.91 2003/08/06 21:33:39 cheshire
149 Fix compiler warnings on PocketPC 2003 (Windows CE)
150
151 Revision 1.90 2003/08/06 20:30:17 cheshire
152 Add structure definition for rdataMX (not currently used, but good to have it for completeness)
153
154 Revision 1.89 2003/08/06 18:58:19 cheshire
155 Update comments
156
157 Revision 1.88 2003/07/24 23:45:44 cheshire
158 To eliminate compiler warnings, changed definition of mDNSBool from
159 "unsigned char" to "int", since "int" is in fact truly the type that C uses
160 for the result of comparison operators (a<b) and logical operators (a||b)
161
162 Revision 1.87 2003/07/22 23:57:20 cheshire
163 Move platform-layer function prototypes from mDNSEmbeddedAPI.h to mDNSPlatformFunctions.h where they belong
164
165 Revision 1.86 2003/07/20 03:52:02 ksekar
166 Bug #: <rdar://problem/3320722>: Feature: New Rendezvous APIs (#7875) (mDNSResponder component)
167 Added error type for incompatibility between daemon and client versions
168
169 Revision 1.85 2003/07/19 03:23:13 cheshire
170 <rdar://problem/2986147> mDNSResponder needs to receive and cache larger records
171
172 Revision 1.84 2003/07/18 23:52:12 cheshire
173 To improve consistency of field naming, global search-and-replace:
174 NextProbeTime -> NextScheduledProbe
175 NextResponseTime -> NextScheduledResponse
176
177 Revision 1.83 2003/07/18 00:29:59 cheshire
178 <rdar://problem/3268878> Remove mDNSResponder version from packet header and use HINFO record instead
179
180 Revision 1.82 2003/07/17 17:35:04 cheshire
181 <rdar://problem/3325583> Rate-limit responses, to guard against packet flooding
182
183 Revision 1.81 2003/07/16 05:01:36 cheshire
184 Add fields 'LargeAnswers' and 'ExpectUnicastResponse' in preparation for
185 <rdar://problem/3315761> Need to implement "unicast response" request, using top bit of qclass
186
187 Revision 1.80 2003/07/15 01:55:12 cheshire
188 <rdar://problem/3315777> Need to implement service registration with subtypes
189
190 Revision 1.79 2003/07/13 02:28:00 cheshire
191 <rdar://problem/3325166> SendResponses didn't all its responses
192 Delete all references to RRInterfaceActive -- it's now superfluous
193
194 Revision 1.78 2003/07/13 01:47:53 cheshire
195 Fix one error and one warning in the Windows build
196
197 Revision 1.77 2003/07/11 01:32:38 cheshire
198 Syntactic cleanup (no change to funcationality): Now that we only have one host name,
199 rename field "hostname1" to "hostname", and field "RR_A1" to "RR_A".
200
201 Revision 1.76 2003/07/11 01:28:00 cheshire
202 <rdar://problem/3161289> No more local.arpa
203
204 Revision 1.75 2003/07/02 21:19:45 cheshire
205 <rdar://problem/3313413> Update copyright notices, etc., in source code comments
206
207 Revision 1.74 2003/07/02 02:41:23 cheshire
208 <rdar://problem/2986146> mDNSResponder needs to start with a smaller cache and then grow it as needed
209
210 Revision 1.73 2003/06/10 04:24:39 cheshire
211 <rdar://problem/3283637> React when we observe other people query unsuccessfully for a record that's in our cache
212 Some additional refinements:
213 Don't try to do this for unicast-response queries
214 better tracking of Qs and KAs in multi-packet KA lists
215
216 Revision 1.72 2003/06/10 01:46:27 cheshire
217 Add better comments explaining how these data structures are intended to be used from the client layer
218
219 Revision 1.71 2003/06/07 06:45:05 cheshire
220 <rdar://problem/3283666> No need for multiple machines to all be sending the same queries
221
222 Revision 1.70 2003/06/07 04:50:53 cheshire
223 <rdar://problem/3283637> React when we observe other people query unsuccessfully for a record that's in our cache
224
225 Revision 1.69 2003/06/07 04:22:17 cheshire
226 Add MsgBuffer for error log and debug messages
227
228 Revision 1.68 2003/06/07 01:46:38 cheshire
229 <rdar://problem/3283540> When query produces zero results, call mDNS_Reconfirm() on any antecedent records
230
231 Revision 1.67 2003/06/07 01:22:14 cheshire
232 <rdar://problem/3283516> mDNSResponder needs an mDNS_Reconfirm() function
233
234 Revision 1.66 2003/06/07 00:59:43 cheshire
235 <rdar://problem/3283454> Need some randomness to spread queries on the network
236
237 Revision 1.65 2003/06/06 21:41:11 cheshire
238 For consistency, mDNS_StopQuery() should return an mStatus result, just like all the other mDNSCore routines
239
240 Revision 1.64 2003/06/06 21:38:55 cheshire
241 Renamed 'NewData' as 'FreshData' (The data may not be new data, just a refresh of data that we
242 already had in our cache. This refreshes our TTL on the data, but the data itself stays the same.)
243
244 Revision 1.63 2003/06/06 17:20:14 cheshire
245 For clarity, rename question fields name/rrtype/rrclass as qname/qtype/qclass
246 (Global search-and-replace; no functional change to code execution.)
247
248 Revision 1.62 2003/06/04 01:25:33 cheshire
249 <rdar://problem/3274950> Cannot perform multi-packet known-answer suppression messages
250 Display time interval between first and subsequent queries
251
252 Revision 1.61 2003/06/03 05:02:16 cheshire
253 <rdar://problem/3277080> Duplicate registrations not handled as efficiently as they should be
254
255 Revision 1.60 2003/05/31 00:09:49 cheshire
256 <rdar://problem/3274862> Add ability to discover what services are on a network
257
258 Revision 1.59 2003/05/29 06:11:35 cheshire
259 <rdar://problem/3272214>: Report if there appear to be too many "Resolve" callbacks
260
261 Revision 1.58 2003/05/29 05:48:06 cheshire
262 Minor fix for when generating printf warnings: mDNS_snprintf arguments are now 3,4
263
264 Revision 1.57 2003/05/26 03:21:27 cheshire
265 Tidy up address structure naming:
266 mDNSIPAddr => mDNSv4Addr (for consistency with mDNSv6Addr)
267 mDNSAddr.addr.ipv4 => mDNSAddr.ip.v4
268 mDNSAddr.addr.ipv6 => mDNSAddr.ip.v6
269
270 Revision 1.56 2003/05/26 03:01:27 cheshire
271 <rdar://problem/3268904> sprintf/vsprintf-style functions are unsafe; use snprintf/vsnprintf instead
272
273 Revision 1.55 2003/05/26 00:47:30 cheshire
274 Comment clarification
275
276 Revision 1.54 2003/05/24 16:39:48 cheshire
277 <rdar://problem/3268631> SendResponses also needs to handle multihoming better
278
279 Revision 1.53 2003/05/23 02:15:37 cheshire
280 Fixed misleading use of the term "duplicate suppression" where it should have
281 said "known answer suppression". (Duplicate answer suppression is something
282 different, and duplicate question suppression is yet another thing, so the use
283 of the completely vague term "duplicate suppression" was particularly bad.)
284
285 Revision 1.52 2003/05/22 02:29:22 cheshire
286 <rdar://problem/2984918> SendQueries needs to handle multihoming better
287 Complete rewrite of SendQueries. Works much better now :-)
288
289 Revision 1.51 2003/05/21 20:14:55 cheshire
290 Fix comments and warnings
291
292 Revision 1.50 2003/05/14 07:08:36 cheshire
293 <rdar://problem/3159272> mDNSResponder should be smarter about reconfigurations
294 Previously, when there was any network configuration change, mDNSResponder
295 would tear down the entire list of active interfaces and start again.
296 That was very disruptive, and caused the entire cache to be flushed,
297 and caused lots of extra network traffic. Now it only removes interfaces
298 that have really gone, and only adds new ones that weren't there before.
299
300 Revision 1.49 2003/05/07 01:49:36 cheshire
301 Remove "const" in ConstructServiceName prototype
302
303 Revision 1.48 2003/05/07 00:18:44 cheshire
304 Fix typo: "kDNSQClass_Mask" should be "kDNSClass_Mask"
305
306 Revision 1.47 2003/05/06 00:00:46 cheshire
307 <rdar://problem/3248914> Rationalize naming of domainname manipulation functions
308
309 Revision 1.46 2003/04/30 20:39:09 cheshire
310 Add comment
311
312 Revision 1.45 2003/04/29 00:40:50 cheshire
313 Fix compiler warnings
314
315 Revision 1.44 2003/04/26 02:41:56 cheshire
316 <rdar://problem/3241281> Change timenow from a local variable to a structure member
317
318 Revision 1.43 2003/04/25 01:45:56 cheshire
319 <rdar://problem/3240002> mDNS_RegisterNoSuchService needs to include a host name
320
321 Revision 1.42 2003/04/15 20:58:31 jgraessl
322
323 Bug #: 3229014
324 Added a hash to lookup records in the cache.
325
326 Revision 1.41 2003/04/15 18:09:13 jgraessl
327
328 Bug #: 3228892
329 Reviewed by: Stuart Cheshire
330 Added code to keep track of when the next cache item will expire so we can
331 call TidyRRCache only when necessary.
332
333 Revision 1.40 2003/03/29 01:55:19 cheshire
334 <rdar://problem/3212360> mDNSResponder sometimes suffers false self-conflicts when it sees its own packets
335 Solution: Major cleanup of packet timing and conflict handling rules
336
337 Revision 1.39 2003/03/27 03:30:55 cheshire
338 <rdar://problem/3210018> Name conflicts not handled properly, resulting in memory corruption, and eventual crash
339 Problem was that HostNameCallback() was calling mDNS_DeregisterInterface(), which is not safe in a callback
340 Fixes:
341 1. Make mDNS_DeregisterInterface() safe to call from a callback
342 2. Make HostNameCallback() use mDNS_DeadvertiseInterface() instead
343 (it never really needed to deregister the interface at all)
344
345 Revision 1.38 2003/03/15 04:40:36 cheshire
346 Change type called "mDNSOpaqueID" to the more descriptive name "mDNSInterfaceID"
347
348 Revision 1.37 2003/03/14 21:34:11 cheshire
349 <rdar://problem/3176950> Can't setup and print to Lexmark PS printers via Airport Extreme
350 Increase size of cache rdata from 512 to 768
351
352 Revision 1.36 2003/03/05 03:38:35 cheshire
353 Bug #: 3185731 Bogus error message in console: died or deallocated, but no record of client can be found!
354 Fixed by leaving client in list after conflict, until client explicitly deallocates
355
356 Revision 1.35 2003/02/21 02:47:54 cheshire
357 Bug #: 3099194 mDNSResponder needs performance improvements
358 Several places in the code were calling CacheRRActive(), which searched the entire
359 question list every time, to see if this cache resource record answers any question.
360 Instead, we now have a field "CRActiveQuestion" in the resource record structure
361
362 Revision 1.34 2003/02/21 01:54:08 cheshire
363 Bug #: 3099194 mDNSResponder needs performance improvements
364 Switched to using new "mDNS_Execute" model (see "Implementer Notes.txt")
365
366 Revision 1.33 2003/02/20 06:48:32 cheshire
367 Bug #: 3169535 Xserve RAID needs to do interface-specific registrations
368 Reviewed by: Josh Graessley, Bob Bradley
369
370 Revision 1.32 2003/01/31 03:35:59 cheshire
371 Bug #: 3147097 mDNSResponder sometimes fails to find the correct results
372 When there were *two* active questions in the list, they were incorrectly
373 finding *each other* and *both* being marked as duplicates of another question
374
375 Revision 1.31 2003/01/29 02:46:37 cheshire
376 Fix for IPv6:
377 A physical interface is identified solely by its InterfaceID (not by IP and type).
378 On a given InterfaceID, mDNSCore may send both v4 and v6 multicasts.
379 In cases where the requested outbound protocol (v4 or v6) is not supported on
380 that InterfaceID, the platform support layer should simply discard that packet.
381
382 Revision 1.30 2003/01/29 01:47:08 cheshire
383 Rename 'Active' to 'CRActive' or 'InterfaceActive' for improved clarity
384
385 Revision 1.29 2003/01/28 05:23:43 cheshire
386 Bug #: 3147097 mDNSResponder sometimes fails to find the correct results
387 Add 'Active' flag for interfaces
388
389 Revision 1.28 2003/01/28 01:35:56 cheshire
390 Revise comment about ThisQInterval to reflect new semantics
391
392 Revision 1.27 2003/01/13 23:49:42 jgraessl
393 Merged changes for the following fixes in to top of tree:
394 3086540 computer name changes not handled properly
395 3124348 service name changes are not properly handled
396 3124352 announcements sent in pairs, failing chattiness test
397
398 Revision 1.26 2002/12/23 22:13:28 jgraessl
399
400 Reviewed by: Stuart Cheshire
401 Initial IPv6 support for mDNSResponder.
402
403 Revision 1.25 2002/09/21 20:44:49 zarzycki
404 Added APSL info
405
406 Revision 1.24 2002/09/19 23:47:35 cheshire
407 Added mDNS_RegisterNoSuchService() function for assertion of non-existence
408 of a particular named service
409
410 Revision 1.23 2002/09/19 21:25:34 cheshire
411 mDNS_snprintf() doesn't need to be in a separate file
412
413 Revision 1.22 2002/09/19 04:20:43 cheshire
414 Remove high-ascii characters that confuse some systems
415
416 Revision 1.21 2002/09/17 01:06:35 cheshire
417 Change mDNS_AdvertiseLocalAddresses to be a parameter to mDNS_Init()
418
419 Revision 1.20 2002/09/16 18:41:41 cheshire
420 Merge in license terms from Quinn's copy, in preparation for Darwin release
421
422 */
423
424 #ifndef __mDNSClientAPI_h
425 #define __mDNSClientAPI_h
426
427 #include <stdarg.h> // stdarg.h is required for for va_list support for the mDNS_vsnprintf declaration
428 #include "mDNSDebug.h"
429
430 #ifdef __cplusplus
431 extern "C" {
432 #endif
433
434 // ***************************************************************************
435 // Function scope indicators
436
437 // If you see "mDNSlocal" before a function name in a C file, it means the function is not callable outside this file
438 #ifndef mDNSlocal
439 #define mDNSlocal static
440 #endif
441 // If you see "mDNSexport" before a symbol in a C file, it means the symbol is exported for use by clients
442 // For every "mDNSexport" in a C file, there needs to be a corresponding "extern" declaration in some header file
443 // (When a C file #includes a header file, the "extern" declarations tell the compiler:
444 // "This symbol exists -- but not necessarily in this C file.")
445 #ifndef mDNSexport
446 #define mDNSexport
447 #endif
448
449 // ***************************************************************************
450 // Structure packing macro
451
452 // If we're not using GNUC, it's not fatal.
453 // Most compilers naturally pack the on-the-wire structures correctly anyway, so a plain "struct" is usually fine.
454 // In the event that structures are not packed correctly, mDNS_Init() will detect this and report an error, so the
455 // developer will know what's wrong, and can investigate what needs to be done on that compiler to provide proper packing.
456 #ifndef packedstruct
457 #if ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9)))
458 #define packedstruct struct __attribute__((__packed__))
459 #define packedunion union __attribute__((__packed__))
460 #else
461 #define packedstruct struct
462 #define packedunion union
463 #endif
464 #endif
465
466 // ***************************************************************************
467 #if 0
468 #pragma mark - DNS Resource Record class and type constants
469 #endif
470
471 typedef enum // From RFC 1035
472 {
473 kDNSClass_IN = 1, // Internet
474 kDNSClass_CS = 2, // CSNET
475 kDNSClass_CH = 3, // CHAOS
476 kDNSClass_HS = 4, // Hesiod
477 kDNSClass_NONE = 254, // Used in DNS UPDATE [RFC 2136]
478
479 kDNSClass_Mask = 0x7FFF,// Multicast DNS uses the bottom 15 bits to identify the record class...
480 kDNSClass_UniqueRRSet = 0x8000,// ... and the top bit indicates that all other cached records are now invalid
481
482 kDNSQClass_ANY = 255, // Not a DNS class, but a DNS query class, meaning "all classes"
483 kDNSQClass_UnicastResponse = 0x8000 // Top bit set in a question means "unicast response acceptable"
484 } DNS_ClassValues;
485
486 typedef enum // From RFC 1035
487 {
488 kDNSType_A = 1, // 1 Address
489 kDNSType_NS, // 2 Name Server
490 kDNSType_MD, // 3 Mail Destination
491 kDNSType_MF, // 4 Mail Forwarder
492 kDNSType_CNAME, // 5 Canonical Name
493 kDNSType_SOA, // 6 Start of Authority
494 kDNSType_MB, // 7 Mailbox
495 kDNSType_MG, // 8 Mail Group
496 kDNSType_MR, // 9 Mail Rename
497 kDNSType_NULL, // 10 NULL RR
498 kDNSType_WKS, // 11 Well-known-service
499 kDNSType_PTR, // 12 Domain name pointer
500 kDNSType_HINFO, // 13 Host information
501 kDNSType_MINFO, // 14 Mailbox information
502 kDNSType_MX, // 15 Mail Exchanger
503 kDNSType_TXT, // 16 Arbitrary text string
504
505 kDNSType_AAAA = 28, // 28 IPv6 address
506 kDNSType_SRV = 33, // 33 Service record
507
508 kDNSQType_ANY = 255 // Not a DNS type, but a DNS query type, meaning "all types"
509 } DNS_TypeValues;
510
511 // ***************************************************************************
512 #if 0
513 #pragma mark - Simple types
514 #endif
515
516 // mDNS defines its own names for these common types to simplify portability across
517 // multiple platforms that may each have their own (different) names for these types.
518 typedef int mDNSBool;
519 typedef signed char mDNSs8;
520 typedef unsigned char mDNSu8;
521 typedef signed short mDNSs16;
522 typedef unsigned short mDNSu16;
523 #if _LP64
524 typedef signed int mDNSs32;
525 typedef unsigned int mDNSu32;
526 #else
527 typedef signed long mDNSs32;
528 typedef unsigned long mDNSu32;
529 #endif
530
531 // To enforce useful type checking, we make mDNSInterfaceID be a pointer to a dummy struct
532 // This way, mDNSInterfaceIDs can be assigned, and compared with each other, but not with other types
533 // Declaring the type to be the typical generic "void *" would lack this type checking
534 typedef struct mDNSInterfaceID_dummystruct { void *dummy; } *mDNSInterfaceID;
535
536 // These types are for opaque two- and four-byte identifiers.
537 // The "NotAnInteger" fields of the unions allow the value to be conveniently passed around in a
538 // register for the sake of efficiency, and compared for equality or inequality, but don't forget --
539 // just because it is in a register doesn't mean it is an integer. Operations like greater than,
540 // less than, add, multiply, increment, decrement, etc., are undefined for opaque identifiers,
541 // and if you make the mistake of trying to do those using the NotAnInteger field, then you'll
542 // find you get code that doesn't work consistently on big-endian and little-endian machines.
543 typedef packedunion { mDNSu8 b[2]; mDNSu16 NotAnInteger; } mDNSOpaque16;
544 typedef packedunion { mDNSu8 b[4]; mDNSu32 NotAnInteger; } mDNSOpaque32;
545 typedef packedunion { mDNSu8 b[16]; mDNSu16 w[8]; mDNSu32 l[4]; } mDNSOpaque128;
546
547 typedef mDNSOpaque16 mDNSIPPort; // An IP port is a two-byte opaque identifier (not an integer)
548 typedef mDNSOpaque32 mDNSv4Addr; // An IP address is a four-byte opaque identifier (not an integer)
549 typedef mDNSOpaque128 mDNSv6Addr; // An IPv6 address is a 16-byte opaque identifier (not an integer)
550
551 enum
552 {
553 mDNSAddrType_None = 0,
554 mDNSAddrType_IPv4 = 4,
555 mDNSAddrType_IPv6 = 6,
556 mDNSAddrType_Unknown = ~0 // Special marker value used in known answer list recording
557 };
558
559 typedef struct
560 {
561 mDNSs32 type;
562 union { mDNSv6Addr v6; mDNSv4Addr v4; } ip;
563 } mDNSAddr;
564
565 enum { mDNSfalse = 0, mDNStrue = 1 };
566
567 #define mDNSNULL 0L
568
569 enum
570 {
571 mStatus_Waiting = 1,
572 mStatus_NoError = 0,
573
574 // mDNS return values are in the range FFFE FF00 (-65792) to FFFE FFFF (-65537)
575 // The top end of the range (FFFE FFFF) is used for error codes;
576 // the bottom end of the range (FFFE FF00) is used for non-error values;
577
578 // Error codes:
579 mStatus_UnknownErr = -65537, // 0xFFFE FFFF
580 mStatus_NoSuchNameErr = -65538,
581 mStatus_NoMemoryErr = -65539,
582 mStatus_BadParamErr = -65540,
583 mStatus_BadReferenceErr = -65541,
584 mStatus_BadStateErr = -65542,
585 mStatus_BadFlagsErr = -65543,
586 mStatus_UnsupportedErr = -65544,
587 mStatus_NotInitializedErr = -65545,
588 mStatus_NoCache = -65546,
589 mStatus_AlreadyRegistered = -65547,
590 mStatus_NameConflict = -65548,
591 mStatus_Invalid = -65549,
592 // = -65550,
593 mStatus_Incompatible = -65551,
594 mStatus_BadInterfaceErr = -65552,
595
596 // -65553 - -65789 currently unused
597
598 // Non-error values:
599 mStatus_GrowCache = -65790,
600 mStatus_ConfigChanged = -65791,
601 mStatus_MemFree = -65792 // 0xFFFE FF00
602 };
603
604 typedef mDNSs32 mStatus;
605
606 // RFC 1034/1035 specify that a domain label consists of a length byte plus up to 63 characters
607 #define MAX_DOMAIN_LABEL 63
608 typedef struct { mDNSu8 c[ 64]; } domainlabel; // One label: length byte and up to 63 characters
609
610 // RFC 1034/1035 specify that a domain name, including length bytes, data bytes, and terminating zero, may be up to 255 bytes long
611 #define MAX_DOMAIN_NAME 255
612 typedef struct { mDNSu8 c[256]; } domainname; // Up to 255 bytes of length-prefixed domainlabels
613
614 typedef struct { mDNSu8 c[256]; } UTF8str255; // Null-terminated C string
615
616 // The longest legal textual form of a DNS name is 1005 bytes, including the C-string terminating NULL at the end.
617 // Explanation:
618 // When a native domainname object is converted to printable textual form using ConvertDomainNameToCString(),
619 // non-printing characters are represented in the conventional DNS way, as '\ddd', where ddd is a three-digit decimal number.
620 // The longest legal domain name is 255 bytes, in the form of four labels as shown below:
621 // Length byte, 63 data bytes, length byte, 63 data bytes, length byte, 63 data bytes, length byte, 61 data bytes, zero byte.
622 // Each label is encoded textually as characters followed by a trailing dot.
623 // If every character has to be represented as a four-byte escape sequence, then this makes the maximum textual form four labels
624 // plus the C-string terminating NULL as shown below:
625 // 63*4+1 + 63*4+1 + 63*4+1 + 61*4+1 + 1 = 1005.
626 // Note that MAX_ESCAPED_DOMAIN_LABEL is not normally used: If you're only decoding a single label, escaping is usually not required.
627 // It is for domain names, where dots are used as label separators, that proper escaping is vital.
628 #define MAX_ESCAPED_DOMAIN_LABEL 254
629 #define MAX_ESCAPED_DOMAIN_NAME 1005
630
631 // ***************************************************************************
632 #if 0
633 #pragma mark - Resource Record structures
634 #endif
635
636 // Authoritative Resource Records:
637 // There are four basic types: Shared, Advisory, Unique, Known Unique
638
639 // * Shared Resource Records do not have to be unique
640 // -- Shared Resource Records are used for DNS-SD service PTRs
641 // -- It is okay for several hosts to have RRs with the same name but different RDATA
642 // -- We use a random delay on responses to reduce collisions when all the hosts respond to the same query
643 // -- These RRs typically have moderately high TTLs (e.g. one hour)
644 // -- These records are announced on startup and topology changes for the benefit of passive listeners
645 // -- These records send a goodbye packet when deregistering
646 //
647 // * Advisory Resource Records are like Shared Resource Records, except they don't send a goodbye packet
648 //
649 // * Unique Resource Records should be unique among hosts within any given mDNS scope
650 // -- The majority of Resource Records are of this type
651 // -- If two entities on the network have RRs with the same name but different RDATA, this is a conflict
652 // -- Responses may be sent immediately, because only one host should be responding to any particular query
653 // -- These RRs typically have low TTLs (e.g. ten seconds)
654 // -- On startup and after topology changes, a host issues queries to verify uniqueness
655
656 // * Known Unique Resource Records are treated like Unique Resource Records, except that mDNS does
657 // not have to verify their uniqueness because this is already known by other means (e.g. the RR name
658 // is derived from the host's IP or Ethernet address, which is already known to be a unique identifier).
659
660 // Summary of properties of different record types:
661 // Probe? Does this record type send probes before announcing?
662 // Conflict? Does this record type react if we observe an apparent conflict?
663 // Goodbye? Does this record type send a goodbye packet on departure?
664 //
665 // Probe? Conflict? Goodbye? Notes
666 // Unregistered Should not appear in any list (sanity check value)
667 // Shared No No Yes e.g. Service PTR record
668 // Deregistering No No Yes Shared record about to announce its departure and leave the list
669 // Advisory No No No
670 // Unique Yes Yes No Record intended to be unique -- will probe to verify
671 // Verified Yes Yes No Record has completed probing, and is verified unique
672 // KnownUnique No Yes No Record is assumed by other means to be unique
673
674 // Valid lifecycle of a record:
675 // Unregistered -> Shared -> Deregistering -(goodbye)-> Unregistered
676 // Unregistered -> Advisory -> Unregistered
677 // Unregistered -> Unique -(probe)-> Verified -> Unregistered
678 // Unregistered -> KnownUnique -> Unregistered
679
680 // Each Authoritative kDNSRecordType has only one bit set. This makes it easy to quickly see if a record
681 // is one of a particular set of types simply by performing the appropriate bitwise masking operation.
682
683 // Cache Resource Records (received from the network):
684 // There are four basic types: Answer, Unique Answer, Additional, Unique Additional
685 // Bit 7 (the top bit) of kDNSRecordType is always set for Cache Resource Records; always clear for Authoritative Resource Records
686 // Bit 6 (value 0x40) is set for answer records; clear for additional records
687 // Bit 5 (value 0x20) is set for records received with the kDNSClass_UniqueRRSet
688
689 enum
690 {
691 kDNSRecordTypeUnregistered = 0x00, // Not currently in any list
692 kDNSRecordTypeDeregistering = 0x01, // Shared record about to announce its departure and leave the list
693
694 kDNSRecordTypeUnique = 0x02, // Will become a kDNSRecordTypeVerified when probing is complete
695
696 kDNSRecordTypeAdvisory = 0x04, // Like Shared, but no goodbye packet
697 kDNSRecordTypeShared = 0x08, // Shared means record name does not have to be unique -- use random delay on responses
698 kDNSRecordTypeVerified = 0x10, // Unique means mDNS should check that name is unique (and then send immediate responses)
699 kDNSRecordTypeKnownUnique = 0x20, // Known Unique means mDNS can assume name is unique without checking
700
701 kDNSRecordTypeUniqueMask = (kDNSRecordTypeUnique | kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique),
702 kDNSRecordTypeActiveMask = (kDNSRecordTypeAdvisory | kDNSRecordTypeShared | kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique),
703
704 kDNSRecordTypePacketAdd = 0x80, // Received in the Additional Section of a DNS Response
705 kDNSRecordTypePacketAddUnique = 0xA0, // Received in the Additional Section of a DNS Response with kDNSClass_UniqueRRSet set
706 kDNSRecordTypePacketAns = 0xC0, // Received in the Answer Section of a DNS Response
707 kDNSRecordTypePacketAnsUnique = 0xE0, // Received in the Answer Section of a DNS Response with kDNSClass_UniqueRRSet set
708
709 kDNSRecordTypePacketAnsMask = 0x40, // True for PacketAns and PacketAnsUnique
710 kDNSRecordTypePacketUniqueMask = 0x20 // True for PacketAddUnique and PacketAnsUnique
711 };
712
713 typedef packedstruct { mDNSu16 priority; mDNSu16 weight; mDNSIPPort port; domainname target; } rdataSRV;
714 typedef packedstruct { mDNSu16 preference; domainname exchange; } rdataMX;
715
716 // StandardAuthRDSize is 264 (256+8), which is large enough to hold a maximum-sized SRV record
717 // MaximumRDSize is 8K the absolute maximum we support (at least for now)
718 #define StandardAuthRDSize 264
719 #define MaximumRDSize 8192
720
721 // InlineCacheRDSize is 64
722 // Records received from the network with rdata this size or less have their rdata stored right in the CacheRecord object
723 // Records received from the network with rdata larger than this have additional storage allocated for the rdata
724 // A quick unscientific sample from a busy network at Apple with lots of machines revealed this:
725 // 1461 records in cache
726 // 292 were one-byte TXT records
727 // 136 were four-byte A records
728 // 184 were sixteen-byte AAAA records
729 // 780 were various PTR, TXT and SRV records from 12-64 bytes
730 // Only 69 records had rdata bigger than 64 bytes
731 #define InlineCacheRDSize 64
732
733 typedef union
734 {
735 mDNSu8 data[StandardAuthRDSize];
736 mDNSv4Addr ip; // For 'A' record
737 mDNSv6Addr ipv6; // For 'AAAA' record
738 domainname name; // For PTR and CNAME records
739 UTF8str255 txt; // For TXT record
740 rdataSRV srv; // For SRV record
741 rdataMX mx; // For MX record
742 } RDataBody;
743
744 typedef struct
745 {
746 mDNSu16 MaxRDLength; // Amount of storage allocated for rdata (usually sizeof(RDataBody))
747 RDataBody u;
748 } RData;
749 #define sizeofRDataHeader (sizeof(RData) - sizeof(RDataBody))
750
751 typedef struct AuthRecord_struct AuthRecord;
752 typedef struct CacheRecord_struct CacheRecord;
753 typedef struct ResourceRecord_struct ResourceRecord;
754 typedef struct DNSQuestion_struct DNSQuestion;
755 typedef struct mDNS_struct mDNS;
756 typedef struct mDNS_PlatformSupport_struct mDNS_PlatformSupport;
757
758 // Note: Within an mDNSRecordCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Close(), mDNS_Execute()
759 typedef void mDNSRecordCallback(mDNS *const m, AuthRecord *const rr, mStatus result);
760
761 // Note:
762 // Restrictions: An mDNSRecordUpdateCallback may not make any mDNS API calls.
763 // The intent of this callback is to allow the client to free memory, if necessary.
764 // The internal data structures of the mDNS code may not be in a state where mDNS API calls may be made safely.
765 typedef void mDNSRecordUpdateCallback(mDNS *const m, AuthRecord *const rr, RData *OldRData);
766
767 struct ResourceRecord_struct
768 {
769 mDNSu8 RecordType; // See enum above
770 mDNSInterfaceID InterfaceID; // Set if this RR is specific to one interface
771 // For records received off the wire, InterfaceID is *always* set to the receiving interface
772 // For our authoritative records, InterfaceID is usually zero, except for those few records
773 // that are interface-specific (e.g. address records, especially linklocal addresses)
774 domainname name;
775 mDNSu16 rrtype;
776 mDNSu16 rrclass;
777 mDNSu32 rroriginalttl; // In seconds
778 mDNSu16 rdlength; // Size of the raw rdata, in bytes
779 mDNSu16 rdestimate; // Upper bound on size of rdata after name compression
780 mDNSu32 namehash; // Name-based (i.e. case insensitive) hash of name
781 mDNSu32 rdatahash; // 32-bit hash of the raw rdata
782 mDNSu32 rdnamehash; // Set if this rdata contains a domain name (e.g. PTR, SRV, CNAME etc.)
783 RData *rdata; // Pointer to storage for this rdata
784 };
785
786 struct AuthRecord_struct
787 {
788 // For examples of how to set up this structure for use in mDNS_Register(),
789 // see mDNS_AdvertiseInterface() or mDNS_RegisterService().
790 // Basically, resrec and persistent metadata need to be set up before calling mDNS_Register().
791 // mDNS_SetupResourceRecord() is avaliable as a helper routine to set up most fields to sensible default values for you
792
793 AuthRecord *next; // Next in list; first element of structure for efficiency reasons
794 ResourceRecord resrec;
795
796 // Persistent metadata for Authoritative Records
797 AuthRecord *Additional1; // Recommended additional record to include in response
798 AuthRecord *Additional2; // Another additional
799 AuthRecord *DependentOn; // This record depends on another for its uniqueness checking
800 AuthRecord *RRSet; // This unique record is part of an RRSet
801 mDNSRecordCallback *RecordCallback; // Callback function to call for state changes
802 void *RecordContext; // Context parameter for the callback function
803 mDNSu8 HostTarget; // Set if the target of this record (PTR, CNAME, SRV, etc.) is our host name
804
805 // Transient state for Authoritative Records
806 mDNSu8 Acknowledged; // Set if we've given the success callback to the client
807 mDNSu8 ProbeCount; // Number of probes remaining before this record is valid (kDNSRecordTypeUnique)
808 mDNSu8 AnnounceCount; // Number of announcements remaining (kDNSRecordTypeShared)
809 mDNSu8 IncludeInProbe; // Set if this RR is being put into a probe right now
810 mDNSInterfaceID ImmedAnswer; // Someone on this interface issued a query we need to answer (all-ones for all interfaces)
811 mDNSInterfaceID ImmedAdditional; // Hint that we might want to also send this record, just to be helpful
812 mDNSInterfaceID SendRNow; // The interface this query is being sent on right now
813 mDNSv4Addr v4Requester; // Recent v4 query for this record, or all-ones if more than one recent query
814 mDNSv6Addr v6Requester; // Recent v6 query for this record, or all-ones if more than one recent query
815 AuthRecord *NextResponse; // Link to the next element in the chain of responses to generate
816 const mDNSu8 *NR_AnswerTo; // Set if this record was selected by virtue of being a direct answer to a question
817 AuthRecord *NR_AdditionalTo; // Set if this record was selected by virtue of being additional to another
818 mDNSs32 ThisAPInterval; // In platform time units: Current interval for announce/probe
819 mDNSs32 AnnounceUntil; // In platform time units: Creation time + TTL
820 mDNSs32 LastAPTime; // In platform time units: Last time we sent announcement/probe
821 mDNSs32 LastMCTime; // Last time we multicast this record (used to guard against packet-storm attacks)
822 mDNSInterfaceID LastMCInterface; // Interface this record was multicast on at the time LastMCTime was recorded
823 RData *NewRData; // Set if we are updating this record with new rdata
824 mDNSu16 newrdlength; // ... and the length of the new RData
825 mDNSRecordUpdateCallback *UpdateCallback;
826 mDNSu32 UpdateCredits; // Token-bucket rate limiting of excessive updates
827 mDNSs32 NextUpdateCredit; // Time next token is added to bucket
828 mDNSs32 UpdateBlocked; // Set if update delaying is in effect
829
830 RData rdatastorage; // Normally the storage is right here, except for oversized records
831 // rdatastorage MUST be the last thing in the structure -- when using oversized AuthRecords, extra bytes
832 // are appended after the end of the AuthRecord, logically augmenting the size of the rdatastorage
833 // DO NOT ADD ANY MORE FIELDS HERE
834 };
835
836 struct CacheRecord_struct
837 {
838 CacheRecord *next; // Next in list; first element of structure for efficiency reasons
839 ResourceRecord resrec;
840
841 // Transient state for Cache Records
842 CacheRecord *NextInKAList; // Link to the next element in the chain of known answers to send
843 mDNSs32 TimeRcvd; // In platform time units
844 mDNSs32 NextRequiredQuery; // In platform time units
845 mDNSs32 LastUsed; // In platform time units
846 mDNSu32 UseCount; // Number of times this RR has been used to answer a question
847 DNSQuestion *CRActiveQuestion; // Points to an active question referencing this answer
848 mDNSu32 UnansweredQueries; // Number of times we've issued a query for this record without getting an answer
849 mDNSs32 LastUnansweredTime; // In platform time units; last time we incremented UnansweredQueries
850 mDNSu32 MPUnansweredQ; // Multi-packet query handling: Number of times we've seen a query for this record
851 mDNSs32 MPLastUnansweredQT; // Multi-packet query handling: Last time we incremented MPUnansweredQ
852 mDNSu32 MPUnansweredKA; // Multi-packet query handling: Number of times we've seen this record in a KA list
853 mDNSBool MPExpectingKA; // Multi-packet query handling: Set when we increment MPUnansweredQ; allows one KA
854 CacheRecord *NextInCFList; // Set if this is in the list of records we just received with the cache flush bit set
855
856 struct { mDNSu16 MaxRDLength; mDNSu8 data[InlineCacheRDSize]; } rdatastorage; // Storage for small records is right here
857 };
858
859 typedef struct
860 {
861 CacheRecord r;
862 mDNSu8 _extradata[MaximumRDSize-InlineCacheRDSize]; // Glue on the necessary number of extra bytes
863 } LargeCacheRecord;
864
865 typedef struct NetworkInterfaceInfo_struct NetworkInterfaceInfo;
866
867 struct NetworkInterfaceInfo_struct
868 {
869 // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
870 NetworkInterfaceInfo *next;
871
872 mDNSBool InterfaceActive; // InterfaceActive is set if interface is sending & receiving packets
873 // InterfaceActive is clear if interface is here to represent an address with A
874 // and/or AAAA records, but there is already an earlier representative for this
875 // physical interface which will be used for the actual sending & receiving
876 // packets (this status may change as interfaces are added and removed)
877 mDNSBool IPv4Available; // If InterfaceActive, set if v4 available on this InterfaceID
878 mDNSBool IPv6Available; // If InterfaceActive, set if v6 available on this InterfaceID
879
880 // Standard AuthRecords that every Responder host should have (one per active IP address)
881 AuthRecord RR_A; // 'A' or 'AAAA' (address) record for our ".local" name
882 AuthRecord RR_PTR; // PTR (reverse lookup) record
883 AuthRecord RR_HINFO;
884
885 // Client API fields: The client must set up these fields *before* calling mDNS_RegisterInterface()
886 mDNSInterfaceID InterfaceID;
887 mDNSAddr ip;
888 mDNSBool Advertise; // Set Advertise to false if you are only searching on this interface
889 mDNSBool TxAndRx; // Set to false if not sending and receiving packets on this interface
890 };
891
892 typedef struct ExtraResourceRecord_struct ExtraResourceRecord;
893 struct ExtraResourceRecord_struct
894 {
895 ExtraResourceRecord *next;
896 AuthRecord r;
897 // Note: Add any additional fields *before* the AuthRecord in this structure, not at the end.
898 // In some cases clients can allocate larger chunks of memory and set r->rdata->MaxRDLength to indicate
899 // that this extra memory is available, which would result in any fields after the AuthRecord getting smashed
900 };
901
902 // Note: Within an mDNSServiceCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Close(), mDNS_Execute()
903 typedef struct ServiceRecordSet_struct ServiceRecordSet;
904 typedef void mDNSServiceCallback(mDNS *const m, ServiceRecordSet *const sr, mStatus result);
905 struct ServiceRecordSet_struct
906 {
907 // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
908 // No fields need to be set up by the client prior to calling mDNS_RegisterService();
909 // all required data is passed as parameters to that function.
910 mDNSServiceCallback *ServiceCallback;
911 void *ServiceContext;
912 ExtraResourceRecord *Extras; // Optional list of extra AuthRecords attached to this service registration
913 mDNSu32 NumSubTypes;
914 AuthRecord *SubTypes;
915 mDNSBool Conflict; // Set if this record set was forcibly deregistered because of a conflict
916 domainname Host; // Set if this service record does not use the standard target host name
917 AuthRecord RR_ADV; // e.g. _services._dns-sd._udp.local. PTR _printer._tcp.local.
918 AuthRecord RR_PTR; // e.g. _printer._tcp.local. PTR Name._printer._tcp.local.
919 AuthRecord RR_SRV; // e.g. Name._printer._tcp.local. SRV 0 0 port target
920 AuthRecord RR_TXT; // e.g. Name._printer._tcp.local. TXT PrintQueueName
921 // Don't add any fields after AuthRecord RR_TXT.
922 // This is where the implicit extra space goes if we allocate a ServiceRecordSet containing an oversized RR_TXT record
923 };
924
925 // ***************************************************************************
926 #if 0
927 #pragma mark - Question structures
928 #endif
929
930 // We record the last eight instances of each duplicate query
931 // This gives us v4/v6 on each of Ethernet/AirPort and Firewire, and two free slots "for future expansion"
932 // If the host has more active interfaces that this it is not fatal -- duplicate question suppression will degrade gracefully.
933 // Since we will still remember the last eight, the busiest interfaces will still get the effective duplicate question suppression.
934 #define DupSuppressInfoSize 8
935
936 typedef struct
937 {
938 mDNSs32 Time;
939 mDNSInterfaceID InterfaceID;
940 mDNSs32 Type; // v4 or v6?
941 } DupSuppressInfo;
942
943 // Note: Within an mDNSQuestionCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Close(), mDNS_Execute()
944 typedef void mDNSQuestionCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord);
945 struct DNSQuestion_struct
946 {
947 // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
948 DNSQuestion *next;
949 mDNSu32 qnamehash;
950 mDNSs32 LastQTime; // Last scheduled transmission of this Q on *all* applicable interfaces
951 mDNSs32 ThisQInterval; // LastQTime + ThisQInterval is the next scheduled transmission of this Q
952 // ThisQInterval > 0 for an active question;
953 // ThisQInterval = 0 for a suspended question that's still in the list
954 // ThisQInterval = -1 for a cancelled question that's been removed from the list
955 mDNSu32 RecentAnswers; // Number of answers since the last time we sent this query
956 mDNSu32 CurrentAnswers; // Number of records currently in the cache that answer this question
957 mDNSu32 LargeAnswers; // Number of answers with rdata > 1024 bytes
958 mDNSu32 UniqueAnswers; // Number of answers received with kDNSClass_UniqueRRSet bit set
959 DNSQuestion *DuplicateOf;
960 DNSQuestion *NextInDQList;
961 DupSuppressInfo DupSuppress[DupSuppressInfoSize];
962 mDNSInterfaceID SendQNow; // The interface this query is being sent on right now
963 mDNSBool SendOnAll; // Set if we're sending this question on all active interfaces
964 mDNSs32 LastQTxTime; // Last time this Q was sent on one (but not necessarily all) interfaces
965
966 // Client API fields: The client must set up these fields *before* calling mDNS_StartQuery()
967 mDNSInterfaceID InterfaceID; // Non-zero if you want to issue link-local queries only on a single specific IP interface
968 domainname qname;
969 mDNSu16 qtype;
970 mDNSu16 qclass;
971 mDNSQuestionCallback *QuestionCallback;
972 void *QuestionContext;
973 };
974
975 typedef struct
976 {
977 // Client API fields: The client must set up name and InterfaceID *before* calling mDNS_StartResolveService()
978 // When the callback is invoked, ip, port, TXTlen and TXTinfo will have been filled in with the results learned from the network.
979 domainname name;
980 mDNSInterfaceID InterfaceID; // ID of the interface the response was received on
981 mDNSAddr ip; // Remote (destination) IP address where this service can be accessed
982 mDNSIPPort port; // Port where this service can be accessed
983 mDNSu16 TXTlen;
984 mDNSu8 TXTinfo[2048]; // Additional demultiplexing information (e.g. LPR queue name)
985 } ServiceInfo;
986
987 // Note: Within an mDNSServiceInfoQueryCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Close(), mDNS_Execute()
988 typedef struct ServiceInfoQuery_struct ServiceInfoQuery;
989 typedef void mDNSServiceInfoQueryCallback(mDNS *const m, ServiceInfoQuery *query);
990 struct ServiceInfoQuery_struct
991 {
992 // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
993 // No fields need to be set up by the client prior to calling mDNS_StartResolveService();
994 // all required data is passed as parameters to that function.
995 // The ServiceInfoQuery structure memory is working storage for mDNSCore to discover the requested information
996 // and place it in the ServiceInfo structure. After the client has called mDNS_StopResolveService(), it may
997 // dispose of the ServiceInfoQuery structure while retaining the results in the ServiceInfo structure.
998 DNSQuestion qSRV;
999 DNSQuestion qTXT;
1000 DNSQuestion qAv4;
1001 DNSQuestion qAv6;
1002 mDNSu8 GotSRV;
1003 mDNSu8 GotTXT;
1004 mDNSu8 GotADD;
1005 mDNSu32 Answers;
1006 ServiceInfo *info;
1007 mDNSServiceInfoQueryCallback *ServiceInfoQueryCallback;
1008 void *ServiceInfoQueryContext;
1009 };
1010
1011 // ***************************************************************************
1012 #if 0
1013 #pragma mark - Main mDNS object, used to hold all the mDNS state
1014 #endif
1015
1016 typedef void mDNSCallback(mDNS *const m, mStatus result);
1017
1018 #define CACHE_HASH_SLOTS 499
1019
1020 enum
1021 {
1022 mDNS_KnownBug_PhantomInterfaces = 1
1023 };
1024
1025 struct mDNS_struct
1026 {
1027 // Internal state fields. These hold the main internal state of mDNSCore;
1028 // the client layer needn't be concerned with them.
1029 // No fields need to be set up by the client prior to calling mDNS_Init();
1030 // all required data is passed as parameters to that function.
1031
1032 mDNS_PlatformSupport *p; // Pointer to platform-specific data of indeterminite size
1033 mDNSu32 KnownBugs;
1034 mDNSBool AdvertiseLocalAddresses;
1035 mStatus mDNSPlatformStatus;
1036 mDNSCallback *MainCallback;
1037 void *MainContext;
1038
1039 // For debugging: To catch and report locking failures
1040 mDNSu32 mDNS_busy; // Incremented between mDNS_Lock/mDNS_Unlock section
1041 mDNSu32 mDNS_reentrancy; // Incremented when calling a client callback
1042 mDNSu8 mDNS_shutdown; // Set when we're shutting down, allows us to skip some unnecessary steps
1043 mDNSu8 lock_rrcache; // For debugging: Set at times when these lists may not be modified
1044 mDNSu8 lock_Questions;
1045 mDNSu8 lock_Records;
1046 char MsgBuffer[80]; // Temp storage used while building error log messages
1047
1048 // Task Scheduling variables
1049 mDNSs32 timenow; // The time that this particular activation of the mDNS code started
1050 mDNSs32 timenow_last; // The time the last time we ran
1051 mDNSs32 timenow_adjust; // Correction applied if we ever discover time went backwards
1052 mDNSs32 NextScheduledEvent; // Derived from values below
1053 mDNSs32 SuppressSending; // Don't send *any* packets during this time
1054 mDNSs32 NextCacheCheck; // Next time to refresh cache record before it expires
1055 mDNSs32 NextScheduledQuery; // Next time to send query in its exponential backoff sequence
1056 mDNSs32 NextScheduledProbe; // Next time to probe for new authoritative record
1057 mDNSs32 NextScheduledResponse; // Next time to send authoritative record(s) in responses
1058 mDNSs32 ExpectUnicastResponse; // Set when we send a query with the kDNSQClass_UnicastResponse bit set
1059 mDNSs32 RandomQueryDelay; // For de-synchronization of query packets on the wire
1060 mDNSBool SendDeregistrations; // Set if we need to send deregistrations (immediately)
1061 mDNSBool SendImmediateAnswers; // Set if we need to send answers (immediately -- or as soon as SuppressSending clears)
1062 mDNSBool SleepState; // Set if we're sleeping (send no more packets)
1063
1064 // These fields only required for mDNS Searcher...
1065 DNSQuestion *Questions; // List of all registered questions, active and inactive
1066 DNSQuestion *NewQuestions; // Fresh questions not yet answered from cache
1067 DNSQuestion *CurrentQuestion; // Next question about to be examined in AnswerLocalQuestions()
1068 DNSQuestion *LocalOnlyQuestions; // Questions with InterfaceID set to ~0 ("local only")
1069 DNSQuestion *NewLocalOnlyQuestions; // Fresh local-only questions not yet answered
1070 mDNSu32 rrcache_size; // Total number of available cache entries
1071 mDNSu32 rrcache_totalused; // Number of cache entries currently occupied
1072 mDNSu32 rrcache_active; // Number of cache entries currently occupied by records that answer active questions
1073 mDNSu32 rrcache_report;
1074 CacheRecord *rrcache_free;
1075 CacheRecord *rrcache_hash[CACHE_HASH_SLOTS];
1076 CacheRecord **rrcache_tail[CACHE_HASH_SLOTS];
1077 mDNSu32 rrcache_used[CACHE_HASH_SLOTS];
1078
1079 // Fields below only required for mDNS Responder...
1080 domainlabel nicelabel; // Rich text label encoded using canonically precomposed UTF-8
1081 domainlabel hostlabel; // Conforms to RFC 1034 "letter-digit-hyphen" ARPANET host name rules
1082 domainname hostname; // Host Name, e.g. "Foo.local."
1083 UTF8str255 HIHardware;
1084 UTF8str255 HISoftware;
1085 AuthRecord *ResourceRecords;
1086 AuthRecord *DuplicateRecords; // Records currently 'on hold' because they are duplicates of existing records
1087 AuthRecord *LocalOnlyRecords; // Local records registered with InterfaceID set to ~0 ("local only")
1088 AuthRecord *NewLocalOnlyRecords; // Fresh local-only records not yet delivered to local-only questions
1089 mDNSBool DiscardLocalOnlyRecords;// Set when we have "remove" events we need to deliver to local-only questions
1090 AuthRecord *CurrentRecord; // Next AuthRecord about to be examined
1091 NetworkInterfaceInfo *HostInterfaces;
1092 mDNSs32 ProbeFailTime;
1093 mDNSs32 NumFailedProbes;
1094 mDNSs32 SuppressProbes;
1095 };
1096
1097 // ***************************************************************************
1098 #if 0
1099 #pragma mark - Useful Static Constants
1100 #endif
1101
1102 extern const mDNSIPPort zeroIPPort;
1103 extern const mDNSv4Addr zeroIPAddr;
1104 extern const mDNSv6Addr zerov6Addr;
1105 extern const mDNSv4Addr onesIPv4Addr;
1106 extern const mDNSv6Addr onesIPv6Addr;
1107 extern const mDNSInterfaceID mDNSInterface_Any;
1108
1109 extern const mDNSIPPort UnicastDNSPort;
1110 extern const mDNSIPPort MulticastDNSPort;
1111 extern const mDNSv4Addr AllDNSAdminGroup;
1112 extern const mDNSv4Addr AllDNSLinkGroup;
1113 extern const mDNSv6Addr AllDNSLinkGroupv6;
1114 extern const mDNSAddr AllDNSLinkGroup_v4;
1115 extern const mDNSAddr AllDNSLinkGroup_v6;
1116
1117 // ***************************************************************************
1118 #if 0
1119 #pragma mark - Main Client Functions
1120 #endif
1121
1122 // Every client should call mDNS_Init, passing in storage for the mDNS object, mDNS_PlatformSupport object, and rrcache.
1123 // The rrcachesize parameter is the size of (i.e. number of entries in) the rrcache array passed in.
1124 // Most clients use mDNS_Init_AdvertiseLocalAddresses. This causes mDNSCore to automatically
1125 // create the correct address records for all the hosts interfaces. If you plan to advertise
1126 // services being offered by the local machine, this is almost always what you want.
1127 // There are two cases where you might use mDNS_Init_DontAdvertiseLocalAddresses:
1128 // 1. A client-only device, that browses for services but doesn't advertise any of its own.
1129 // 2. A proxy-registration service, that advertises services being offered by other machines, and takes
1130 // the appropriate steps to manually create the correct address records for those other machines.
1131 // In principle, a proxy-like registration service could manually create address records for its own machine too,
1132 // but this would be pointless extra effort when using mDNS_Init_AdvertiseLocalAddresses does that for you.
1133 //
1134 // When mDNS has finished setting up the client's callback is called
1135 // A client can also spin and poll the mDNSPlatformStatus field to see when it changes from mStatus_Waiting to mStatus_NoError
1136 //
1137 // Call mDNS_Close to tidy up before exiting
1138 //
1139 // Call mDNS_Register with a completed AuthRecord object to register a resource record
1140 // If the resource record type is kDNSRecordTypeUnique (or kDNSknownunique) then if a conflicting resource record is discovered,
1141 // the resource record's mDNSRecordCallback will be called with error code mStatus_NameConflict. The callback should deregister
1142 // the record, and may then try registering the record again after picking a new name (e.g. by automatically appending a number).
1143 //
1144 // Call mDNS_StartQuery to initiate a query. mDNS will proceed to issue Multicast DNS query packets, and any time a response
1145 // is received containing a record which matches the question, the DNSQuestion's mDNSAnswerCallback function will be called
1146 // Call mDNS_StopQuery when no more answers are required
1147 //
1148 // Care should be taken on multi-threaded or interrupt-driven environments.
1149 // The main mDNS routines call mDNSPlatformLock() on entry and mDNSPlatformUnlock() on exit;
1150 // each platform layer needs to implement these appropriately for its respective platform.
1151 // For example, if the support code on a particular platform implements timer callbacks at interrupt time, then
1152 // mDNSPlatformLock/Unlock need to disable interrupts or do similar concurrency control to ensure that the mDNS
1153 // code is not entered by an interrupt-time timer callback while in the middle of processing a client call.
1154
1155 extern mStatus mDNS_Init (mDNS *const m, mDNS_PlatformSupport *const p,
1156 CacheRecord *rrcachestorage, mDNSu32 rrcachesize,
1157 mDNSBool AdvertiseLocalAddresses,
1158 mDNSCallback *Callback, void *Context);
1159 // See notes above on use of NoCache/ZeroCacheSize
1160 #define mDNS_Init_NoCache mDNSNULL
1161 #define mDNS_Init_ZeroCacheSize 0
1162 // See notes above on use of Advertise/DontAdvertiseLocalAddresses
1163 #define mDNS_Init_AdvertiseLocalAddresses mDNStrue
1164 #define mDNS_Init_DontAdvertiseLocalAddresses mDNSfalse
1165 #define mDNS_Init_NoInitCallback mDNSNULL
1166 #define mDNS_Init_NoInitCallbackContext mDNSNULL
1167
1168 extern void mDNS_GrowCache (mDNS *const m, CacheRecord *storage, mDNSu32 numrecords);
1169 extern void mDNS_Close (mDNS *const m);
1170 extern mDNSs32 mDNS_Execute (mDNS *const m);
1171
1172 extern mStatus mDNS_Register (mDNS *const m, AuthRecord *const rr);
1173 extern mStatus mDNS_Update (mDNS *const m, AuthRecord *const rr, mDNSu32 newttl,
1174 const mDNSu16 newrdlength,
1175 RData *const newrdata, mDNSRecordUpdateCallback *Callback);
1176 extern mStatus mDNS_Deregister(mDNS *const m, AuthRecord *const rr);
1177
1178 extern mStatus mDNS_StartQuery(mDNS *const m, DNSQuestion *const question);
1179 extern mStatus mDNS_StopQuery (mDNS *const m, DNSQuestion *const question);
1180 extern mStatus mDNS_Reconfirm (mDNS *const m, CacheRecord *const cacherr);
1181 extern mStatus mDNS_ReconfirmByValue(mDNS *const m, ResourceRecord *const rr);
1182
1183 // ***************************************************************************
1184 #if 0
1185 #pragma mark - Platform support functions that are accessible to the client layer too
1186 #endif
1187
1188 extern mDNSs32 mDNSPlatformOneSecond;
1189 extern mDNSs32 mDNSPlatformTimeNow(void);
1190
1191 // ***************************************************************************
1192 #if 0
1193 #pragma mark - General utility and helper functions
1194 #endif
1195
1196 // mDNS_RegisterService is a single call to register the set of resource records associated with a given named service.
1197 //
1198 // mDNS_StartResolveService is single call which is equivalent to multiple calls to mDNS_StartQuery,
1199 // to find the IP address, port number, and demultiplexing information for a given named service.
1200 // As with mDNS_StartQuery, it executes asynchronously, and calls the ServiceInfoQueryCallback when the answer is
1201 // found. After the service is resolved, the client should call mDNS_StopResolveService to complete the transaction.
1202 // The client can also call mDNS_StopResolveService at any time to abort the transaction.
1203 //
1204 // mDNS_GetBrowseDomains is a special case of the mDNS_StartQuery call, where the resulting answers
1205 // are a list of PTR records indicating (in the rdata) domains that are recommended for browsing.
1206 // After getting the list of domains to browse, call mDNS_StopQuery to end the search.
1207 // mDNS_GetDefaultBrowseDomain returns the name of the domain that should be highlighted by default.
1208 //
1209 // mDNS_GetRegistrationDomains and mDNS_GetDefaultRegistrationDomain are the equivalent calls to get the list
1210 // of one or more domains that should be offered to the user as choices for where they may register their service,
1211 // and the default domain in which to register in the case where the user has made no selection.
1212
1213 extern void mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mDNSInterfaceID InterfaceID,
1214 mDNSu16 rrtype, mDNSu32 ttl, mDNSu8 RecordType, mDNSRecordCallback Callback, void *Context);
1215
1216 extern mStatus mDNS_RegisterService (mDNS *const m, ServiceRecordSet *sr,
1217 const domainlabel *const name, const domainname *const type, const domainname *const domain,
1218 const domainname *const host, mDNSIPPort port, const mDNSu8 txtinfo[], mDNSu16 txtlen,
1219 AuthRecord *SubTypes, mDNSu32 NumSubTypes,
1220 const mDNSInterfaceID InterfaceID, mDNSServiceCallback Callback, void *Context);
1221 extern mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra, RData *rdata, mDNSu32 ttl);
1222 extern mStatus mDNS_RemoveRecordFromService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra);
1223 extern mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordSet *const sr, const domainlabel *newname);
1224 extern mStatus mDNS_DeregisterService(mDNS *const m, ServiceRecordSet *sr);
1225
1226 extern mStatus mDNS_RegisterNoSuchService(mDNS *const m, AuthRecord *const rr,
1227 const domainlabel *const name, const domainname *const type, const domainname *const domain,
1228 const domainname *const host,
1229 const mDNSInterfaceID InterfaceID, mDNSRecordCallback Callback, void *Context);
1230 #define mDNS_DeregisterNoSuchService mDNS_Deregister
1231
1232 extern mStatus mDNS_StartBrowse(mDNS *const m, DNSQuestion *const question,
1233 const domainname *const srv, const domainname *const domain,
1234 const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *Callback, void *Context);
1235 #define mDNS_StopBrowse mDNS_StopQuery
1236
1237 extern mStatus mDNS_StartResolveService(mDNS *const m, ServiceInfoQuery *query, ServiceInfo *info, mDNSServiceInfoQueryCallback *Callback, void *Context);
1238 extern void mDNS_StopResolveService (mDNS *const m, ServiceInfoQuery *query);
1239
1240 typedef enum
1241 {
1242 mDNS_DomainTypeBrowse = 0,
1243 mDNS_DomainTypeBrowseDefault = 1,
1244 mDNS_DomainTypeRegistration = 2,
1245 mDNS_DomainTypeRegistrationDefault = 3
1246 } mDNS_DomainType;
1247
1248 extern mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, mDNS_DomainType DomainType, const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *Callback, void *Context);
1249 // In the Panther mDNSResponder we don't do unicast queries yet, so there's no point trying to do domain enumeration
1250 // mDNS_GetDomains() and mDNS_StopGetDomains() are set to be no-ops so that clients don't try to do browse/register operations that will fail
1251 //#define mDNS_StopGetDomains mDNS_StopQuery
1252 #define mDNS_StopGetDomains(m,q) ((void)(m),(void)(q))
1253 extern mStatus mDNS_AdvertiseDomains(mDNS *const m, AuthRecord *rr, mDNS_DomainType DomainType, const mDNSInterfaceID InterfaceID, char *domname);
1254 #define mDNS_StopAdvertiseDomains mDNS_Deregister
1255
1256 // ***************************************************************************
1257 #if 0
1258 #pragma mark - DNS name utility functions
1259 #endif
1260
1261 // In order to expose the full capabilities of the DNS protocol (which allows any arbitrary eight-bit values
1262 // in domain name labels, including unlikely characters like ascii nulls and even dots) all the mDNS APIs
1263 // work with DNS's native length-prefixed strings. For convenience in C, the following utility functions
1264 // are provided for converting between C's null-terminated strings and DNS's length-prefixed strings.
1265
1266 // Assignment
1267 // A simple C structure assignment of a domainname can cause a protection fault by accessing unmapped memory,
1268 // because that object is defined to be 256 bytes long, but not all domainname objects are truly the full size.
1269 // This macro uses mDNSPlatformMemCopy() to make sure it only touches the actual bytes that are valid.
1270 #define AssignDomainName(DST, SRC) mDNSPlatformMemCopy((SRC).c, (DST).c, DomainNameLength(&(SRC)))
1271
1272 // Comparison functions
1273 extern mDNSBool SameDomainLabel(const mDNSu8 *a, const mDNSu8 *b);
1274 extern mDNSBool SameDomainName(const domainname *const d1, const domainname *const d2);
1275
1276 // Get total length of domain name, in native DNS format, including terminal root label
1277 // (e.g. length of "com." is 5 (length byte, three data bytes, final zero)
1278 extern mDNSu16 DomainNameLength(const domainname *const name);
1279
1280 // Append functions to append one or more labels to an existing native format domain name:
1281 // AppendLiteralLabelString adds a single label from a literal C string, with no escape character interpretation.
1282 // AppendDNSNameString adds zero or more labels from a C string using conventional DNS dots-and-escaping interpretation
1283 // AppendDomainLabel adds a single label from a native format domainlabel
1284 // AppendDomainName adds zero or more labels from a native format domainname
1285 extern mDNSu8 *AppendLiteralLabelString(domainname *const name, const char *cstr);
1286 extern mDNSu8 *AppendDNSNameString (domainname *const name, const char *cstr);
1287 extern mDNSu8 *AppendDomainLabel (domainname *const name, const domainlabel *const label);
1288 extern mDNSu8 *AppendDomainName (domainname *const name, const domainname *const append);
1289
1290 // Convert from null-terminated string to native DNS format:
1291 // The DomainLabel form makes a single label from a literal C string, with no escape character interpretation.
1292 // The DomainName form makes native format domain name from a C string using conventional DNS interpretation:
1293 // dots separate labels, and within each label, '\.' represents a literal dot, '\\' represents a literal
1294 // backslash and backslash with three decimal digits (e.g. \000) represents an arbitrary byte value.
1295 extern mDNSBool MakeDomainLabelFromLiteralString(domainlabel *const label, const char *cstr);
1296 extern mDNSu8 *MakeDomainNameFromDNSNameString (domainname *const name, const char *cstr);
1297
1298 // Convert native format domainlabel or domainname back to C string format
1299 // IMPORTANT:
1300 // When using ConvertDomainLabelToCString, the target buffer must be MAX_ESCAPED_DOMAIN_LABEL (254) bytes long
1301 // to guarantee there will be no buffer overrun. It is only safe to use a buffer shorter than this in rare cases
1302 // where the label is known to be constrained somehow (for example, if the label is known to be either "_tcp" or "_udp").
1303 // Similarly, when using ConvertDomainNameToCString, the target buffer must be MAX_ESCAPED_DOMAIN_NAME (1005) bytes long.
1304 // See definitions of MAX_ESCAPED_DOMAIN_LABEL and MAX_ESCAPED_DOMAIN_NAME for more detailed explanation.
1305 extern char *ConvertDomainLabelToCString_withescape(const domainlabel *const name, char *cstr, char esc);
1306 #define ConvertDomainLabelToCString_unescaped(D,C) ConvertDomainLabelToCString_withescape((D), (C), 0)
1307 #define ConvertDomainLabelToCString(D,C) ConvertDomainLabelToCString_withescape((D), (C), '\\')
1308 extern char *ConvertDomainNameToCString_withescape(const domainname *const name, char *cstr, char esc);
1309 #define ConvertDomainNameToCString_unescaped(D,C) ConvertDomainNameToCString_withescape((D), (C), 0)
1310 #define ConvertDomainNameToCString(D,C) ConvertDomainNameToCString_withescape((D), (C), '\\')
1311
1312 extern void ConvertUTF8PstringToRFC1034HostLabel(const mDNSu8 UTF8Name[], domainlabel *const hostlabel);
1313
1314 extern mDNSu8 *ConstructServiceName(domainname *const fqdn, const domainlabel *name, const domainname *type, const domainname *const domain);
1315 extern mDNSBool DeconstructServiceName(const domainname *const fqdn, domainlabel *const name, domainname *const type, domainname *const domain);
1316
1317 // Note: Some old functions have been replaced by more sensibly-named versions.
1318 // You can uncomment the hash-defines below if you don't want to have to change your source code right away.
1319 // When updating your code, note that (unlike the old versions) *all* the new routines take the target object
1320 // as their first parameter.
1321 //#define ConvertCStringToDomainName(SRC,DST) MakeDomainNameFromDNSNameString((DST),(SRC))
1322 //#define ConvertCStringToDomainLabel(SRC,DST) MakeDomainLabelFromLiteralString((DST),(SRC))
1323 //#define AppendStringLabelToName(DST,SRC) AppendLiteralLabelString((DST),(SRC))
1324 //#define AppendStringNameToName(DST,SRC) AppendDNSNameString((DST),(SRC))
1325 //#define AppendDomainLabelToName(DST,SRC) AppendDomainLabel((DST),(SRC))
1326 //#define AppendDomainNameToName(DST,SRC) AppendDomainName((DST),(SRC))
1327
1328 // ***************************************************************************
1329 #if 0
1330 #pragma mark - Other utility functions
1331 #endif
1332
1333 extern mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, va_list arg);
1334 extern mDNSu32 mDNS_snprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, ...) IS_A_PRINTF_STYLE_FUNCTION(3,4);
1335 extern char *DNSTypeName(mDNSu16 rrtype);
1336 extern char *GetRRDisplayString_rdb(mDNS *const m, const ResourceRecord *rr, RDataBody *rd);
1337 #define GetRRDisplayString(m, rr) GetRRDisplayString_rdb((m), &(rr)->resrec, &(rr)->resrec.rdata->u)
1338 extern mDNSBool mDNSSameAddress(const mDNSAddr *ip1, const mDNSAddr *ip2);
1339 extern void IncrementLabelSuffix(domainlabel *name, mDNSBool RichText);
1340
1341 // ***************************************************************************
1342 #if 0
1343 #pragma mark - PlatformSupport interface
1344 #endif
1345
1346 // This section defines the interface to the Platform Support layer.
1347 // Normal client code should not use any of types defined here, or directly call any of the functions defined here.
1348 // The definitions are placed here because sometimes clients do use these calls indirectly, via other supported client operations.
1349 // For example, AssignDomainName is a macro defined using mDNSPlatformMemCopy()
1350
1351 typedef packedstruct
1352 {
1353 mDNSOpaque16 id;
1354 mDNSOpaque16 flags;
1355 mDNSu16 numQuestions;
1356 mDNSu16 numAnswers;
1357 mDNSu16 numAuthorities;
1358 mDNSu16 numAdditionals;
1359 } DNSMessageHeader;
1360
1361 // We can send and receive packets up to 9000 bytes (Ethernet Jumbo Frame size, if that ever becomes widely used)
1362 // However, in the normal case we try to limit packets to 1500 bytes so that we don't get IP fragmentation on standard Ethernet
1363 // 40 (IPv6 header) + 8 (UDP header) + 12 (DNS message header) + 1440 (DNS message body) = 1500 total
1364 #define AbsoluteMaxDNSMessageData 8940
1365 #define NormalMaxDNSMessageData 1440
1366 typedef packedstruct
1367 {
1368 DNSMessageHeader h; // Note: Size 12 bytes
1369 mDNSu8 data[AbsoluteMaxDNSMessageData]; // 40 (IPv6) + 8 (UDP) + 12 (DNS header) + 8940 (data) = 9000
1370 } DNSMessage;
1371
1372 // Every platform support module must provide the following functions.
1373 // mDNSPlatformInit() typically opens a communication endpoint, and starts listening for mDNS packets.
1374 // When Setup is complete, the platform support layer calls mDNSCoreInitComplete().
1375 // mDNSPlatformSendUDP() sends one UDP packet
1376 // When a packet is received, the PlatformSupport code calls mDNSCoreReceive()
1377 // mDNSPlatformClose() tidies up on exit
1378 // Note: mDNSPlatformMemAllocate/mDNSPlatformMemFree are only required for handling oversized resource records.
1379 // If your target platform has a well-defined specialized application, and you know that all the records it uses
1380 // are InlineCacheRDSize or less, then you can just make a simple mDNSPlatformMemAllocate() stub that always returns
1381 // NULL. InlineCacheRDSize is a compile-time constant, which is set by default to 64. If you need to handle records
1382 // a little larger than this and you don't want to have to implement run-time allocation and freeing, then you
1383 // can raise the value of this constant to a suitable value (at the expense of increased memory usage).
1384 extern mStatus mDNSPlatformInit (mDNS *const m);
1385 extern void mDNSPlatformClose (mDNS *const m);
1386 extern mStatus mDNSPlatformSendUDP(const mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end,
1387 mDNSInterfaceID InterfaceID, mDNSIPPort srcport, const mDNSAddr *dst, mDNSIPPort dstport);
1388
1389 extern void mDNSPlatformLock (const mDNS *const m);
1390 extern void mDNSPlatformUnlock (const mDNS *const m);
1391
1392 extern void mDNSPlatformStrCopy (const void *src, void *dst);
1393 extern mDNSu32 mDNSPlatformStrLen (const void *src);
1394 extern void mDNSPlatformMemCopy (const void *src, void *dst, mDNSu32 len);
1395 extern mDNSBool mDNSPlatformMemSame (const void *src, const void *dst, mDNSu32 len);
1396 extern void mDNSPlatformMemZero ( void *dst, mDNSu32 len);
1397 extern void * mDNSPlatformMemAllocate (mDNSu32 len);
1398 extern void mDNSPlatformMemFree (void *mem);
1399 extern mStatus mDNSPlatformTimeInit (mDNSs32 *timenow);
1400
1401 // The core mDNS code provides these functions, for the platform support code to call at appropriate times
1402 //
1403 // mDNS_GenerateFQDN() is called once on startup (typically from mDNSPlatformInit())
1404 // and then again on each subsequent change of the dot-local host name.
1405 //
1406 // mDNS_RegisterInterface() is used by the platform support layer to inform mDNSCore of what
1407 // physical and/or logical interfaces are available for sending and receiving packets.
1408 // Typically it is called on startup for each available interface, but register/deregister may be
1409 // called again later, on multiple occasions, to inform the core of interface configuration changes.
1410 // If set->Advertise is set non-zero, then mDNS_RegisterInterface() also registers the standard
1411 // resource records that should be associated with every publicised IP address/interface:
1412 // -- Name-to-address records (A/AAAA)
1413 // -- Address-to-name records (PTR)
1414 // -- Host information (HINFO)
1415 //
1416 // mDNSCoreInitComplete() is called when the platform support layer is finished.
1417 // Typically this is at the end of mDNSPlatformInit(), but may be later
1418 // (on platforms like OT that allow asynchronous initialization of the networking stack).
1419 //
1420 // mDNSCoreReceive() is called when a UDP packet is received
1421 //
1422 // mDNSCoreMachineSleep() is called when the machine sleeps or wakes
1423 // (This refers to heavyweight laptop-style sleep/wake that disables network access,
1424 // not lightweight second-by-second CPU power management modes.)
1425
1426 extern void mDNS_GenerateFQDN(mDNS *const m);
1427 extern mStatus mDNS_RegisterInterface (mDNS *const m, NetworkInterfaceInfo *set);
1428 extern void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set);
1429 extern void mDNSCoreInitComplete(mDNS *const m, mStatus result);
1430 extern void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end,
1431 const mDNSAddr *const srcaddr, const mDNSIPPort srcport,
1432 const mDNSAddr *const dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, mDNSu8 ttl);
1433 extern void mDNSCoreMachineSleep(mDNS *const m, mDNSBool wake);
1434
1435 // ***************************************************************************
1436 #if 0
1437 #pragma mark - Compile-Time assertion checks
1438 #endif
1439
1440 // Some C compiler cleverness. We can make the compiler check certain things for
1441 // us, and report compile-time errors if anything is wrong. The usual way to do
1442 // this would be to use a run-time "if" statement, but then you don't find out
1443 // what's wrong until you run the software. This way, if the assertion condition
1444 // is false, the array size is negative, and the complier complains immediately.
1445
1446 struct mDNS_CompileTimeAssertionChecks
1447 {
1448 // Check that the compiler generated our on-the-wire packet format structure definitions
1449 // properly packed, without adding padding bytes to align fields on 32-bit or 64-bit boundaries.
1450 char assert0[(sizeof(rdataSRV) == 262 ) ? 1 : -1];
1451 char assert1[(sizeof(DNSMessageHeader) == 12 ) ? 1 : -1];
1452 char assert2[(sizeof(DNSMessage) == 12+AbsoluteMaxDNSMessageData) ? 1 : -1];
1453 char assert3[(sizeof(mDNSs8) == 1 ) ? 1 : -1];
1454 char assert4[(sizeof(mDNSu8) == 1 ) ? 1 : -1];
1455 char assert5[(sizeof(mDNSs16) == 2 ) ? 1 : -1];
1456 char assert6[(sizeof(mDNSu16) == 2 ) ? 1 : -1];
1457 char assert7[(sizeof(mDNSs32) == 4 ) ? 1 : -1];
1458 char assert8[(sizeof(mDNSu32) == 4 ) ? 1 : -1];
1459 char assert9[(sizeof(mDNSOpaque16) == 2 ) ? 1 : -1];
1460 char assertA[(sizeof(mDNSOpaque32) == 4 ) ? 1 : -1];
1461 char assertB[(sizeof(mDNSOpaque128) == 16 ) ? 1 : -1];
1462 };
1463
1464 // ***************************************************************************
1465
1466 #ifdef __cplusplus
1467 }
1468 #endif
1469
1470 #endif