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