1 /*
2  * Copyright (c) 2002-2024 Apple Inc. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     https://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15 
16    NOTE:
17    If you're building an application that uses DNS Service Discovery
18    this is probably NOT the header file you're looking for.
19    In most cases you will want to use /usr/include/dns_sd.h instead.
20 
21    This header file defines the lowest level raw interface to mDNSCore,
22    which is appropriate *only* on tiny embedded systems where everything
23    runs in a single address space and memory is extremely constrained.
24    All the APIs here are malloc-free, which means that the caller is
25    responsible for passing in a pointer to the relevant storage that
26    will be used in the execution of that call, and (when called with
27    correct parameters) all the calls are guaranteed to succeed. There
28    is never a case where a call can suffer intermittent failures because
29    the implementation calls malloc() and sometimes malloc() returns NULL
30    because memory is so limited that no more is available.
31    This is primarily for devices that need to have precisely known fixed
32    memory requirements, with absolutely no uncertainty or run-time variation,
33    but that certainty comes at a cost of more difficult programming.
34 
35    For applications running on general-purpose desktop operating systems
36    (Mac OS, Linux, Solaris, Windows, etc.) the API you should use is
37    /usr/include/dns_sd.h, which defines the API by which multiple
38    independent client processes communicate their DNS Service Discovery
39    requests to a single "mdnsd" daemon running in the background.
40 
41    Even on platforms that don't run multiple independent processes in
42    multiple independent address spaces, you can still use the preferred
43    dns_sd.h APIs by linking in "dnssd_clientshim.c", which implements
44    the standard "dns_sd.h" API calls, allocates any required storage
45    using malloc(), and then calls through to the low-level malloc-free
46    mDNSCore routines defined here. This has the benefit that even though
47    you're running on a small embedded system with a single address space,
48    you can still use the exact same client C code as you'd use on a
49    general-purpose desktop system.
50 
51  */
52 
53 #ifndef __mDNSEmbeddedAPI_h
54 #define __mDNSEmbeddedAPI_h
55 
56 #ifdef __MINGW32__
57 // MinGW defines "#define interface struct" for ObjC compatibility.
58 #undef interface
59 #endif
60 
61 #if defined(EFI32) || defined(EFI64) || defined(EFIX64)
62 // EFI doesn't have stdarg.h unless it's building with GCC.
63 #include "Tiano.h"
64 #if !defined(__GNUC__)
65 #define va_list         VA_LIST
66 #define va_start(a, b)  VA_START(a, b)
67 #define va_end(a)       VA_END(a)
68 #define va_arg(a, b)    VA_ARG(a, b)
69 #endif
70 #else
71 #include <stdarg.h>     // stdarg.h is required for for va_list support for the mDNS_vsnprintf declaration
72 #endif
73 
74 #include <inttypes.h>   // for uintptr_t and PRIXPTR
75 
76 
77 #include "mDNSFeatures.h"
78 #include "mDNSDebug.h"
79 #include "general.h"
80 
81 // ***************************************************************************
82 // Feature removal compile options & limited resource targets
83 
84 // The following compile options are responsible for removing certain features from mDNSCore to reduce the
85 // memory footprint for use in embedded systems with limited resources.
86 
87 // UNICAST_DISABLED - disables unicast DNS functionality, including Wide Area Bonjour
88 // SPC_DISABLED - disables Bonjour Sleep Proxy client
89 // IDLESLEEPCONTROL_DISABLED - disables sleep control for Bonjour Sleep Proxy clients
90 
91 // In order to disable the above features pass the option to your compiler, e.g. -D UNICAST_DISABLED
92 
93 #if MDNSRESPONDER_SUPPORTS(APPLE, WEB_CONTENT_FILTER)
94 #include <WebFilterDNS/WebFilterDNS.h>
95 #endif
96 
97 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
98 #include "dnssec_obj_dns_question_member.h"
99 #include "dnssec_obj_resource_record_member.h"
100 #include "dnssec_obj_denial_of_existence.h"
101 #include "dnssec_obj_trust_anchor_manager.h"
102 #endif
103 
104 #if MDNSRESPONDER_SUPPORTS(APPLE, DNS_PUSH)
105 #include "dns_push_obj_dns_question_member.h"
106 #include "dns_push_obj_resource_record_member.h"
107 #endif
108 
109 // Additionally, the LIMITED_RESOURCES_TARGET compile option will reduce the maximum DNS message sizes.
110 
111 #ifdef LIMITED_RESOURCES_TARGET
112 // Don't support jumbo frames
113 // 40 (IPv6 header) + 8 (UDP header) + 12 (DNS message header) + 1440 (DNS message body) = 1500 total
114 #define AbsoluteMaxDNSMessageData   1440
115 // StandardAuthRDSize is 264 (256+8), which is large enough to hold a maximum-sized SRV record (6 + 256 bytes)
116 #define MaximumRDSize               264
117 #endif
118 
119 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
120 #include <mdns/cache_metadata.h>
121 #include <mdns/private.h>
122 #endif
123 
124 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
125 #include <mdns/audit_token.h>
126 #endif
127 
128 #if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
129 #include "dnssd_private.h" // For dnssd_log_privacy_level_t.
130 #endif
131 
132 #if MDNSRESPONDER_SUPPORTS(APPLE, RUNTIME_MDNS_METRICS)
133 #include <mdns/multicast_delay_histogram.h>
134 #endif
135 
136 #if __has_feature(objc_fixed_enum) || __has_extension(cxx_fixed_enum) || __has_extension(cxx_strong_enums)
137     #define MDNSRESPONDER_CLOSED_ENUM(NAME, UNDERLYING_TYPE, ...) \
138         typedef enum : UNDERLYING_TYPE {__VA_ARGS__} MDNSRESPONDER_ENUM_ATTR_CLOSED NAME
139 #else
140     #define MDNSRESPONDER_CLOSED_ENUM(NAME, UNDERLYING_TYPE, ...) \
141         typedef UNDERLYING_TYPE NAME; enum NAME ## _Enum {__VA_ARGS__} MDNSRESPONDER_ENUM_ATTR_CLOSED
142 #endif
143 
144 #ifdef __cplusplus
145 extern "C" {
146 #endif
147 
148 // ***************************************************************************
149 // Function scope indicators
150 
151 // If you see "mDNSlocal" before a function name in a C file, it means the function is not callable outside this file
152 #ifndef mDNSlocal
153 #define mDNSlocal static
154 #endif
155 // If you see "mDNSexport" before a symbol in a C file, it means the symbol is exported for use by clients
156 // For every "mDNSexport" in a C file, there needs to be a corresponding "extern" declaration in some header file
157 // (When a C file #includes a header file, the "extern" declarations tell the compiler:
158 // "This symbol exists -- but not necessarily in this C file.")
159 #ifndef mDNSexport
160 #define mDNSexport
161 #endif
162 
163 // Explanation: These local/export markers are a little habit of mine for signaling the programmers' intentions.
164 // When "mDNSlocal" is just a synonym for "static", and "mDNSexport" is a complete no-op, you could be
165 // forgiven for asking what purpose they serve. The idea is that if you see "mDNSexport" in front of a
166 // function definition it means the programmer intended it to be exported and callable from other files
167 // in the project. If you see "mDNSlocal" in front of a function definition it means the programmer
168 // intended it to be private to that file. If you see neither in front of a function definition it
169 // means the programmer forgot (so you should work out which it is supposed to be, and fix it).
170 // Using "mDNSlocal" instead of "static" makes it easier to do a textual searches for one or the other.
171 // For example you can do a search for "static" to find if any functions declare any local variables as "static"
172 // (generally a bad idea unless it's also "const", because static storage usually risks being non-thread-safe)
173 // without the results being cluttered with hundreds of matches for functions declared static.
174 // - Stuart Cheshire
175 
176 // ***************************************************************************
177 // Structure packing macro
178 
179 // If we're not using GNUC, it's not fatal.
180 // Most compilers naturally pack the on-the-wire structures correctly anyway, so a plain "struct" is usually fine.
181 // In the event that structures are not packed correctly, mDNS_Init() will detect this and report an error, so the
182 // developer will know what's wrong, and can investigate what needs to be done on that compiler to provide proper packing.
183 #ifndef packedstruct
184  #if ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9)))
185   #define packedstruct struct __attribute__((__packed__))
186   #define packedunion  union  __attribute__((__packed__))
187  #else
188   #define packedstruct struct
189   #define packedunion  union
190  #endif
191 #endif
192 
193 #ifndef fallthrough
194  #if MDNS_COMPILER_IS_CLANG()
195   #if __has_attribute(fallthrough)
196    #define fallthrough() __attribute__((fallthrough))
197   #else
198    #define fallthrough()
199   #endif
200  #elif __GNUC__
201   #define fallthrough() __attribute__((fallthrough))
202  #else
203   #define fallthrough()
204  #endif // __GNUC__
205 #endif // fallthrough
206 
207 // ***************************************************************************
208 #if 0
209 #pragma mark - DNS Resource Record class and type constants
210 #endif
211 
212 typedef enum                            // From RFC 1035
213 {
214     kDNSClass_IN               = 1,     // Internet
215     kDNSClass_CS               = 2,     // CSNET
216     kDNSClass_CH               = 3,     // CHAOS
217     kDNSClass_HS               = 4,     // Hesiod
218     kDNSClass_NONE             = 254,   // Used in DNS UPDATE [RFC 2136]
219 
220     kDNSClass_Mask             = 0x7FFF, // Multicast DNS uses the bottom 15 bits to identify the record class...
221     kDNSClass_UniqueRRSet      = 0x8000, // ... and the top bit indicates that all other cached records are now invalid
222 
223     kDNSQClass_ANY             = 255,   // Not a DNS class, but a DNS query class, meaning "all classes"
224     kDNSQClass_UnicastResponse = 0x8000 // Top bit set in a question means "unicast response acceptable"
225 } DNS_ClassValues;
226 
227 typedef enum                // From RFC 1035
228 {
229     kDNSType_A = 1,         //  1 Address
230     kDNSType_NS,            //  2 Name Server
231     kDNSType_MD,            //  3 Mail Destination
232     kDNSType_MF,            //  4 Mail Forwarder
233     kDNSType_CNAME,         //  5 Canonical Name
234     kDNSType_SOA,           //  6 Start of Authority
235     kDNSType_MB,            //  7 Mailbox
236     kDNSType_MG,            //  8 Mail Group
237     kDNSType_MR,            //  9 Mail Rename
238     kDNSType_NULL,          // 10 NULL RR
239     kDNSType_WKS,           // 11 Well-known-service
240     kDNSType_PTR,           // 12 Domain name pointer
241     kDNSType_HINFO,         // 13 Host information
242     kDNSType_MINFO,         // 14 Mailbox information
243     kDNSType_MX,            // 15 Mail Exchanger
244     kDNSType_TXT,           // 16 Arbitrary text string
245     kDNSType_RP,            // 17 Responsible person
246     kDNSType_AFSDB,         // 18 AFS cell database
247     kDNSType_X25,           // 19 X_25 calling address
248     kDNSType_ISDN,          // 20 ISDN calling address
249     kDNSType_RT,            // 21 Router
250     kDNSType_NSAP,          // 22 NSAP address
251     kDNSType_NSAP_PTR,      // 23 Reverse NSAP lookup (deprecated)
252     kDNSType_SIG,           // 24 Security signature
253     kDNSType_KEY,           // 25 Security key
254     kDNSType_PX,            // 26 X.400 mail mapping
255     kDNSType_GPOS,          // 27 Geographical position (withdrawn)
256     kDNSType_AAAA,          // 28 IPv6 Address
257     kDNSType_LOC,           // 29 Location Information
258     kDNSType_NXT,           // 30 Next domain (security)
259     kDNSType_EID,           // 31 Endpoint identifier
260     kDNSType_NIMLOC,        // 32 Nimrod Locator
261     kDNSType_SRV,           // 33 Service record
262     kDNSType_ATMA,          // 34 ATM Address
263     kDNSType_NAPTR,         // 35 Naming Authority PoinTeR
264     kDNSType_KX,            // 36 Key Exchange
265     kDNSType_CERT,          // 37 Certification record
266     kDNSType_A6,            // 38 IPv6 Address (deprecated)
267     kDNSType_DNAME,         // 39 Non-terminal DNAME (for IPv6)
268     kDNSType_SINK,          // 40 Kitchen sink (experimental)
269     kDNSType_OPT,           // 41 EDNS0 option (meta-RR)
270     kDNSType_APL,           // 42 Address Prefix List
271     kDNSType_DS,            // 43 Delegation Signer
272     kDNSType_SSHFP,         // 44 SSH Key Fingerprint
273     kDNSType_IPSECKEY,      // 45 IPSECKEY
274     kDNSType_RRSIG,         // 46 RRSIG
275     kDNSType_NSEC,          // 47 Denial of Existence
276     kDNSType_DNSKEY,        // 48 DNSKEY
277     kDNSType_DHCID,         // 49 DHCP Client Identifier
278     kDNSType_NSEC3,         // 50 Hashed Authenticated Denial of Existence
279     kDNSType_NSEC3PARAM,    // 51 Hashed Authenticated Denial of Existence
280 
281     kDNSType_HIP = 55,      // 55 Host Identity Protocol
282 
283     kDNSType_SVCB = 64,     // 64 Service Binding
284     kDNSType_HTTPS,         // 65 HTTPS Service Binding
285 
286     kDNSType_SPF = 99,      // 99 Sender Policy Framework for E-Mail
287     kDNSType_UINFO,         // 100 IANA-Reserved
288     kDNSType_UID,           // 101 IANA-Reserved
289     kDNSType_GID,           // 102 IANA-Reserved
290     kDNSType_UNSPEC,        // 103 IANA-Reserved
291 
292     kDNSType_TKEY = 249,    // 249 Transaction key
293     kDNSType_TSIG,          // 250 Transaction signature
294     kDNSType_IXFR,          // 251 Incremental zone transfer
295     kDNSType_AXFR,          // 252 Transfer zone of authority
296     kDNSType_MAILB,         // 253 Transfer mailbox records
297     kDNSType_MAILA,         // 254 Transfer mail agent records
298     kDNSQType_ANY,          // Not a DNS type, but a DNS query type, meaning "all types"
299     kDNSType_TSR = 65323    // Time since received, private for now, will update when allocated by IANA
300 } DNS_TypeValues;
301 
302 // ***************************************************************************
303 #if 0
304 #pragma mark -
305 #pragma mark - Simple types
306 #endif
307 
308 // mDNS defines its own names for these common types to simplify portability across
309 // multiple platforms that may each have their own (different) names for these types.
310 typedef unsigned char mDNSBool;
311 typedef   signed char mDNSs8;
312 typedef unsigned char mDNSu8;
313 typedef   signed short mDNSs16;
314 typedef unsigned short mDNSu16;
315 
316 // Source: http://www.unix.org/version2/whatsnew/lp64_wp.html
317 // http://software.intel.com/sites/products/documentation/hpc/mkl/lin/MKL_UG_structure/Support_for_ILP64_Programming.htm
318 // It can be safely assumed that int is 32bits on the platform
319 #if defined(_ILP64) || defined(__ILP64__)
320 typedef   signed int32 mDNSs32;
321 typedef unsigned int32 mDNSu32;
322 #else
323 typedef   signed int mDNSs32;
324 typedef unsigned int mDNSu32;
325 #endif
326 
327 // To enforce useful type checking, we make mDNSInterfaceID be a pointer to a dummy struct
328 // This way, mDNSInterfaceIDs can be assigned, and compared with each other, but not with other types
329 // Declaring the type to be the typical generic "void *" would lack this type checking
330 typedef const struct mDNSInterfaceID_dummystruct { void *dummy; } *mDNSInterfaceID;
331 
332 // Use when printing interface IDs; the interface ID is actually a pointer, but we're only using
333 // the pointer as a unique identifier, and in special cases it's actually a small number.   So there's
334 // little point in printing all 64 bits--the upper 32 bits in particular will not add information.
335 #define IIDPrintable(x) ((uint32_t)(uintptr_t)(x))
336 
337 // These types are for opaque two- and four-byte identifiers.
338 // The "NotAnInteger" fields of the unions allow the value to be conveniently passed around in a
339 // register for the sake of efficiency, and compared for equality or inequality, but don't forget --
340 // just because it is in a register doesn't mean it is an integer. Operations like greater than,
341 // less than, add, multiply, increment, decrement, etc., are undefined for opaque identifiers,
342 // and if you make the mistake of trying to do those using the NotAnInteger field, then you'll
343 // find you get code that doesn't work consistently on big-endian and little-endian machines.
344 #if defined(_WIN32)
345  #pragma pack(push,2)
346 #endif
347 typedef       union { mDNSu8 b[ 2]; mDNSu16 NotAnInteger; } mDNSOpaque16;
348 typedef       union { mDNSu8 b[ 4]; mDNSu32 NotAnInteger; } mDNSOpaque32;
349 typedef packedunion { mDNSu8 b[ 6]; mDNSu16 w[3]; mDNSu32 l[1]; } mDNSOpaque48;
350 typedef       union { mDNSu8 b[ 8]; mDNSu16 w[4]; mDNSu32 l[2]; } mDNSOpaque64;
351 typedef       union { mDNSu8 b[16]; mDNSu16 w[8]; mDNSu32 l[4]; } mDNSOpaque128;
352 #if defined(_WIN32)
353  #pragma pack(pop)
354 #endif
355 
356 typedef mDNSOpaque16 mDNSIPPort;        // An IP port is a two-byte opaque identifier (not an integer)
357 typedef mDNSOpaque32 mDNSv4Addr;        // An IP address is a four-byte opaque identifier (not an integer)
358 typedef mDNSOpaque128 mDNSv6Addr;       // An IPv6 address is a 16-byte opaque identifier (not an integer)
359 typedef mDNSOpaque48 mDNSEthAddr;       // An Ethernet address is a six-byte opaque identifier (not an integer)
360 
361 // Bit operations for opaque 64 bit quantity. Uses the 32 bit quantity(l[2]) to set and clear bits
362 #define mDNSNBBY 8
363 #define bit_set_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] |= (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
364 #define bit_clr_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] &= ~(1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
365 #define bit_get_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] & (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
366 
367 // Bit operations for opaque 128 bit quantity. Uses the 32 bit quantity(l[4]) to set and clear bits
368 #define bit_set_opaque128(op128, index) (op128.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] |= (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
369 #define bit_clr_opaque128(op128, index) (op128.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] &= ~(1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
370 #define bit_get_opaque128(op128, index) (op128.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] & (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
371 
372 typedef enum
373 {
374     mDNSAddrType_None    = 0,
375     mDNSAddrType_IPv4    = 4,
376     mDNSAddrType_IPv6    = 6,
377     mDNSAddrType_Unknown = ~0   // Special marker value used in known answer list recording
378 } mDNSAddr_Type;
379 
380 typedef enum
381 {
382     mDNSTransport_None = 0,
383     mDNSTransport_UDP  = 1,
384     mDNSTransport_TCP  = 2
385 } mDNSTransport_Type;
386 
387 typedef struct
388 {
389     mDNSs32 type;
390     union { mDNSv6Addr v6; mDNSv4Addr v4; } ip;
391 } mDNSAddr;
392 
393 enum { mDNSfalse = 0, mDNStrue = 1 };
394 
395 #define mDNSNULL 0L
396 
397 enum
398 {
399     mStatus_Waiting           = 1,
400     mStatus_NoError           = 0,
401 
402     // mDNS return values are in the range FFFE FF00 (-65792) to FFFE FFFF (-65537)
403     // The top end of the range (FFFE FFFF) is used for error codes;
404     // the bottom end of the range (FFFE FF00) is used for non-error values;
405 
406     // Error codes:
407     mStatus_UnknownErr                = -65537,     // First value: 0xFFFE FFFF
408     mStatus_NoSuchNameErr             = -65538,
409     mStatus_NoMemoryErr               = -65539,
410     mStatus_BadParamErr               = -65540,
411     mStatus_BadReferenceErr           = -65541,
412     mStatus_BadStateErr               = -65542,
413     mStatus_BadFlagsErr               = -65543,
414     mStatus_UnsupportedErr            = -65544,
415     mStatus_NotInitializedErr         = -65545,
416     mStatus_NoCache                   = -65546,
417     mStatus_AlreadyRegistered         = -65547,
418     mStatus_NameConflict              = -65548,
419     mStatus_Invalid                   = -65549,
420     mStatus_Firewall                  = -65550,
421     mStatus_Incompatible              = -65551,
422     mStatus_BadInterfaceErr           = -65552,
423     mStatus_Refused                   = -65553,
424     mStatus_NoSuchRecord              = -65554,
425     mStatus_NoAuth                    = -65555,
426     mStatus_NoSuchKey                 = -65556,
427     mStatus_NATTraversal              = -65557,
428     mStatus_DoubleNAT                 = -65558,
429     mStatus_BadTime                   = -65559,
430     mStatus_BadSig                    = -65560,     // while we define this per RFC 2845, BIND 9 returns Refused for bad/missing signatures
431     mStatus_BadKey                    = -65561,
432     mStatus_TransientErr              = -65562,     // transient failures, e.g. sending packets shortly after a network transition or wake from sleep
433     mStatus_ServiceNotRunning         = -65563,     // Background daemon not running
434     mStatus_NATPortMappingUnsupported = -65564,     // NAT doesn't support PCP, NAT-PMP or UPnP
435     mStatus_NATPortMappingDisabled    = -65565,     // NAT supports PCP, NAT-PMP or UPnP, but it's disabled by the administrator
436     mStatus_NoRouter                  = -65566,
437     mStatus_PollingMode               = -65567,
438     mStatus_Timeout                   = -65568,
439     mStatus_DefunctConnection         = -65569,
440     mStatus_PolicyDenied              = -65570,
441     mStatus_NotPermitted              = -65571,     // From kDNSSDAdvertisingProxyStatus_NotPermitted
442     mStatus_StaleData                 = -65572,
443     // -65573 to -65785 currently unused; available for allocation
444 
445     // udp connection status
446     mStatus_HostUnreachErr    = -65786,
447 
448     // tcp connection status
449     mStatus_ConnPending       = -65787,
450     mStatus_ConnFailed        = -65788,
451     mStatus_ConnEstablished   = -65789,
452 
453     // Non-error values:
454     mStatus_GrowCache         = -65790,
455     mStatus_ConfigChanged     = -65791,
456     mStatus_MemFree           = -65792      // Last value: 0xFFFE FF00
457 
458     // mStatus_MemFree is the last legal mDNS error code, at the end of the range allocated for mDNS
459 };
460 
461 typedef mDNSs32 mStatus;
462 
463 #define MaxIp 5 // Needs to be consistent with MaxInputIf in dns_services.h
464 
465 typedef enum { q_stop = 0, q_start } q_state;
466 typedef enum { reg_stop = 0, reg_start } reg_state;
467 
468 // RFC 1034/1035 specify that a domain label consists of a length byte plus up to 63 characters
469 #define MAX_DOMAIN_LABEL 63
470 typedef struct { mDNSu8 c[ 64]; } domainlabel;      // One label: length byte and up to 63 characters
471 
472 // RFC 1034/1035/2181 specify that a domain name (length bytes and data bytes) may be up to 255 bytes long,
473 // plus the terminating zero at the end makes 256 bytes total in the on-the-wire format.
474 #define MAX_DOMAIN_NAME 256
475 typedef struct { mDNSu8 c[256]; } domainname;       // Up to 256 bytes of length-prefixed domainlabels
476 
477 typedef struct { mDNSu8 c[256]; } UTF8str255;       // Null-terminated C string
478 
479 // The longest legal textual form of a DNS name is 1009 bytes, including the C-string terminating NULL at the end.
480 // Explanation:
481 // When a native domainname object is converted to printable textual form using ConvertDomainNameToCString(),
482 // non-printing characters are represented in the conventional DNS way, as '\ddd', where ddd is a three-digit decimal number.
483 // The longest legal domain name is 256 bytes, in the form of four labels as shown below:
484 // Length byte, 63 data bytes, length byte, 63 data bytes, length byte, 63 data bytes, length byte, 62 data bytes, zero byte.
485 // Each label is encoded textually as characters followed by a trailing dot.
486 // If every character has to be represented as a four-byte escape sequence, then this makes the maximum textual form four labels
487 // plus the C-string terminating NULL as shown below:
488 // 63*4+1 + 63*4+1 + 63*4+1 + 62*4+1 + 1 = 1009.
489 // Note that MAX_ESCAPED_DOMAIN_LABEL is not normally used: If you're only decoding a single label, escaping is usually not required.
490 // It is for domain names, where dots are used as label separators, that proper escaping is vital.
491 #define MAX_ESCAPED_DOMAIN_LABEL 254
492 #define MAX_ESCAPED_DOMAIN_NAME 1009
493 
494 // MAX_REVERSE_MAPPING_NAME
495 // For IPv4: "123.123.123.123.in-addr.arpa."  30 bytes including terminating NUL
496 // For IPv6: "x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.ip6.arpa."  74 bytes including terminating NUL
497 
498 #define MAX_REVERSE_MAPPING_NAME_V4 30
499 #define MAX_REVERSE_MAPPING_NAME_V6 74
500 #define MAX_REVERSE_MAPPING_NAME    74
501 
502 // Most records have a TTL of 75 minutes, so that their 80% cache-renewal query occurs once per hour.
503 // For records containing a hostname (in the name on the left, or in the rdata on the right),
504 // like A, AAAA, reverse-mapping PTR, and SRV, we previously used a two-minute TTL by default, because we did't want
505 // them to hang around for too long in the cache if the host in question crashes or otherwise goes away... but to reduce
506 // the multicast traffic required to refresh these records, the same 75 minute TTL is now used for all record types.
507 
508 #define kStandardTTL (3600UL * 100 / 80)
509 #define kHostNameTTL kStandardTTL           // Was 120UL
510 
511 // Multicast DNS uses announcements (gratuitous responses) to update peer caches.
512 // This means it is feasible to use relatively larger TTL values than we might otherwise
513 // use, because we have a cache coherency protocol to keep the peer caches up to date.
514 // With Unicast DNS, once an authoritative server gives a record with a certain TTL value to a client
515 // or caching server, that client or caching server is entitled to hold onto the record until its TTL
516 // expires, and has no obligation to contact the authoritative server again until that time arrives.
517 // This means that whereas Multicast DNS can use announcements to pre-emptively update stale data
518 // before it would otherwise have expired, standard Unicast DNS (not using LLQs) has no equivalent
519 // mechanism, and TTL expiry is the *only* mechanism by which stale data gets deleted. Because of this,
520 // we currently limit the TTL to ten seconds in such cases where no dynamic cache updating is possible.
521 #define kStaticCacheTTL 10
522 
523 #define DefaultTTLforRRType(X) (((X) == kDNSType_A || (X) == kDNSType_AAAA || (X) == kDNSType_SRV) ? kHostNameTTL : kStandardTTL)
524 #define mDNS_KeepaliveRecord(rr) ((rr)->rrtype == kDNSType_NULL && SameDomainLabel(SecondLabel((rr)->name)->c, (mDNSu8 *)"\x0A_keepalive"))
525 
526 // Number of times keepalives are sent if no ACK is received before waking up the system
527 // this is analogous to net.inet.tcp.keepcnt
528 #define kKeepaliveRetryCount    10
529 // The frequency at which keepalives are retried if no ACK is received
530 #define kKeepaliveRetryInterval 30
531 
532 typedef struct AuthRecord_struct AuthRecord;
533 typedef struct ServiceRecordSet_struct ServiceRecordSet;
534 typedef struct CacheRecord_struct CacheRecord;
535 typedef struct CacheGroup_struct CacheGroup;
536 typedef struct AuthGroup_struct AuthGroup;
537 typedef struct DNSQuestion_struct DNSQuestion;
538 typedef struct ZoneData_struct ZoneData;
539 typedef struct mDNS_struct mDNS;
540 typedef struct mDNS_PlatformSupport_struct mDNS_PlatformSupport;
541 typedef struct NATTraversalInfo_struct NATTraversalInfo;
542 typedef struct ResourceRecord_struct ResourceRecord;
543 
544 // Structure to abstract away the differences between TCP/SSL sockets, and one for UDP sockets
545 // The actual definition of these structures appear in the appropriate platform support code
546 typedef struct TCPListener_struct TCPListener;
547 typedef struct TCPSocket_struct TCPSocket;
548 typedef struct UDPSocket_struct UDPSocket;
549 typedef struct TLSContext_struct TLSContext;
550 typedef struct TLSServerContext_struct TLSServerContext;
551 
552 // ***************************************************************************
553 #if 0
554 #pragma mark -
555 #pragma mark - DNS Message structures
556 #endif
557 
558 #define mDNS_numZones   numQuestions
559 #define mDNS_numPrereqs numAnswers
560 #define mDNS_numUpdates numAuthorities
561 
562 typedef struct
563 {
564     mDNSOpaque16 id;
565     mDNSOpaque16 flags;
566     mDNSu16 numQuestions;
567     mDNSu16 numAnswers;
568     mDNSu16 numAuthorities;
569     mDNSu16 numAdditionals;
570 } DNSMessageHeader;
571 
572 // We can send and receive packets up to 9000 bytes (Ethernet Jumbo Frame size, if that ever becomes widely used)
573 // However, in the normal case we try to limit packets to 1500 bytes so that we don't get IP fragmentation on standard Ethernet
574 // 40 (IPv6 header) + 8 (UDP header) + 12 (DNS message header) + 1440 (DNS message body) = 1500 total
575 #ifndef AbsoluteMaxDNSMessageData
576 #define AbsoluteMaxDNSMessageData 8940
577 #endif
578 #define NormalMaxDNSMessageData 1440
579 typedef struct
580 {
581     DNSMessageHeader h;                     // Note: Size 12 bytes
582     mDNSu8 data[AbsoluteMaxDNSMessageData]; // 40 (IPv6) + 8 (UDP) + 12 (DNS header) + 8940 (data) = 9000
583 } DNSMessage;
584 
585 typedef struct tcpInfo_t
586 {
587     mDNS             *m;
588     TCPSocket        *sock;
589     DNSMessage request;
590     int requestLen;
591     DNSQuestion      *question;   // For queries
592     AuthRecord       *rr;         // For record updates
593     mDNSAddr Addr;
594     mDNSIPPort Port;
595     mDNSIPPort SrcPort;
596     DNSMessage       *reply;
597     mDNSu16 replylen;
598     unsigned long nread;
599     int numReplies;
600 } tcpInfo_t;
601 
602 // ***************************************************************************
603 #if 0
604 #pragma mark -
605 #pragma mark - Other Packet Format Structures
606 #endif
607 
608 typedef packedstruct
609 {
610     mDNSEthAddr dst;
611     mDNSEthAddr src;
612     mDNSOpaque16 ethertype;
613 } EthernetHeader;           // 14 bytes
614 
615 // For clang, suppress -Wunaligned-access, which is triggered by the fact that the type of spa is mDNSv4Addr, which
616 // isn't a packed union, but it's a member of ARP_EthIP, which is packed. Having an unpacked union as a member of a
617 // packed struct is suspicious, but doesn't automatically produce undefined behavior, i.e., the compiler will
618 // produce the correct code to deal with the fact that spa may not be on a 4-byte boundary. If the address of any
619 // of the members of ARP_EthIP is used, then the -Waddress-of-packed-member warning will be triggered, which is a
620 // more useful warning. See <https://github.com/llvm/llvm-project/issues/55520#issuecomment-1128533595>.
621 typedef packedstruct
622 {
623     mDNSOpaque16 hrd;
624     mDNSOpaque16 pro;
625     mDNSu8 hln;
626     mDNSu8 pln;
627     mDNSOpaque16 op;
628     mDNSEthAddr sha;
629 MDNS_CLANG_IGNORE_UNALIGNED_ACCESS_WARNING_BEGIN()
630     mDNSv4Addr spa;
631 MDNS_CLANG_IGNORE_UNALIGNED_ACCESS_WARNING_END()
632     mDNSEthAddr tha;
633     mDNSv4Addr tpa;
634 } ARP_EthIP;                // 28 bytes
635 
636 typedef packedstruct
637 {
638     mDNSu8 vlen;
639     mDNSu8 tos;
640     mDNSOpaque16 totlen;
641     mDNSOpaque16 id;
642     mDNSOpaque16 flagsfrags;
643     mDNSu8 ttl;
644     mDNSu8 protocol;        // Payload type: 0x06 = TCP, 0x11 = UDP
645     mDNSu16 checksum;
646     mDNSv4Addr src;
647     mDNSv4Addr dst;
648 } IPv4Header;               // 20 bytes
649 
650 typedef packedstruct
651 {
652     mDNSu32 vcf;            // Version, Traffic Class, Flow Label
653     mDNSu16 len;            // Payload Length
654     mDNSu8 pro;             // Type of next header: 0x06 = TCP, 0x11 = UDP, 0x3A = ICMPv6
655     mDNSu8 ttl;             // Hop Limit
656     mDNSv6Addr src;
657     mDNSv6Addr dst;
658 } IPv6Header;               // 40 bytes
659 
660 typedef packedstruct
661 {
662     mDNSv6Addr src;
663     mDNSv6Addr dst;
664     mDNSOpaque32 len;
665     mDNSOpaque32 pro;
666 } IPv6PseudoHeader;         // 40 bytes
667 
668 typedef union
669 {
670     mDNSu8 bytes[20];
671     ARP_EthIP arp;
672     IPv4Header v4;
673     IPv6Header v6;
674 } NetworkLayerPacket;
675 
676 typedef packedstruct
677 {
678     mDNSIPPort src;
679     mDNSIPPort dst;
680     mDNSu32 seq;
681     mDNSu32 ack;
682     mDNSu8 offset;
683     mDNSu8 flags;
684     mDNSu16 window;
685     mDNSu16 checksum;
686     mDNSu16 urgent;
687 } TCPHeader;                // 20 bytes; IP protocol type 0x06
688 
689 typedef struct
690 {
691     mDNSInterfaceID IntfId;
692     mDNSu32 seq;
693     mDNSu32 ack;
694     mDNSu16 window;
695 } mDNSTCPInfo;
696 
697 typedef packedstruct
698 {
699     mDNSIPPort src;
700     mDNSIPPort dst;
701     mDNSu16 len;            // Length including UDP header (i.e. minimum value is 8 bytes)
702     mDNSu16 checksum;
703 } UDPHeader;                // 8 bytes; IP protocol type 0x11
704 
705 typedef struct
706 {
707     mDNSu8 type;            // 0x87 == Neighbor Solicitation, 0x88 == Neighbor Advertisement
708     mDNSu8 code;
709     mDNSu16 checksum;
710     mDNSu32 flags_res;      // R/S/O flags and reserved bits
711     mDNSv6Addr target;
712     // Typically 8 bytes of options are also present
713 } IPv6NDP;                  // 24 bytes or more; IP protocol type 0x3A
714 
715 typedef struct
716 {
717     mDNSAddr    ipaddr;
718     char        ethaddr[18];
719 } IPAddressMACMapping;
720 
721 #define NDP_Sol 0x87
722 #define NDP_Adv 0x88
723 
724 #define NDP_Router    0x80
725 #define NDP_Solicited 0x40
726 #define NDP_Override  0x20
727 
728 #define NDP_SrcLL 1
729 #define NDP_TgtLL 2
730 
731 typedef union
732 {
733     mDNSu8 bytes[20];
734     TCPHeader tcp;
735     UDPHeader udp;
736     IPv6NDP ndp;
737 } TransportLayerPacket;
738 
739 typedef packedstruct
740 {
741     mDNSOpaque64 InitiatorCookie;
742     mDNSOpaque64 ResponderCookie;
743     mDNSu8 NextPayload;
744     mDNSu8 Version;
745     mDNSu8 ExchangeType;
746     mDNSu8 Flags;
747     mDNSOpaque32 MessageID;
748     mDNSu32 Length;
749 } IKEHeader;                // 28 bytes
750 
751 // ***************************************************************************
752 #if 0
753 #pragma mark -
754 #pragma mark - Resource Record structures
755 #endif
756 
757 // Authoritative Resource Records:
758 // There are four basic types: Shared, Advisory, Unique, Known Unique
759 
760 // * Shared Resource Records do not have to be unique
761 // -- Shared Resource Records are used for DNS-SD service PTRs
762 // -- It is okay for several hosts to have RRs with the same name but different RDATA
763 // -- We use a random delay on responses to reduce collisions when all the hosts respond to the same query
764 // -- These RRs typically have moderately high TTLs (e.g. one hour)
765 // -- These records are announced on startup and topology changes for the benefit of passive listeners
766 // -- These records send a goodbye packet when deregistering
767 //
768 // * Advisory Resource Records are like Shared Resource Records, except they don't send a goodbye packet
769 //
770 // * Unique Resource Records should be unique among hosts within any given mDNS scope
771 // -- The majority of Resource Records are of this type
772 // -- If two entities on the network have RRs with the same name but different RDATA, this is a conflict
773 // -- Responses may be sent immediately, because only one host should be responding to any particular query
774 // -- These RRs typically have low TTLs (e.g. a few minutes)
775 // -- On startup and after topology changes, a host issues queries to verify uniqueness
776 
777 // * Known Unique Resource Records are treated like Unique Resource Records, except that mDNS does
778 // not have to verify their uniqueness because this is already known by other means (e.g. the RR name
779 // is derived from the host's IP or Ethernet address, which is already known to be a unique identifier).
780 
781 // Summary of properties of different record types:
782 // Probe?    Does this record type send probes before announcing?
783 // Conflict? Does this record type react if we observe an apparent conflict?
784 // Goodbye?  Does this record type send a goodbye packet on departure?
785 //
786 //               Probe? Conflict? Goodbye? Notes
787 // Unregistered                            Should not appear in any list (sanity check value)
788 // Shared         No      No       Yes     e.g. Service PTR record
789 // Deregistering  No      No       Yes     Shared record about to announce its departure and leave the list
790 // Advisory       No      No       No
791 // Unique         Yes     Yes      No      Record intended to be unique -- will probe to verify
792 // Verified       Yes     Yes      No      Record has completed probing, and is verified unique
793 // KnownUnique    No      Yes      No      Record is assumed by other means to be unique
794 
795 // Valid lifecycle of a record:
796 // Unregistered ->                   Shared      -> Deregistering -(goodbye)-> Unregistered
797 // Unregistered ->                   Advisory                               -> Unregistered
798 // Unregistered -> Unique -(probe)-> Verified                               -> Unregistered
799 // Unregistered ->                   KnownUnique                            -> Unregistered
800 
801 // Each Authoritative kDNSRecordType has only one bit set. This makes it easy to quickly see if a record
802 // is one of a particular set of types simply by performing the appropriate bitwise masking operation.
803 
804 // Cache Resource Records (received from the network):
805 // There are four basic types: Answer, Unique Answer, Additional, Unique Additional
806 // Bit 7 (the top bit) of kDNSRecordType is always set for Cache Resource Records; always clear for Authoritative Resource Records
807 // Bit 6 (value 0x40) is set for answer records; clear for authority/additional records
808 // Bit 5 (value 0x20) is set for records received with the kDNSClass_UniqueRRSet
809 
810 typedef enum
811 {
812     kDNSRecordTypeUnregistered     = 0x00,  // Not currently in any list
813     kDNSRecordTypeDeregistering    = 0x01,  // Shared record about to announce its departure and leave the list
814 
815     kDNSRecordTypeUnique           = 0x02,  // Will become a kDNSRecordTypeVerified when probing is complete
816 
817     kDNSRecordTypeAdvisory         = 0x04,  // Like Shared, but no goodbye packet
818     kDNSRecordTypeShared           = 0x08,  // Shared means record name does not have to be unique -- use random delay on responses
819 
820     kDNSRecordTypeVerified         = 0x10,  // Unique means mDNS should check that name is unique (and then send immediate responses)
821     kDNSRecordTypeKnownUnique      = 0x20,  // Known Unique means mDNS can assume name is unique without checking
822                                             // For Dynamic Update records, Known Unique means the record must already exist on the server.
823     kDNSRecordTypeUniqueMask       = (kDNSRecordTypeUnique | kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique),
824     kDNSRecordTypeActiveSharedMask = (kDNSRecordTypeAdvisory         | kDNSRecordTypeShared),
825     kDNSRecordTypeActiveUniqueMask = (kDNSRecordTypeVerified         | kDNSRecordTypeKnownUnique),
826     kDNSRecordTypeActiveMask       = (kDNSRecordTypeActiveSharedMask | kDNSRecordTypeActiveUniqueMask),
827 
828     kDNSRecordTypePacketAdd        = 0x80,  // Received in the Additional  Section of a DNS Response
829     kDNSRecordTypePacketAddUnique  = 0x90,  // Received in the Additional  Section of a DNS Response with kDNSClass_UniqueRRSet set
830     kDNSRecordTypePacketAuth       = 0xA0,  // Received in the Authorities Section of a DNS Response
831     kDNSRecordTypePacketAuthUnique = 0xB0,  // Received in the Authorities Section of a DNS Response with kDNSClass_UniqueRRSet set
832     kDNSRecordTypePacketAns        = 0xC0,  // Received in the Answer      Section of a DNS Response
833     kDNSRecordTypePacketAnsUnique  = 0xD0,  // Received in the Answer      Section of a DNS Response with kDNSClass_UniqueRRSet set
834 
835     kDNSRecordTypePacketNegative   = 0xF0,  // Pseudo-RR generated to cache non-existence results like NXDomain
836 
837     kDNSRecordTypePacketUniqueMask = 0x10   // True for PacketAddUnique, PacketAnsUnique, PacketAuthUnique, kDNSRecordTypePacketNegative
838 } kDNSRecordTypes;
839 
840 typedef packedstruct { mDNSu16 priority; mDNSu16 weight; mDNSIPPort port; domainname target;   } rdataSRV;
841 typedef packedstruct { mDNSu16 preference;                                domainname exchange; } rdataMX;
842 typedef       struct { domainname mbox; domainname txt;                                        } rdataRP;
843 typedef packedstruct { mDNSu16 preference; domainname map822; domainname mapx400;              } rdataPX;
844 
845 typedef packedstruct
846 {
847     domainname mname;
848     domainname rname;
849     mDNSs32 serial;     // Modular counter; increases when zone changes
850     mDNSu32 refresh;    // Time in seconds that a slave waits after successful replication of the database before it attempts replication again
851     mDNSu32 retry;      // Time in seconds that a slave waits after an unsuccessful replication attempt before it attempts replication again
852     mDNSu32 expire;     // Time in seconds that a slave holds on to old data while replication attempts remain unsuccessful
853     mDNSu32 min;        // Nominally the minimum record TTL for this zone, in seconds; also used for negative caching.
854 } rdataSOA;
855 
856 typedef enum
857 {
858     platform_OSX = 1,   // OSX Platform
859     platform_iOS,       // iOS Platform
860     platform_Atv,       // Atv Platform
861     platform_NonApple   // Non-Apple (Windows, POSIX) Platform
862 } Platform_t;
863 
864 // EDNS Option Code registrations are recorded in the "DNS EDNS0 Options" section of
865 // <http://www.iana.org/assignments/dns-parameters>
866 
867 #define kDNSOpt_LLQ   1
868 #define kDNSOpt_Lease 2
869 #define kDNSOpt_NSID  3
870 #define kDNSOpt_Owner 4
871 #define kDNSOpt_Trace 65001  // 65001-65534 Reserved for Local/Experimental Use
872 #define kDNSOpt_TSR   65002
873 
874 typedef struct
875 {
876     mDNSu16 vers;
877     mDNSu16 llqOp;
878     mDNSu16 err;        // Or UDP reply port, in setup request
879     // Note: In the in-memory form, there's typically a two-byte space here, so that the following 64-bit id is word-aligned
880     mDNSOpaque64 id;
881     mDNSu32 llqlease;
882 } LLQOptData;
883 
884 typedef struct
885 {
886     mDNSu8 vers;            // Version number of this Owner OPT record
887     mDNSs8 seq;             // Sleep/wake epoch
888     mDNSEthAddr HMAC;       // Host's primary identifier (e.g. MAC of on-board Ethernet)
889     mDNSEthAddr IMAC;       // Interface's MAC address (if different to primary MAC)
890     mDNSOpaque48 password;  // Optional password
891 } OwnerOptData;
892 
893 typedef struct
894 {
895     mDNSu8    platf;      // Running platform (see enum Platform_t)
896     mDNSu32   mDNSv;      // mDNSResponder Version (DNS_SD_H defined in dns_sd.h)
897 } TracerOptData;
898 
899 typedef struct
900 {
901     mDNSs32 timeStamp;      // TSR record timestamp
902     mDNSu32 hostkeyHash;    // 32-bit Hostkey Hash value
903     mDNSu16 recIndex;       // Index into the DNS packet of the first answer (1-based)
904 } TSROptData;
905 
906 // Note: rdataOPT format may be repeated an arbitrary number of times in a single resource record
907 typedef struct
908 {
909     mDNSu16 opt;
910     mDNSu16 optlen;
911     union { LLQOptData llq; mDNSu32 updatelease; OwnerOptData owner; TracerOptData tracer; TSROptData tsr; } u;
912 } rdataOPT;
913 
914 // Space needed to put OPT records into a packet:
915 // Header         11  bytes (name 1, type 2, class 2, TTL 4, length 2)
916 // LLQ   rdata    18  bytes (opt 2, len 2, vers 2, op 2, err 2, id 8, lease 4)
917 // Lease rdata     8  bytes (opt 2, len 2, lease 4)
918 // Owner rdata 12-24  bytes (opt 2, len 2, owner 8-20)
919 // Trace rdata     9  bytes (opt 2, len 2, platf 1, mDNSv 4)
920 // TSR rdata      14  bytes (opt 2, len 2, time 4, hash 4, index 2)
921 
922 #define DNSOpt_Header_Space                 11
923 #define DNSOpt_LLQData_Space               (4 + 2 + 2 + 2 + 8 + 4)
924 #define DNSOpt_LeaseData_Space             (4 + 4)
925 #define DNSOpt_OwnerData_ID_Space          (4 + 2 + 6)
926 #define DNSOpt_OwnerData_ID_Wake_Space     (4 + 2 + 6 + 6)
927 #define DNSOpt_OwnerData_ID_Wake_PW4_Space (4 + 2 + 6 + 6 + 4)
928 #define DNSOpt_OwnerData_ID_Wake_PW6_Space (4 + 2 + 6 + 6 + 6)
929 #define DNSOpt_TraceData_Space             (4 + 1 + 4)
930 #define DNSOpt_TSRData_Space               (4 + 4 + 4 + 2)
931 
932 #define ValidOwnerLength(X) (   (X) == DNSOpt_OwnerData_ID_Space          - 4 || \
933                                 (X) == DNSOpt_OwnerData_ID_Wake_Space     - 4 || \
934                                 (X) == DNSOpt_OwnerData_ID_Wake_PW4_Space - 4 || \
935                                 (X) == DNSOpt_OwnerData_ID_Wake_PW6_Space - 4    )
936 
937 #define DNSOpt_Owner_Space(A,B) (mDNSSameEthAddress((A),(B)) ? DNSOpt_OwnerData_ID_Space : DNSOpt_OwnerData_ID_Wake_Space)
938 
939 #define DNSOpt_Data_Space(O) (                                  \
940         (O)->opt == kDNSOpt_LLQ   ? DNSOpt_LLQData_Space   :        \
941         (O)->opt == kDNSOpt_Lease ? DNSOpt_LeaseData_Space :        \
942         (O)->opt == kDNSOpt_Trace ? DNSOpt_TraceData_Space :        \
943         (O)->opt == kDNSOpt_TSR   ? DNSOpt_TSRData_Space   :        \
944         (O)->opt == kDNSOpt_Owner ? DNSOpt_Owner_Space(&(O)->u.owner.HMAC, &(O)->u.owner.IMAC) : 0x10000)
945 
946 // NSEC record is defined in RFC 4034.
947 // 16 bit RRTYPE space is split into 256 windows and each window has 256 bits (32 bytes).
948 // If we create a structure for NSEC, it's size would be:
949 //
950 //   256 bytes domainname 'nextname'
951 // + 256 * 34 = 8704 bytes of bitmap data
952 // = 8960 bytes total
953 //
954 // This would be a waste, as types about 256 are not very common. But it would be odd, if we receive
955 // a type above 256 (.US zone had TYPE65534 when this code was written) and not able to handle it.
956 // Hence, we handle any size by not fixing a strucure in place. The following is just a placeholder
957 // and never used anywhere.
958 //
959 #define NSEC_MCAST_WINDOW_SIZE 32
960 typedef struct
961 {
962     domainname *next; //placeholders are uncommented because C89 in Windows requires that a struct has at least a member.
963     char bitmap[32];
964 } rdataNSEC;
965 
966 // StandardAuthRDSize is 264 (256+8), which is large enough to hold a maximum-sized SRV record (6 + 256 bytes)
967 // MaximumRDSize is 8K the absolute maximum we support (at least for now)
968 #define StandardAuthRDSize 264
969 #ifndef MaximumRDSize
970 #define MaximumRDSize 8192
971 #endif
972 
973 // InlineCacheRDSize is 68
974 // Records received from the network with rdata this size or less have their rdata stored right in the CacheRecord object
975 // Records received from the network with rdata larger than this have additional storage allocated for the rdata
976 // A quick unscientific sample from a busy network at Apple with lots of machines revealed this:
977 // 1461 records in cache
978 // 292 were one-byte TXT records
979 // 136 were four-byte A records
980 // 184 were sixteen-byte AAAA records
981 // 780 were various PTR, TXT and SRV records from 12-64 bytes
982 // Only 69 records had rdata bigger than 64 bytes
983 // Note that since CacheRecord object and a CacheGroup object are allocated out of the same pool, it's sensible to
984 // have them both be the same size. Making one smaller without making the other smaller won't actually save any memory.
985 #define InlineCacheRDSize 68
986 
987 // The RDataBody union defines the common rdata types that fit into our 264-byte limit
988 typedef union
989 {
990     mDNSu8 data[StandardAuthRDSize];
991     mDNSv4Addr ipv4;        // For 'A' record
992     domainname name;        // For PTR, NS, CNAME, DNAME
993     UTF8str255 txt;
994     rdataMX mx;
995     mDNSv6Addr ipv6;        // For 'AAAA' record
996     rdataSRV srv;
997     mDNSs32 tsr_value;      // For TSR record
998     rdataOPT opt[2];        // For EDNS0 OPT record; RDataBody may contain multiple variable-length rdataOPT objects packed together
999 } RDataBody;
1000 
1001 // The RDataBody2 union is the same as above, except it includes fields for the larger types like soa, rp, px
1002 typedef union
1003 {
1004     mDNSu8 data[StandardAuthRDSize];
1005     mDNSv4Addr ipv4;        // For 'A' record
1006     domainname name;        // For PTR, NS, CNAME, DNAME
1007     rdataSOA soa;           // This is large; not included in the normal RDataBody definition
1008     UTF8str255 txt;
1009     rdataMX mx;
1010     rdataRP rp;             // This is large; not included in the normal RDataBody definition
1011     rdataPX px;             // This is large; not included in the normal RDataBody definition
1012     mDNSv6Addr ipv6;        // For 'AAAA' record
1013     rdataSRV srv;
1014     mDNSs32 tsr_value;      // For TSR record
1015     rdataOPT opt[2];        // For EDNS0 OPT record; RDataBody may contain multiple variable-length rdataOPT objects packed together
1016 } RDataBody2;
1017 
1018 typedef struct
1019 {
1020     mDNSu16 MaxRDLength;    // Amount of storage allocated for rdata (usually sizeof(RDataBody))
1021     mDNSu16 padding;        // So that RDataBody is aligned on 32-bit boundary
1022     RDataBody u;
1023 } RData;
1024 
1025 // sizeofRDataHeader should be 4 bytes
1026 #define sizeofRDataHeader (sizeof(RData) - sizeof(RDataBody))
1027 
1028 // RData_small is a smaller version of the RData object, used for inline data storage embedded in a CacheRecord_struct
1029 typedef struct
1030 {
1031     mDNSu16 MaxRDLength;    // Storage allocated for data (may be greater than InlineCacheRDSize if additional storage follows this object)
1032     mDNSu16 padding;        // So that data is aligned on 32-bit boundary
1033     mDNSu8 data[InlineCacheRDSize];
1034 } RData_small;
1035 
1036 // Note: Within an mDNSRecordCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
1037 typedef void mDNSRecordCallback (mDNS *const m, AuthRecord *const rr, mStatus result);
1038 
1039 // Note:
1040 // Restrictions: An mDNSRecordUpdateCallback may not make any mDNS API calls.
1041 // The intent of this callback is to allow the client to free memory, if necessary.
1042 // The internal data structures of the mDNS code may not be in a state where mDNS API calls may be made safely.
1043 typedef void mDNSRecordUpdateCallback (mDNS *const m, AuthRecord *const rr, RData *OldRData, mDNSu16 OldRDLen);
1044 
1045 // ***************************************************************************
1046 #if 0
1047 #pragma mark -
1048 #pragma mark - NAT Traversal structures and constants
1049 #endif
1050 
1051 #define NATMAP_MAX_RETRY_INTERVAL    ((mDNSPlatformOneSecond * 60) * 15)    // Max retry interval is 15 minutes
1052 #define NATMAP_MIN_RETRY_INTERVAL     (mDNSPlatformOneSecond * 2)           // Min retry interval is 2 seconds
1053 #define NATMAP_INIT_RETRY             (mDNSPlatformOneSecond / 4)           // start at 250ms w/ exponential decay
1054 #define NATMAP_DEFAULT_LEASE          (60 * 60 * 2)                         // 2 hour lease life in seconds
1055 #define NATMAP_VERS 0
1056 
1057 typedef enum
1058 {
1059     NATOp_AddrRequest    = 0,
1060     NATOp_MapUDP         = 1,
1061     NATOp_MapTCP         = 2,
1062 
1063     NATOp_AddrResponse   = 0x80 | 0,
1064     NATOp_MapUDPResponse = 0x80 | 1,
1065     NATOp_MapTCPResponse = 0x80 | 2,
1066 } NATOp_t;
1067 
1068 enum
1069 {
1070     NATErr_None    = 0,
1071     NATErr_Vers    = 1,
1072     NATErr_Refused = 2,
1073     NATErr_NetFail = 3,
1074     NATErr_Res     = 4,
1075     NATErr_Opcode  = 5
1076 };
1077 
1078 typedef mDNSu16 NATErr_t;
1079 
1080 typedef struct // packedstruct unnecessary
1081 {
1082     mDNSu8 vers;
1083     mDNSu8 opcode;
1084 } NATAddrRequest;
1085 
1086 typedef packedstruct
1087 {
1088     mDNSu8 vers;
1089     mDNSu8 opcode;
1090     mDNSu16 err;
1091     mDNSu32 upseconds;          // Time since last NAT engine reboot, in seconds
1092     mDNSv4Addr ExtAddr;
1093 } NATAddrReply;
1094 
1095 typedef packedstruct
1096 {
1097     mDNSu8 vers;
1098     mDNSu8 opcode;
1099     mDNSOpaque16 unused;
1100     mDNSIPPort intport;
1101     mDNSIPPort extport;
1102     mDNSu32 NATReq_lease;
1103 } NATPortMapRequest;
1104 
1105 typedef packedstruct
1106 {
1107     mDNSu8 vers;
1108     mDNSu8 opcode;
1109     mDNSu16 err;
1110     mDNSu32 upseconds;          // Time since last NAT engine reboot, in seconds
1111     mDNSIPPort intport;
1112     mDNSIPPort extport;
1113     mDNSu32 NATRep_lease;
1114 } NATPortMapReply;
1115 
1116 // PCP Support for IPv4 mappings
1117 
1118 #define PCP_VERS 0x02
1119 #define PCP_WAITSECS_AFTER_EPOCH_INVALID 5
1120 
1121 typedef enum
1122 {
1123     PCPOp_Announce = 0,
1124     PCPOp_Map      = 1
1125 } PCPOp_t;
1126 
1127 typedef enum
1128 {
1129     PCPProto_All = 0,
1130     PCPProto_TCP = 6,
1131     PCPProto_UDP = 17
1132 } PCPProto_t;
1133 
1134 typedef enum
1135 {
1136     PCPResult_Success         = 0,
1137     PCPResult_UnsuppVersion   = 1,
1138     PCPResult_NotAuthorized   = 2,
1139     PCPResult_MalformedReq    = 3,
1140     PCPResult_UnsuppOpcode    = 4,
1141     PCPResult_UnsuppOption    = 5,
1142     PCPResult_MalformedOption = 6,
1143     PCPResult_NetworkFailure  = 7,
1144     PCPResult_NoResources     = 8,
1145     PCPResult_UnsuppProtocol  = 9,
1146     PCPResult_UserExQuota     = 10,
1147     PCPResult_CantProvideExt  = 11,
1148     PCPResult_AddrMismatch    = 12,
1149     PCPResult_ExcesRemotePeer = 13
1150 } PCPResult_t;
1151 
1152 typedef struct
1153 {
1154     mDNSu8       version;
1155     mDNSu8       opCode;
1156     mDNSOpaque16 reserved;
1157     mDNSu32      lifetime;
1158     mDNSv6Addr   clientAddr;
1159     mDNSu32      nonce[3];
1160     mDNSu8       protocol;
1161     mDNSu8       reservedMapOp[3];
1162     mDNSIPPort   intPort;
1163     mDNSIPPort   extPort;
1164     mDNSv6Addr   extAddress;
1165 } PCPMapRequest;
1166 
1167 typedef struct
1168 {
1169     mDNSu8     version;
1170     mDNSu8     opCode;
1171     mDNSu8     reserved;
1172     mDNSu8     result;
1173     mDNSu32    lifetime;
1174     mDNSu32    epoch;
1175     mDNSu32    clientAddrParts[3];
1176     mDNSu32    nonce[3];
1177     mDNSu8     protocol;
1178     mDNSu8     reservedMapOp[3];
1179     mDNSIPPort intPort;
1180     mDNSIPPort extPort;
1181     mDNSv6Addr extAddress;
1182 } PCPMapReply;
1183 
1184 // LNT Support
1185 
1186 typedef enum
1187 {
1188     LNTDiscoveryOp      = 1,
1189     LNTExternalAddrOp   = 2,
1190     LNTPortMapOp        = 3,
1191     LNTPortMapDeleteOp  = 4
1192 } LNTOp_t;
1193 
1194 #define LNT_MAXBUFSIZE 8192
1195 typedef struct tcpLNTInfo_struct tcpLNTInfo;
1196 struct tcpLNTInfo_struct
1197 {
1198     tcpLNTInfo       *next;
1199     mDNS             *m;
1200     NATTraversalInfo *parentNATInfo;    // pointer back to the parent NATTraversalInfo
1201     TCPSocket        *sock;
1202     LNTOp_t op;                         // operation performed using this connection
1203     mDNSAddr Address;                   // router address
1204     mDNSIPPort Port;                    // router port
1205     mDNSu8           *Request;          // xml request to router
1206     int requestLen;
1207     mDNSu8           *Reply;            // xml reply from router
1208     int replyLen;
1209     unsigned long nread;                // number of bytes read so far
1210     int retries;                        // number of times we've tried to do this port mapping
1211 };
1212 
1213 typedef void (*NATTraversalClientCallback)(mDNS *m, NATTraversalInfo *n);
1214 
1215 // if m->timenow <  ExpiryTime then we have an active mapping, and we'll renew halfway to expiry
1216 // if m->timenow >= ExpiryTime then our mapping has expired, and we're trying to create one
1217 
1218 typedef enum
1219 {
1220     NATTProtocolNone    = 0,
1221     NATTProtocolNATPMP  = 1,
1222     NATTProtocolUPNPIGD = 2,
1223     NATTProtocolPCP     = 3,
1224 } NATTProtocol;
1225 
1226 struct NATTraversalInfo_struct
1227 {
1228     // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
1229     NATTraversalInfo           *next;
1230 
1231     mDNSs32 ExpiryTime;                             // Time this mapping expires, or zero if no mapping
1232     mDNSs32 retryInterval;                          // Current interval, between last packet we sent and the next one
1233     mDNSs32 retryPortMap;                           // If Protocol is nonzero, time to send our next mapping packet
1234     mStatus NewResult;                              // New error code; will be copied to Result just prior to invoking callback
1235     NATTProtocol lastSuccessfulProtocol;            // To send correct deletion request & update non-PCP external address operations
1236     mDNSBool sentNATPMP;                            // Whether we just sent a NAT-PMP packet, so we won't send another if
1237                                                     //    we receive another NAT-PMP "Unsupported Version" packet
1238 
1239 #ifdef _LEGACY_NAT_TRAVERSAL_
1240     tcpLNTInfo tcpInfo;                             // Legacy NAT traversal (UPnP) TCP connection
1241 #endif
1242 
1243     // Result fields: When the callback is invoked these fields contain the answers the client is looking for
1244     // When the callback is invoked ExternalPort is *usually* set to be the same the same as RequestedPort, except:
1245     // (a) When we're behind a NAT gateway with port mapping disabled, ExternalPort is reported as zero to
1246     //     indicate that we don't currently have a working mapping (but RequestedPort retains the external port
1247     //     we'd like to get, the next time we meet an accomodating NAT gateway willing to give us one).
1248     // (b) When we have a routable non-RFC1918 address, we don't *need* a port mapping, so ExternalPort
1249     //     is reported as the same as our InternalPort, since that is effectively our externally-visible port too.
1250     //     Again, RequestedPort retains the external port we'd like to get the next time we find ourself behind a NAT gateway.
1251     // To improve stability of port mappings, RequestedPort is updated any time we get a successful
1252     // mapping response from the PCP, NAT-PMP or UPnP gateway. For example, if we ask for port 80, and
1253     // get assigned port 81, then thereafter we'll contine asking for port 81.
1254     mDNSInterfaceID InterfaceID;
1255     mDNSv4Addr ExternalAddress;                     // Initially set to onesIPv4Addr, until first callback
1256     mDNSv4Addr NewAddress;                          // May be updated with actual value assigned by gateway
1257     mDNSIPPort ExternalPort;
1258     mDNSu32 Lifetime;
1259     mStatus Result;
1260 
1261     // Client API fields: The client must set up these fields *before* making any NAT traversal API calls
1262     mDNSu8 Protocol;                                // NATOp_MapUDP or NATOp_MapTCP, or zero if just requesting the external IP address
1263     mDNSIPPort IntPort;                             // Client's internal port number (doesn't change)
1264     mDNSIPPort RequestedPort;                       // Requested external port; may be updated with actual value assigned by gateway
1265     mDNSu32 NATLease;                               // Requested lifetime in seconds (doesn't change)
1266     NATTraversalClientCallback clientCallback;
1267     void                       *clientContext;
1268 };
1269 
1270 // ***************************************************************************
1271 #if 0
1272 #pragma mark -
1273 #pragma mark - DNSServer & McastResolver structures and constants
1274 #endif
1275 
1276 enum
1277 {
1278     McastResolver_FlagDelete = 1,
1279     McastResolver_FlagNew    = 2
1280 };
1281 
1282 typedef struct McastResolver
1283 {
1284     struct McastResolver *next;
1285     mDNSInterfaceID interface;
1286     mDNSu32 flags;              // Set when we're planning to delete this from the list
1287     domainname domain;
1288     mDNSu32 timeout;            // timeout value for questions
1289 } McastResolver;
1290 
1291 enum {
1292     Mortality_Mortal      = 0,          // This cache record can expire and get purged
1293     Mortality_Immortal    = 1,          // Allow this record to remain in the cache indefinitely
1294     Mortality_Ghost       = 2           // An immortal record that has expired and can linger in the cache
1295 };
1296 typedef mDNSu8 MortalityState;
1297 
1298 // ScopeType values for DNSServer matching
1299 typedef enum
1300 {
1301     kScopeNone         = 0,        // DNS server used by unscoped questions
1302     kScopeInterfaceID  = 1,        // Scoped DNS server used only by scoped questions
1303     kScopeServiceID    = 2         // Service specific DNS server used only by questions
1304                                    // have a matching serviceID
1305 } ScopeType;
1306 
1307 #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
1308 typedef mDNSu32 DNSServerFlags;
1309 #define DNSServerFlag_Delete        (1U << 0)
1310 #if MDNSRESPONDER_SUPPORTS(APPLE, SYMPTOMS)
1311 #define DNSServerFlag_Unreachable   (1U << 1)
1312 #endif
1313 
1314 typedef struct DNSServer
1315 {
1316     struct DNSServer *next;
1317     mDNSInterfaceID interface;  // DNS requests should be sent on this interface
1318     mDNSs32 serviceID;          // ServiceID from DNS configuration.
1319     mDNSAddr addr;              // DNS server's IP address.
1320     DNSServerFlags flags;       // Set when we're planning to delete this from the list.
1321     mDNSs32 penaltyTime;        // amount of time this server is penalized
1322     ScopeType scopeType;        // See the ScopeType enum above
1323     mDNSu32 timeout;            // timeout value for questions
1324     mDNSu32 resGroupID;         // ID of the resolver group that contains this DNSServer
1325     mDNSIPPort port;            // DNS server's port number.
1326     mDNSBool usableA;           // True if A query results are usable over the interface, i.e., interface has IPv4.
1327     mDNSBool usableAAAA;        // True if AAAA query results are usable over the interface, i.e., interface has IPv6.
1328     mDNSBool isCell;            // True if the interface to this server is cellular.
1329     mDNSBool isExpensive;       // True if the interface to this server is expensive.
1330     mDNSBool isConstrained;     // True if the interface to this server is constrained.
1331     mDNSBool isCLAT46;          // True if the interface to this server supports CLAT46.
1332     domainname domain;          // name->server matching for "split dns"
1333 } DNSServer;
1334 #endif
1335 
1336 struct ResourceRecord_struct
1337 {
1338     mDNSu8 RecordType;                  // See kDNSRecordTypes enum.
1339     mDNSu8 rcode;                       // If the record was received via DNS, specifies the RCODE of the response message.
1340     MortalityState mortality;           // Mortality of this resource record (See MortalityState enum)
1341     mDNSu16 rrtype;                     // See DNS_TypeValues enum.
1342     mDNSu16 rrclass;                    // See DNS_ClassValues enum.
1343     mDNSu32 rroriginalttl;              // In seconds
1344     mDNSu16 rdlength;                   // Size of the raw rdata, in bytes, in the on-the-wire format
1345                                         // (In-memory storage may be larger, for structures containing 'holes', like SOA)
1346     mDNSu16 rdestimate;                 // Upper bound on on-the-wire size of rdata after name compression
1347     mDNSu32 namehash;                   // Name-based (i.e. case-insensitive) hash of name
1348     mDNSu32 rdatahash;                  // For rdata containing domain name (e.g. PTR, SRV, CNAME etc.), case-insensitive name hash
1349                                         // else, for all other rdata, 32-bit hash of the raw rdata
1350                                         // Note: This requirement is important. Various routines like AddAdditionalsToResponseList(),
1351                                         // ReconfirmAntecedents(), etc., use rdatahash as a pre-flight check to see
1352                                         // whether it's worth doing a full SameDomainName() call. If the rdatahash
1353                                         // is not a correct case-insensitive name hash, they'll get false negatives.
1354     // Grouping pointers together at the end of the structure improves the memory layout efficiency
1355     mDNSInterfaceID InterfaceID;        // Set if this RR is specific to one interface
1356                                         // For records received off the wire, InterfaceID is *always* set to the receiving interface
1357                                         // For our authoritative records, InterfaceID is usually zero, except for those few records
1358                                         // that are interface-specific (e.g. address records, especially linklocal addresses)
1359     const domainname *name;
1360     RData           *rdata;             // Pointer to storage for this rdata
1361 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
1362     mdns_cache_metadata_t metadata;
1363 #else
1364     DNSServer       *rDNSServer;        // Unicast DNS server authoritative for this entry; null for multicast
1365 #endif
1366 
1367 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
1368     dnssec_obj_resource_record_member_t dnssec;     // DNSSEC-related information for the current RR.
1369 #endif
1370 };
1371 
1372 
1373 // Unless otherwise noted, states may apply to either independent record registrations or service registrations
1374 typedef enum
1375 {
1376     regState_Zero              = 0,
1377     regState_Pending           = 1,     // update sent, reply not received
1378     regState_Registered        = 2,     // update sent, reply received
1379     regState_DeregPending      = 3,     // dereg sent, reply not received
1380     regState_Unregistered      = 4,     // not in any list
1381     regState_Refresh           = 5,     // outstanding refresh (or target change) message
1382     regState_NATMap            = 6,     // establishing NAT port mapping
1383     regState_UpdatePending     = 7,     // update in flight as result of mDNS_Update call
1384     regState_NoTarget          = 8,     // SRV Record registration pending registration of hostname
1385     regState_NATError          = 9     // unable to complete NAT traversal
1386 } regState_t;
1387 
1388 enum
1389 {
1390     Target_Manual = 0,
1391     Target_AutoHost = 1,
1392     Target_AutoHostAndNATMAP = 2
1393 };
1394 
1395 typedef enum
1396 {
1397     mergeState_Zero = 0,
1398     mergeState_DontMerge = 1  // Set on fatal error conditions to disable merging
1399 } mergeState_t;
1400 
1401 #define AUTH_GROUP_NAME_SIZE    128
1402 struct AuthGroup_struct             // Header object for a list of AuthRecords with the same name
1403 {
1404     AuthGroup      *next;               // Next AuthGroup object in this hash table bucket
1405     mDNSu32 namehash;                   // Name-based (i.e. case insensitive) hash of name
1406     AuthRecord     *members;            // List of CacheRecords with this same name
1407     AuthRecord    **rrauth_tail;        // Tail end of that list
1408     domainname     *name;               // Common name for all AuthRecords in this list
1409     AuthRecord     *NewLocalOnlyRecords;
1410     mDNSu8 namestorage[AUTH_GROUP_NAME_SIZE];
1411 };
1412 
1413 #ifndef AUTH_HASH_SLOTS
1414 #define AUTH_HASH_SLOTS 499
1415 #endif
1416 #define FORALL_AUTHRECORDS(SLOT,AG,AR)                              \
1417     for ((SLOT) = 0; (SLOT) < AUTH_HASH_SLOTS; (SLOT)++)                                                                     \
1418         for ((AG)=m->rrauth.rrauth_hash[(SLOT)]; (AG); (AG)=(AG)->next)                                                                         \
1419             for ((AR) = (AG)->members; (AR); (AR)=(AR)->next)
1420 
1421 typedef union AuthEntity_union AuthEntity;
1422 union AuthEntity_union { AuthEntity *next; AuthGroup ag; };
1423 typedef struct {
1424     mDNSu32 rrauth_size;                // Total number of available auth entries
1425     mDNSu32 rrauth_totalused;           // Number of auth entries currently occupied
1426     mDNSu32 rrauth_report;
1427     mDNSu8 rrauth_lock;                 // For debugging: Set at times when these lists may not be modified
1428     AuthEntity *rrauth_free;
1429     AuthGroup *rrauth_hash[AUTH_HASH_SLOTS];
1430 }AuthHash;
1431 
1432 // AuthRecordAny includes mDNSInterface_Any and interface specific auth records.
1433 typedef enum
1434 {
1435     AuthRecordAny,              // registered for *Any, NOT including P2P interfaces
1436     AuthRecordAnyIncludeP2P,    // registered for *Any, including P2P interfaces
1437     AuthRecordAnyIncludeAWDL,   // registered for *Any, including AWDL interface
1438     AuthRecordAnyIncludeAWDLandP2P, // registered for *Any, including AWDL and P2P interfaces
1439     AuthRecordLocalOnly,
1440     AuthRecordP2P,              // discovered over D2D/P2P framework
1441 } AuthRecType;
1442 
1443 #define AuthRecordIncludesAWDL(AR) \
1444     (((AR)->ARType == AuthRecordAnyIncludeAWDL) || ((AR)->ARType == AuthRecordAnyIncludeAWDLandP2P))
1445 
1446 typedef enum
1447 {
1448     AuthFlagsWakeOnly = 0x1     // WakeOnly service
1449 } AuthRecordFlags;
1450 
1451 struct AuthRecord_struct
1452 {
1453     // For examples of how to set up this structure for use in mDNS_Register(),
1454     // see mDNS_AdvertiseInterface() or mDNS_RegisterService().
1455     // Basically, resrec and persistent metadata need to be set up before calling mDNS_Register().
1456     // mDNS_SetupResourceRecord() is avaliable as a helper routine to set up most fields to sensible default values for you
1457 
1458     AuthRecord     *next;               // Next in list; first element of structure for efficiency reasons
1459     // Field Group 1: Common ResourceRecord fields
1460     ResourceRecord resrec;              // 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit (now 44/64)
1461 
1462     // Field Group 2: Persistent metadata for Authoritative Records
1463     AuthRecord     *Additional1;        // Recommended additional record to include in response (e.g. SRV for PTR record)
1464     AuthRecord     *Additional2;        // Another additional (e.g. TXT for PTR record)
1465     AuthRecord     *DependentOn;        // This record depends on another for its uniqueness checking
1466     uintptr_t      RRSet;               // This unique record is part of an RRSet
1467     mDNSRecordCallback *RecordCallback; // Callback function to call for state changes, and to free memory asynchronously on deregistration
1468     void           *RecordContext;      // Context parameter for the callback function
1469     mDNSu8 AutoTarget;                  // Set if the target of this record (PTR, CNAME, SRV, etc.) is our host name
1470     mDNSu8 AllowRemoteQuery;            // Set if we allow hosts not on the local link to query this record
1471     mDNSu8 ForceMCast;                  // Set by client to advertise solely via multicast, even for apparently unicast names
1472     mDNSu8 AuthFlags;
1473 
1474     OwnerOptData WakeUp;                // WakeUp.HMAC.l[0] nonzero indicates that this is a Sleep Proxy record
1475     mDNSAddr AddressProxy;              // For reverse-mapping Sleep Proxy PTR records, address in question
1476     mDNSs32 TimeRcvd;                   // In platform time units
1477     mDNSs32 TimeExpire;                 // In platform time units
1478     AuthRecType ARType;                 // LocalOnly, P2P or Normal ?
1479     mDNSs32 KATimeExpire;               // In platform time units: time to send keepalive packet for the proxy record
1480 
1481     // Field Group 3: Transient state for Authoritative Records
1482     mDNSs32 ProbingConflictCount;       // Number of conflicting records observed during probing.
1483     mDNSs32 LastConflictPktNum;         // Number of the last received packet that caused a probing conflict.
1484     mDNSu8 Acknowledged;                // Set if we've given the success callback to the client
1485     mDNSu8 ProbeRestartCount;           // Number of times we have restarted probing
1486     mDNSu8 ProbeCount;                  // Number of probes remaining before this record is valid (kDNSRecordTypeUnique)
1487     mDNSu8 AnnounceCount;               // Number of announcements remaining (kDNSRecordTypeShared)
1488     mDNSu8 RequireGoodbye;              // Set if this RR has been announced on the wire and will require a goodbye packet
1489     mDNSu8 AnsweredLocalQ;              // Set if this AuthRecord has been delivered to any local question (LocalOnly or mDNSInterface_Any)
1490     mDNSu8 IncludeInProbe;              // Set if this RR is being put into a probe right now
1491     mDNSu8 ImmedUnicast;                // Set if we may send our response directly via unicast to the requester
1492     mDNSInterfaceID SendNSECNow;        // Set if we need to generate associated NSEC data for this rrname
1493     mDNSInterfaceID ImmedAnswer;        // Someone on this interface issued a query we need to answer (all-ones for all interfaces)
1494 #if defined(MDNS_LOG_ANSWER_SUPPRESSION_TIMES) && MDNS_LOG_ANSWER_SUPPRESSION_TIMES
1495     mDNSs32 ImmedAnswerMarkTime;
1496 #endif
1497     mDNSInterfaceID ImmedAdditional;    // Hint that we might want to also send this record, just to be helpful
1498     mDNSInterfaceID SendRNow;           // The interface this query is being sent on right now
1499     mDNSv4Addr v4Requester;             // Recent v4 query for this record, or all-ones if more than one recent query
1500     mDNSv6Addr v6Requester;             // Recent v6 query for this record, or all-ones if more than one recent query
1501     AuthRecord     *NextResponse;       // Link to the next element in the chain of responses to generate
1502     const mDNSu8   *NR_AnswerTo;        // Set if this record was selected by virtue of being a direct answer to a question
1503     AuthRecord     *NR_AdditionalTo;    // Set if this record was selected by virtue of being additional to another
1504     mDNSs32 ThisAPInterval;             // In platform time units: Current interval for announce/probe
1505     mDNSs32 LastAPTime;                 // In platform time units: Last time we sent announcement/probe
1506     mDNSs32 LastMCTime;                 // Last time we multicast this record (used to guard against packet-storm attacks)
1507     mDNSInterfaceID LastMCInterface;    // Interface this record was multicast on at the time LastMCTime was recorded
1508     RData          *NewRData;           // Set if we are updating this record with new rdata
1509     mDNSu16 newrdlength;                // ... and the length of the new RData
1510     mDNSRecordUpdateCallback *UpdateCallback;
1511     mDNSu32 UpdateCredits;              // Token-bucket rate limiting of excessive updates
1512     mDNSs32 NextUpdateCredit;           // Time next token is added to bucket
1513     mDNSs32 UpdateBlocked;              // Set if update delaying is in effect
1514     mDNSs32 TentativeSetTime;           // In platform time units
1515 
1516     // Field Group 4: Transient uDNS state for Authoritative Records
1517     regState_t state;           // Maybe combine this with resrec.RecordType state? Right now it's ambiguous and confusing.
1518                                 // e.g. rr->resrec.RecordType can be kDNSRecordTypeUnregistered,
1519                                 // and rr->state can be regState_Unregistered
1520                                 // What if we find one of those statements is true and the other false? What does that mean?
1521     mDNSBool uselease;          // dynamic update contains (should contain) lease option
1522     mDNSs32 expire;             // In platform time units: expiration of lease (-1 for static)
1523     mDNSBool Private;           // If zone is private, DNS updates may have to be encrypted to prevent eavesdropping
1524     mDNSOpaque16 updateid;      // Identifier to match update request and response -- also used when transferring records to Sleep Proxy
1525     mDNSOpaque64 updateIntID;   // Interface IDs (one bit per interface index)to which updates have been sent
1526     const domainname *zone;     // the zone that is updated
1527     ZoneData  *nta;
1528     struct tcpInfo_t *tcp;
1529     NATTraversalInfo NATinfo;
1530     mDNSBool SRVChanged;       // temporarily deregistered service because its SRV target or port changed
1531     mergeState_t mState;       // Unicast Record Registrations merge state
1532     mDNSu8 refreshCount;        // Number of refreshes to the server
1533     mStatus updateError;        // Record update resulted in Error ?
1534 
1535     // uDNS_UpdateRecord support fields
1536     // Do we really need all these in *addition* to NewRData and newrdlength above?
1537     void *UpdateContext;    // Context parameter for the update callback function
1538     mDNSu16 OrigRDLen;      // previously registered, being deleted
1539     mDNSu16 InFlightRDLen;  // currently being registered
1540     mDNSu16 QueuedRDLen;    // pending operation (re-transmitting if necessary) THEN register the queued update
1541     RData *OrigRData;
1542     RData *InFlightRData;
1543     RData *QueuedRData;
1544 
1545     mDNSs32 TimeRegistered; // The time when the record is registered in platform time units.
1546 
1547     // Field Group 5: Large data objects go at the end
1548     domainname namestorage;
1549     RData rdatastorage;                 // Normally the storage is right here, except for oversized records
1550     // rdatastorage MUST be the last thing in the structure -- when using oversized AuthRecords, extra bytes
1551     // are appended after the end of the AuthRecord, logically augmenting the size of the rdatastorage
1552     // DO NOT ADD ANY MORE FIELDS HERE
1553 };
1554 
1555 // IsLocalDomain alone is not sufficient to determine that a record is mDNS or uDNS. By default domain names within
1556 // the "local" pseudo-TLD (and within the IPv4 and IPv6 link-local reverse mapping domains) are automatically treated
1557 // as mDNS records, but it is also possible to force any record (even those not within one of the inherently local
1558 // domains) to be handled as an mDNS record by setting the ForceMCast flag, or by setting a non-zero InterfaceID.
1559 // For example, the reverse-mapping PTR record created in AdvertiseInterface sets the ForceMCast flag, since it points to
1560 // a dot-local hostname, and therefore it would make no sense to register this record with a wide-area Unicast DNS server.
1561 // The same applies to Sleep Proxy records, which we will answer for when queried via mDNS, but we never want to try
1562 // to register them with a wide-area Unicast DNS server -- and we probably don't have the required credentials anyway.
1563 // Currently we have no concept of a wide-area uDNS record scoped to a particular interface, so if the InterfaceID is
1564 // nonzero we treat this the same as ForceMCast.
1565 // Note: Question_uDNS(Q) is used in *only* one place -- on entry to mDNS_StartQuery_internal, to decide whether to set TargetQID.
1566 // Everywhere else in the code, the determination of whether a question is unicast is made by checking to see if TargetQID is nonzero.
1567 #define AuthRecord_uDNS(R) ((R)->resrec.InterfaceID == mDNSInterface_Any && !(R)->ForceMCast && !IsLocalDomain((R)->resrec.name))
1568 #define Question_uDNS(Q)   ((Q)->IsUnicastDotLocal || (Q)->ProxyQuestion || \
1569                             ((Q)->InterfaceID != mDNSInterface_LocalOnly && (Q)->InterfaceID != mDNSInterface_P2P && (Q)->InterfaceID != mDNSInterface_BLE && !(Q)->ForceMCast && !IsLocalDomain(&(Q)->qname)))
1570 
1571 // AuthRecordLocalOnly records are registered using mDNSInterface_LocalOnly and
1572 // AuthRecordP2P records are created by D2DServiceFound events.  Both record types are kept on the same list.
1573 #define RRLocalOnly(rr) ((rr)->ARType == AuthRecordLocalOnly || (rr)->ARType == AuthRecordP2P)
1574 
1575 // All other auth records, not including those defined as RRLocalOnly().
1576 #define RRAny(rr) ((rr)->ARType == AuthRecordAny || (rr)->ARType == AuthRecordAnyIncludeP2P || (rr)->ARType == AuthRecordAnyIncludeAWDL || (rr)->ARType == AuthRecordAnyIncludeAWDLandP2P)
1577 
1578 // Normally we always lookup the cache and /etc/hosts before sending the query on the wire. For single label
1579 // queries (A and AAAA) that are unqualified (indicated by AppendSearchDomains), we want to append search
1580 // domains before we try them as such
1581 #define ApplySearchDomainsFirst(q) ((q)->AppendSearchDomains && (CountLabels(&((q)->qname))) == 1)
1582 
1583 // Wrapper struct for Auth Records for higher-level code that cannot use the AuthRecord's ->next pointer field
1584 typedef struct ARListElem
1585 {
1586     struct ARListElem *next;
1587     AuthRecord ar;          // Note: Must be last element of structure, to accomodate oversized AuthRecords
1588 } ARListElem;
1589 
1590 #if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
1591 // This enum is used by state dump to determine whether the cache record should be redacted when printing the state.
1592 MDNS_CLOSED_ENUM(mDNSCRLogPrivacyLevel, mDNSu8,
1593     // The state change flow:
1594     // mDNSCRLogPrivacyLevel_Default -> mDNSCRLogPrivacyLevel_Private -> mDNSCRLogPrivacyLevel_Public
1595     //            |                                                         ^
1596     //            ----------------------------------------------------------|
1597     mDNSCRLogPrivacyLevel_Default = 0,  // No state has been set, unredacted.
1598     mDNSCRLogPrivacyLevel_Private = 1,  // Private state, redacted.
1599     mDNSCRLogPrivacyLevel_Public = 2    // Public state, unredacted.
1600 );
1601 
1602 #define PRIVATE_DOMAIN_NAME         ((const domainname *)"\x7" "private" "\x6" "domain" "\x4" "name" "\x7" "invalid")
1603 #define PRIVATE_RECORD_DESCRIPTION  "<private record description>"
1604 
1605 #endif // MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
1606 
1607 struct CacheRecord_struct
1608 {
1609     CacheRecord    *next;               // Next in list; first element of structure for efficiency reasons
1610     ResourceRecord resrec;              // 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit (now 44/64)
1611 
1612     // Transient state for Cache Records
1613     CacheRecord    *NextInKAList;       // Link to the next element in the chain of known answers to send
1614     mDNSs32 TimeRcvd;                   // In platform time units
1615     mDNSs32 DelayDelivery;              // Set if we want to defer delivery of this answer to local clients
1616     mDNSs32 NextRequiredQuery;          // In platform time units
1617 #if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_ANALYTICS)
1618     mDNSs32 LastCachedAnswerTime;       // Last time this record was used as an answer from the cache (before a query)
1619                                         // In platform time units
1620 #else
1621     // Extra four bytes here (on 64bit)
1622 #endif
1623     DNSQuestion    *CRActiveQuestion;   // Points to an active question referencing this answer. Can never point to a NewQuestion.
1624     mDNSs32 LastUnansweredTime;         // In platform time units; last time we incremented UnansweredQueries
1625     mDNSu8  UnansweredQueries;          // Number of times we've issued a query for this record without getting an answer
1626 
1627 #if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH) || MDNSRESPONDER_SUPPORTS(APPLE, DNS_PUSH)
1628     mDNSBool DNSPushSubscribed;         // Indicate whether the cached record has an active DNS push subscription. If
1629                                         // true, the record never expires.
1630 #endif
1631 
1632     mDNSOpaque16 responseFlags;         // Second 16 bit in the DNS response
1633     CacheRecord    *NextInCFList;       // Set if this is in the list of records we just received with the cache flush bit set
1634     CacheRecord    *soa;                // SOA record to return for proxy questions
1635 
1636 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
1637     mDNSBool ineligibleForRecycling;    // If this cached record can be recycled when there is not enough cache space.
1638 #endif
1639 #if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
1640     mDNSCRLogPrivacyLevel PrivacyLevel; // The privacy level of the cache record.
1641 #endif
1642 #if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_ASSIST)
1643     mDNSBool unicastAssistSent;         // Unicast Assist sent state of this record.
1644 #endif
1645 
1646     mDNSAddr sourceAddress;             // node from which we received this record
1647     // Size to here is 76 bytes when compiling 32-bit; 104 bytes when compiling 64-bit (now 160 bytes for 64-bit)
1648     RData_small smallrdatastorage;      // Storage for small records is right here (4 bytes header + 68 bytes data = 72 bytes)
1649 };
1650 
1651 // Should match the CacheGroup_struct members, except namestorage[].  Only used to calculate
1652 // the size of the namestorage array in CacheGroup_struct so that sizeof(CacheGroup) == sizeof(CacheRecord)
1653 struct CacheGroup_base
1654 {
1655     CacheGroup     *next;
1656     mDNSu32         namehash;
1657     CacheRecord    *members;
1658     CacheRecord   **rrcache_tail;
1659     domainname     *name;
1660 };
1661 
1662 struct CacheGroup_struct                // Header object for a list of CacheRecords with the same name
1663 {
1664     CacheGroup     *next;               // Next CacheGroup object in this hash table bucket
1665     mDNSu32         namehash;           // Name-based (i.e. case insensitive) hash of name
1666     CacheRecord    *members;            // List of CacheRecords with this same name
1667     CacheRecord   **rrcache_tail;       // Tail end of that list
1668     domainname     *name;               // Common name for all CacheRecords in this list
1669     mDNSu8 namestorage[sizeof(CacheRecord) - sizeof(struct CacheGroup_base)];  // match sizeof(CacheRecord)
1670 };
1671 
1672 // Storage sufficient to hold either a CacheGroup header or a CacheRecord
1673 // -- for best efficiency (to avoid wasted unused storage) they should be the same size
1674 typedef union CacheEntity_union CacheEntity;
1675 union CacheEntity_union { CacheEntity *next; CacheGroup cg; CacheRecord cr; };
1676 
1677 typedef struct
1678 {
1679     CacheRecord r;
1680     mDNSu8 _extradata[MaximumRDSize-InlineCacheRDSize];     // Glue on the necessary number of extra bytes
1681     domainname namestorage;                                 // Needs to go *after* the extra rdata bytes
1682 } LargeCacheRecord;
1683 
1684 typedef struct HostnameInfo
1685 {
1686     struct HostnameInfo *next;
1687     NATTraversalInfo natinfo;
1688     domainname fqdn;
1689     AuthRecord arv4;                          // registered IPv4 address record
1690     AuthRecord arv6;                          // registered IPv6 address record
1691     mDNSRecordCallback *StatusCallback;       // callback to deliver success or error code to client layer
1692     const void *StatusContext;                // Client Context
1693 } HostnameInfo;
1694 
1695 typedef struct ExtraResourceRecord_struct ExtraResourceRecord;
1696 struct ExtraResourceRecord_struct
1697 {
1698     ExtraResourceRecord *next;
1699     mDNSu32 ClientID;  // Opaque ID field to be used by client to map an AddRecord call to a set of Extra records
1700     AuthRecord r;
1701     // Note: Add any additional fields *before* the AuthRecord in this structure, not at the end.
1702     // In some cases clients can allocate larger chunks of memory and set r->rdata->MaxRDLength to indicate
1703     // that this extra memory is available, which would result in any fields after the AuthRecord getting smashed
1704 };
1705 
1706 // Note: Within an mDNSServiceCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
1707 typedef void mDNSServiceCallback (mDNS *const m, ServiceRecordSet *const sr, mStatus result);
1708 
1709 // A ServiceRecordSet has no special meaning to the core code of the Multicast DNS protocol engine;
1710 // it is just a convenience structure to group together the records that make up a standard service
1711 // registration so that they can be allocted and deallocted together as a single memory object.
1712 // It contains its own ServiceCallback+ServiceContext to report aggregate results up to the next layer of software above.
1713 // It also contains:
1714 //  * the basic PTR/SRV/TXT triplet used to represent any DNS-SD service
1715 //  * the "_services" PTR record for service enumeration
1716 //  * the optional list of SubType PTR records
1717 //  * the optional list of additional records attached to the service set (e.g. iChat pictures)
1718 
1719 struct ServiceRecordSet_struct
1720 {
1721     // These internal state fields are used internally by mDNSCore; the client layer needn't be concerned with them.
1722     // No fields need to be set up by the client prior to calling mDNS_RegisterService();
1723     // all required data is passed as parameters to that function.
1724     mDNSServiceCallback *ServiceCallback;
1725     void                *ServiceContext;
1726     mDNSBool Conflict;              // Set if this record set was forcibly deregistered because of a conflict
1727 
1728     ExtraResourceRecord *Extras;    // Optional list of extra AuthRecords attached to this service registration. e.g. TSR record
1729     mDNSu32 NumSubTypes;
1730     AuthRecord          *SubTypes;
1731     mDNSu32             flags;      // saved for subsequent calls to mDNS_RegisterService() if records
1732                                     // need to be re-registered.
1733     AuthRecord RR_ADV;              // e.g. _services._dns-sd._udp.local. PTR _printer._tcp.local.
1734     AuthRecord RR_PTR;              // e.g. _printer._tcp.local.        PTR Name._printer._tcp.local.
1735     AuthRecord RR_SRV;              // e.g. Name._printer._tcp.local.   SRV 0 0 port target
1736     AuthRecord RR_TXT;              // e.g. Name._printer._tcp.local.   TXT PrintQueueName
1737     // Don't add any fields after AuthRecord RR_TXT.
1738     // This is where the implicit extra space goes if we allocate a ServiceRecordSet containing an oversized RR_TXT record
1739 };
1740 
1741 // ***************************************************************************
1742 #if 0
1743 #pragma mark -
1744 #pragma mark - Question structures
1745 #endif
1746 
1747 // We record the last eight instances of each duplicate query
1748 // This gives us v4/v6 on each of Ethernet, AirPort and Firewire, and two free slots "for future expansion"
1749 // If the host has more active interfaces that this it is not fatal -- duplicate question suppression will degrade gracefully.
1750 // Since we will still remember the last eight, the busiest interfaces will still get the effective duplicate question suppression.
1751 #define DupSuppressInfoSize 8
1752 
1753 typedef struct
1754 {
1755     mDNSInterfaceID InterfaceID;
1756     mDNSs32 Time;
1757     mDNSs32 Type;                           // v4 or v6?
1758 } DupSuppressInfo;
1759 
1760 typedef struct
1761 {
1762     DupSuppressInfo slots[DupSuppressInfoSize]; // Data structures for keeping track of duplicate query suppressions.
1763 } DupSuppressState;
1764 
1765 MDNS_CLOSED_ENUM(LLQ_State, mDNSu8,
1766     LLQ_Invalid = 0,
1767     // This is the initial state.
1768     LLQ_Init = 1,
1769 
1770     // All of these states indicate that we are doing DNS Push, and haven't given up yet.
1771           LLQ_DNSPush_ServerDiscovery = 10,
1772           LLQ_DNSPush_Connecting      = 11,
1773           LLQ_DNSPush_Established     = 12,
1774 
1775     // All of these states indicate that we are doing LLQ and haven't given up yet.
1776     LLQ_InitialRequest   = 20,
1777     LLQ_SecondaryRequest = 21,
1778     LLQ_Established      = 22,
1779 
1780     // If we get here, it means DNS Push isn't available, so we're polling.
1781     LLQ_Poll                    = 30
1782 );
1783 
1784 #if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
1785 #define DNS_PUSH_IN_PROGRESS(STATE) ((STATE) == LLQ_DNSPush_ServerDiscovery || (STATE) == LLQ_DNSPush_Connecting \
1786                                         || (STATE) == LLQ_DNSPush_Established)
1787 #endif
1788 
1789 // LLQ constants
1790 #define kLLQ_Vers      1
1791 #define kLLQ_DefLease  7200 // 2 hours
1792 #define kLLQ_MAX_TRIES 3    // retry an operation 3 times max
1793 #define kLLQ_INIT_RESEND 2 // resend an un-ack'd packet after 2 seconds, then double for each additional
1794 // LLQ Operation Codes
1795 #define kLLQOp_Setup     1
1796 #define kLLQOp_Refresh   2
1797 #define kLLQOp_Event     3
1798 
1799 // LLQ Errror Codes
1800 enum
1801 {
1802     LLQErr_NoError    = 0,
1803     LLQErr_ServFull   = 1,
1804     LLQErr_Static     = 2,
1805     LLQErr_FormErr    = 3,
1806     LLQErr_NoSuchLLQ  = 4,
1807     LLQErr_BadVers    = 5,
1808     LLQErr_UnknownErr = 6
1809 };
1810 
1811 typedef enum {
1812     DNSPushServerDisconnected,
1813           DNSPushServerConnectFailed,
1814           DNSPushServerConnectionInProgress,
1815           DNSPushServerConnected,
1816           DNSPushServerSessionEstablished,
1817           DNSPushServerNoDNSPush
1818 } DNSPushServer_ConnectState;
1819 
1820 #define HMAC_LEN    64
1821 #define HMAC_IPAD   0x36
1822 #define HMAC_OPAD   0x5c
1823 #define MD5_LEN     16
1824 
1825 // Internal data structure to maintain authentication information
1826 
1827 #if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
1828 
1829 typedef enum {
1830     kDNSDigest_HMACAlg_None = 0,
1831     kDNSDigest_HMACAlg_MD5,
1832     kDNSDigest_HMACAlg_SHA1,
1833     kDNSDigest_HMACAlg_SHA224,
1834     kDNSDigest_HMACAlg_SHA256,
1835     kDNSDigest_HMACAlg_SHA384,
1836     kDNSDigest_HMACAlg_SHA512,
1837 } DNSDigest_HMACAlgorithm;
1838 
1839 #define kDNSDigest_HMACMD5_OutputLengthInBytes      16
1840 #define kDNSDigest_HMACSHA1_OutputLengthInBytes     20
1841 #define kDNSDigest_HMACSHA224_OutputLengthInBytes   28
1842 #define kDNSDigest_HMACSHA256_OutputLengthInBytes   32
1843 #define kDNSDigest_HMACSHA384_OutputLengthInBytes   48
1844 #define kDNSDigest_HMACSHA512_OutputLengthInBytes   64
1845 
1846 #define kDNSDigest_HMACMD5_KeyLengthInBytes      kDNSDigest_HMACMD5_OutputLengthInBytes
1847 #define kDNSDigest_HMACSHA1_KeyLengthInBytes     kDNSDigest_HMACSHA1_OutputLengthInBytes
1848 #define kDNSDigest_HMACSHA224_KeyLengthInBytes   kDNSDigest_HMACSHA224_OutputLengthInBytes
1849 #define kDNSDigest_HMACSHA256_KeyLengthInBytes   kDNSDigest_HMACSHA256_OutputLengthInBytes
1850 #define kDNSDigest_HMACSHA384_KeyLengthInBytes   kDNSDigest_HMACSHA384_OutputLengthInBytes
1851 #define kDNSDigest_HMACSHA512_KeyLengthInBytes   kDNSDigest_HMACSHA512_OutputLengthInBytes
1852 
1853 #define DNSDigest_Base64EncodedSize(SIZE)       ((((SIZE) + 2) / 3) * 4)
1854 #define DNSDigest_Base64EncodedMaxSize(SIZE)    (DNSDigest_Base64EncodedSize(SIZE))
1855 
1856 #define kDNSDigest_HMACKeyLengthInBytesMAX                  kDNSDigest_HMACSHA512_KeyLengthInBytes
1857 #define kDNSDigest_HMACBase64EncodedKeyLengthInBytesMAX     (DNSDigest_Base64EncodedMaxSize(kDNSDigest_HMACKeyLengthInBytesMAX))
1858 #define kDNSDigest_HMACOutputLengthInBytesMAX               kDNSDigest_HMACSHA512_OutputLengthInBytes
1859 
1860 #endif // MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
1861 
1862 typedef struct DomainAuthInfo
1863 {
1864     struct DomainAuthInfo *next;
1865     mDNSs32 deltime;                        // If we're planning to delete this DomainAuthInfo, the time we want it deleted
1866     domainname domain;
1867     domainname keyname;
1868     domainname hostname;
1869     mDNSIPPort port;
1870 #if MDNSRESPONDER_SUPPORTS(APPLE, SECURE_HMAC_ALGORITHM_2022)
1871     DNSDigest_HMACAlgorithm algorithm;                  // The algorithm of the key.
1872     mDNSu32 key_len;                                    // The actual length of the key data in bytes.
1873     mDNSu8 key[kDNSDigest_HMACKeyLengthInBytesMAX];     // The "large enough" key data buffer.
1874 #else
1875     char b64keydata[32];
1876     mDNSu8 keydata_ipad[HMAC_LEN];              // padded key for inner hash rounds
1877     mDNSu8 keydata_opad[HMAC_LEN];              // padded key for outer hash rounds
1878 #endif
1879 } DomainAuthInfo;
1880 
1881 // Note: Within an mDNSQuestionCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
1882 // Note: Any value other than QC_rmv i.e., any non-zero value will result in kDNSServiceFlagsAdd to the application
1883 // layer. These values are used within mDNSResponder and not sent across to the application. QC_addnocache is for
1884 // delivering a response without adding to the cache. QC_forceresponse is superset of QC_addnocache where in
1885 // addition to not entering in the cache, it also forces the negative response through.
1886 typedef enum { QC_rmv = 0, QC_add, QC_addnocache, QC_forceresponse, QC_suppressed } QC_result;
1887 typedef void mDNSQuestionCallback (mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord);
1888 typedef void (*mDNSQuestionResetHandler)(DNSQuestion *question);
1889 typedef void AsyncDispatchFunc(mDNS *const m, void *context);
1890 extern void mDNSPlatformDispatchAsync(mDNS *const m, void *context, AsyncDispatchFunc func);
1891 
1892 #define NextQSendTime(Q)  ((Q)->LastQTime + (Q)->ThisQInterval)
1893 #define ActiveQuestion(Q) ((Q)->ThisQInterval > 0 && !(Q)->DuplicateOf)
1894 #define TimeToSendThisQuestion(Q,time) (ActiveQuestion(Q) && (time) - NextQSendTime(Q) >= 0)
1895 #define TicksTTL(RR) ((mDNSs32)(RR)->resrec.rroriginalttl * mDNSPlatformOneSecond)
1896 extern mDNSs32 RRExpireTime(const CacheRecord *cr);
1897 #define MaxUnansweredQueries 4
1898 #define MaxTentativeSeconds  5
1899 
1900 // RFC 4122 defines it to be 16 bytes
1901 #define UUID_SIZE       16
1902 
1903 #if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS) || MDNSRESPONDER_SUPPORTS(APPLE, RUNTIME_MDNS_METRICS)
1904 typedef struct
1905 {
1906     mDNSu32             querySendCount;         // Number of queries that have been sent to DNS servers so far.
1907     mDNSs32             firstQueryTime;         // The time when the first query was sent to a DNS server.
1908     mDNSBool            answered;               // Has this question been answered?
1909 }   DNSMetrics;
1910 #endif
1911 
1912 #if MDNSRESPONDER_SUPPORTS(APPLE, DNS64)
1913 #include "DNS64State.h"
1914 #endif
1915 
1916 typedef struct mDNS_DNSPushServer DNSPushServer;
1917 typedef struct mDNS_DNSPushZone   DNSPushZone;
1918 
1919 MDNS_CLOSED_ENUM(mDNSExpiredRecordPolicy, mDNSu8,
1920     mDNSExpiredRecordPolicy_DoNotUse    = 0,    // Don't use expired cache records at all. This is the default policy.
1921     mDNSExpiredRecordPolicy_UseCached   = 1,    // Use expired cache records and immortalize unexpired answers. [1,2]
1922     mDNSExpiredRecordPolicy_Immortalize = 2     // Don't use expired records, but immortalize unexpired answers. [1,2]
1923 );
1924 // Notes:
1925 // 1. Policy only applies to non-mDNS DNSQuestions.
1926 // 2. A DNSQuestion that uses the mDNSExpiredRecordPolicy_UseCached policy will be downgraded to the
1927 //    mDNSExpiredRecordPolicy_Immortalize policy after it has been determined that there are no expired cache records
1928 //    that can be used as answers for the DNSQuestion. The mDNSQuestionEvent_NoMoreExpiredRecords event will be
1929 //    delivered via the DNSQuestion's event handler after the determination, right before the policy downgrade.
1930 
1931 MDNS_CLOSED_ENUM(mDNSQuestionEvent, mDNSu8,
1932     mDNSQuestionEvent_NoMoreExpiredRecords = 1  // No more expired cache records will be provided. [1]
1933 );
1934 // Notes:
1935 // 1. This event is only relevant for non-mDNS DNSQuestions that use the mDNSExpiredRecordPolicy_UseCached policy. It
1936 //    signals that no more expired cache records will be provided to a DNSQuestion's owner.
1937 
1938 typedef void (*mDNSQuestionEventHandler)(DNSQuestion *question, mDNSQuestionEvent event);
1939 
1940 #if MDNSRESPONDER_SUPPORTS(APPLE, PADDING_CHECKS)
1941 // The member variables of struct DNSQuestion_struct are in descending order of alignment requirement to eliminate
1942 // padding between member variables. That is, member variables with an 8-byte alignment requirement come first, followed
1943 // by member variables with a 4-byte alignment requirement, and so forth.
1944 MDNS_CLANG_TREAT_WARNING_AS_ERROR_BEGIN(-Wpadded)
1945 #endif
1946 struct DNSQuestion_struct
1947 {
1948 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
1949     mdns_dns_service_id_t CustomID;         // ID for client-specific custom DNS service.
1950 #endif
1951     DNSQuestion          *next;
1952     mDNSInterfaceID FlappingInterface1;     // Set when an interface goes away, to flag if remove events are delivered for this Q
1953     mDNSInterfaceID FlappingInterface2;     // Set when an interface goes away, to flag if remove events are delivered for this Q
1954     DomainAuthInfo       *AuthInfo;         // Non-NULL if query is currently being done using Private DNS
1955     DNSQuestion          *DuplicateOf;
1956     DNSQuestion          *NextInDQList;
1957     DupSuppressState     *DupSuppress;
1958     mDNSInterfaceID SendQNow;               // The interface this query is being sent on right now
1959     UDPSocket            *LocalSocket;
1960 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
1961     mdns_dns_service_t    dnsservice;       // The current DNS service.
1962     mdns_dns_service_id_t lastDNSServiceID; // The ID of the previous DNS service before a CNAME restart.
1963     mdns_client_t         client;           // The current querier or subscriber.
1964 #else
1965     DNSServer            *qDNSServer;       // Caching server for this query (in the absence of an SRV saying otherwise)
1966 #endif
1967     ZoneData             *nta;              // Used for getting zone data for private or LLQ query
1968     struct tcpInfo_t *tcp;
1969 #if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH)
1970     // DNS Push fields. These fields are only meaningful when LongLived flag is set.
1971     DNSPushZone   *dnsPushZone;             // The DNS push zone where the current question is if the
1972                                             // kDNSServiceFlagsLongLivedQuery flag is set.
1973     DNSPushServer *dnsPushServer;           // The DNS push server that is responsible for answering the current
1974                                             // question if the kDNSServiceFlagsLongLivedQuery flag is set.
1975 #endif
1976 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
1977     mdns_audit_token_t PeerToken;           // The immediate client's audit token.
1978     mdns_audit_token_t DelegatorToken;      // The delegator's audit token if the immediate client is a delegate.
1979 #endif
1980     mDNSInterfaceID InterfaceID;            // Non-zero if you want to issue queries only on a single specific IP interface
1981 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
1982     dnssec_obj_dns_question_member_t dnssec;// DNSSEC-related information for the current question.
1983 #endif
1984     mDNSQuestionCallback *QuestionCallback;
1985     mDNSQuestionResetHandler ResetHandler;
1986     mDNSQuestionEventHandler EventHandler;
1987     void                 *QuestionContext;
1988 #if MDNSRESPONDER_SUPPORTS(APPLE, DNS_PUSH)
1989     dns_push_obj_dns_question_member_t dns_push;
1990 #endif
1991 #if MDNSRESPONDER_SUPPORTS(APPLE, DISCOVERY_PROXY_CLIENT)
1992     CFMutableSetRef DPSubscribers;          // Current set of local domain Discovery Proxy subscribers.
1993 #endif
1994     mDNSu32 qnamehash;
1995     mDNSs32 DelayAnswering;                 // Set if we want to defer answering this question until the cache settles
1996     mDNSs32 LastQTime;                      // Last scheduled transmission of this Q on *all* applicable interfaces
1997     mDNSs32 ThisQInterval;                  // LastQTime + ThisQInterval is the next scheduled transmission of this Q
1998                                             // ThisQInterval > 0 for an active question;
1999                                             // ThisQInterval = 0 for a suspended question that's still in the list
2000                                             // ThisQInterval = -1 for a cancelled question (should not still be in list)
2001     mDNSs32 ExpectUnicastResp;              // Set when we send a query with the kDNSQClass_UnicastResponse bit set
2002     mDNSs32 LastAnswerPktNum;               // The sequence number of the last response packet containing an answer to this Q
2003     mDNSu32 RecentAnswerPkts;               // Number of answers since the last time we sent this query
2004     mDNSu32 CurrentAnswers;                 // Number of records currently in the cache that answer this question
2005     mDNSu32 LargeAnswers;                   // Number of answers with rdata > 1024 bytes
2006     mDNSu32 UniqueAnswers;                  // Number of answers received with kDNSClass_UniqueRRSet bit set
2007     mDNSs32 StopTime;                       // Time this question should be stopped by giving them a negative answer
2008     mDNSs32 pid;                            // Process ID of the client that is requesting the question
2009     mDNSu32 euid;                           // Effective User Id of the client that is requesting the question
2010     mDNSu32 request_id;                     // The ID of request that generates the current question
2011     mDNSs32 LastQTxTime;                    // Last time this Q was sent on one (but not necessarily all) interfaces
2012 #if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS) || MDNSRESPONDER_SUPPORTS(APPLE, RUNTIME_MDNS_METRICS)
2013     DNSMetrics metrics;                    // Data used for collecting unicast/multicast DNS query metrics.
2014 #endif
2015     mDNSu32 ReqLease;                       // LLQ: seconds (relative)
2016     mDNSs32 expire;                         // LLQ: ticks (absolute)
2017     mDNSs32 ServiceID;                      // Service identifier to match against the DNS server
2018     mDNSAddr servAddr;                      // Address and port learned from _dns-llq, _dns-llq-tls or _dns-query-tls SRV query
2019 #if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_DISCOVERY)
2020     mDNSAddr UnicastMDNSResolver;           // If a non-zero IP address, mDNS queries will be sent to this address via
2021                                             // unicast instead of to an mDNS multicast address.
2022 #endif
2023     mDNSu32  flags;                         // flags from original DNSService*() API request.
2024     mDNSOpaque64 id;
2025 #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
2026     mDNSOpaque128 validDNSServers;          // Valid DNSServers for this question
2027 #endif
2028     mDNSIPPort servPort;
2029     mDNSIPPort tcpSrcPort;                  // Local Port TCP packet received on;need this as tcp struct is disposed
2030                                             // by tcpCallback before calling into mDNSCoreReceive
2031     mDNSOpaque16 TargetQID;                 // DNS or mDNS message ID.
2032     mDNSu16 qtype;
2033     mDNSu16 qclass;
2034     mDNSOpaque16 responseFlags;             // Temporary place holder for the error we get back from the DNS server
2035                                             // till we populate in the cache
2036     mDNSs16 ntries;                         // for UDP: the number of packets sent for this LLQ state
2037                                             // for TCP: there is some ambiguity in the use of this variable, but in general, it is
2038                                             //          the number of TCP/TLS connection attempts for this LLQ state, or
2039                                             //          the number of packets sent for this TCP/TLS connection
2040 #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
2041     mDNSu16 noServerResponse;               // At least one server did not respond.
2042 #endif
2043     LLQ_State state;
2044     mDNSu8 BrowseThreshold;                 // If we have received at least this number of answers,
2045                                             // set the next question interval to MaxQuestionInterval
2046     mDNSu8 RequestUnicast;                  // Non-zero if we want to send query with kDNSQClass_UnicastResponse bit set
2047     mDNSu8 CNAMEReferrals;                  // Count of how many CNAME redirections we've done
2048     mDNSBool Suppressed;                    // This query should be suppressed, i.e., not sent on the wire.
2049     mDNSu8 LOAddressAnswers;                // Number of answers from the local only auth records that are
2050                                             // answering A, AAAA, CNAME, or PTR (/etc/hosts)
2051     mDNSu8 WakeOnResolveCount;              // Number of wakes that should be sent on resolve
2052     mDNSBool InitialCacheMiss;              // True after the question cannot be answered from the cache
2053     mDNSBool SendOnAll;                     // Set if we're sending this question on all active interfaces
2054     mDNSBool CachedAnswerNeedsUpdate;       // See SendQueries().  Set if we're sending this question
2055                                             // because a cached answer needs to be refreshed.
2056 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
2057     mDNSu8 ResolverUUID[UUID_SIZE];         // Resolver UUID to match against the DNS server
2058 #endif
2059     domainname qname;
2060     mDNSBool LongLived;                     // Set by client for calls to mDNS_StartQuery to indicate LLQs to unicast layer.
2061     mDNSBool ExpectUnique;                  // Set by client if it's expecting unique RR(s) for this question, not shared RRs
2062     mDNSBool ForceMCast;                    // Set by client to force mDNS query, even for apparently uDNS names
2063     mDNSBool ReturnIntermed;                // Set by client to request callbacks for intermediate CNAME/NXDOMAIN results
2064     mDNSBool SuppressUnusable;              // Set by client to suppress unusable queries to be sent on the wire
2065     mDNSBool TimeoutQuestion;               // Timeout this question if there is no reply in configured time
2066     mDNSBool IsUnicastDotLocal;             // True if this is a dot-local query that should be answered via unicast DNS.
2067     mDNSBool WakeOnResolve;                 // Send wakeup on resolve
2068     mDNSBool UseBackgroundTraffic;          // Set by client to use background traffic class for request
2069     mDNSBool AppendSearchDomains;           // Search domains can be appended for this query
2070     mDNSBool ForcePathEval;                 // Perform a path evaluation even if kDNSServiceFlagsPathEvaluationDone is set.
2071     mDNSBool IsFailover;                    // True if the client requested to skip resolvers that allow failover.
2072     mDNSBool PersistWhenRecordsUnusable;    // Set by client to force CNAME follows while suppressed due to unusable records.
2073     mDNSBool ForceCNAMEFollows;             // Follow CNAMEs even if the DNSQuestion is suppressed.
2074     mDNSExpiredRecordPolicy ExpRecordPolicy;// The DNSQuestion's policy for expired records.
2075 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
2076     mDNSBool RequireEncryption;             // Set by client to require encrypted queries
2077     mDNSBool NeedUpdatedQuerier;            // True if new querier is needed for DNSQuestion's updated qname/qtype/qclass.
2078     mDNSBool UsedAsFailFastProbe;           // True if used as a probe for fail-fast service with connection problems.
2079     mDNSBool ProhibitEncryptedDNS;          // True if use of encrypted DNS protocols is prohibited.
2080     mDNSBool OverrideDNSService;            // True if resolver UUID overrides normal DNS service selection.
2081 #endif
2082     mDNSu8 ProxyQuestion;                   // Proxy Question
2083 #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
2084     mDNSBool inAppBrowserRequest;           // Is request associated with an in-app-browser
2085 #endif
2086     mDNSBool BlockedByPolicy;               // True if the question is blocked by policy rule evaluation.
2087 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
2088     mDNSBool enableDNSSEC;                  // The boolean value controlling whether to enable DNSSEC for this question.
2089 #endif
2090     mDNSu8 uuid[UUID_SIZE];                 // Unique ID of the client that is requesting the question (valid only if pid is zero)
2091 #if MDNSRESPONDER_SUPPORTS(APPLE, DNS64)
2092     DNS64 dns64;                            // DNS64 state for performing IPv6 address synthesis on networks with NAT64.
2093 #endif
2094 #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
2095     mDNSBool triedAllServersOnce;           // True if all DNS servers have been tried once.
2096     mDNSu8 unansweredQueries;               // The number of unanswered queries to this server
2097     mDNSBool Restart;                       // This question should be restarted soon.
2098 #endif
2099 #if MDNSRESPONDER_SUPPORTS(APPLE, UNICAST_ASSIST)
2100     mDNSBool initialAssistPerformed;        // Initial quetion unicast assist logic was performed
2101 #endif
2102 #if MDNSRESPONDER_SUPPORTS(APPLE, LOG_PRIVACY_LEVEL)
2103     dnssd_log_privacy_level_t logPrivacyLevel; // The log privacy level that the client wishes to have when the question
2104                                                // is started.
2105 #endif
2106 #if MDNSRESPONDER_SUPPORTS(APPLE, PADDING_CHECKS)
2107     #if TARGET_OS_OSX || TARGET_OS_TV
2108         MDNS_STRUCT_PAD(2);
2109     #else
2110         MDNS_STRUCT_PAD_64_32(6, 2);
2111     #endif
2112 #endif
2113 };
2114 #if MDNSRESPONDER_SUPPORTS(APPLE, PADDING_CHECKS)
2115 MDNS_CLANG_TREAT_WARNING_AS_ERROR_END()
2116 MDNS_GENERAL_STRUCT_PAD_CHECK(DNSQuestion);
2117 #endif
2118 
2119 typedef enum { ZoneServiceUpdate, ZoneServiceQuery, ZoneServiceLLQ, ZoneServiceDNSPush } ZoneService;
2120 
2121 typedef void ZoneDataCallback (mDNS *const m, mStatus err, const ZoneData *result);
2122 
2123 struct ZoneData_struct
2124 {
2125     domainname ChildName;               // Name for which we're trying to find the responsible server
2126     ZoneService ZoneService;            // Which service we're seeking for this zone (update, query, or LLQ)
2127     domainname       *CurrentSOA;       // Points to somewhere within ChildName
2128     domainname ZoneName;                // Discovered result: Left-hand-side of SOA record
2129     mDNSu16 ZoneClass;                  // Discovered result: DNS Class from SOA record
2130     domainname Host;                    // Discovered result: Target host from SRV record
2131     mDNSIPPort Port;                    // Discovered result: Update port, query port, or LLQ port from SRV record
2132     mDNSAddr Addr;                      // Discovered result: Address of Target host from SRV record
2133     mDNSBool ZonePrivate;               // Discovered result: Does zone require encrypted queries?
2134     ZoneDataCallback *ZoneDataCallback; // Caller-specified function to be called upon completion
2135     void             *ZoneDataContext;
2136     DNSQuestion question;               // Storage for any active question
2137 };
2138 
2139 extern ZoneData *StartGetZoneData(mDNS *const m, const domainname *const name, const ZoneService target, ZoneDataCallback callback, void *callbackInfo);
2140 extern void CancelGetZoneData(mDNS *const m, ZoneData *nta);
2141 extern mDNSBool IsGetZoneDataQuestion(DNSQuestion *q);
2142 
2143 typedef struct DNameListElem
2144 {
2145     struct DNameListElem *next;
2146     mDNSu32 uid;
2147     domainname name;
2148 } DNameListElem;
2149 
2150 
2151 // ***************************************************************************
2152 #if 0
2153 #pragma mark -
2154 #pragma mark - NetworkInterfaceInfo_struct
2155 #endif
2156 
2157 typedef struct NetworkInterfaceInfo_struct NetworkInterfaceInfo;
2158 
2159 // A NetworkInterfaceInfo_struct serves two purposes:
2160 // 1. It holds the address, PTR and HINFO records to advertise a given IP address on a given physical interface
2161 // 2. It tells mDNSCore which physical interfaces are available; each physical interface has its own unique InterfaceID.
2162 //    Since there may be multiple IP addresses on a single physical interface,
2163 //    there may be multiple NetworkInterfaceInfo_structs with the same InterfaceID.
2164 //    In this case, to avoid sending the same packet n times, when there's more than one
2165 //    struct with the same InterfaceID, mDNSCore picks one member of the set to be the
2166 //    active representative of the set; all others have the 'InterfaceActive' flag unset.
2167 
2168 struct NetworkInterfaceInfo_struct
2169 {
2170     // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
2171     NetworkInterfaceInfo *next;
2172 
2173 #if MDNSRESPONDER_SUPPORTS(APPLE, RUNTIME_MDNS_METRICS)
2174     // Object that is used to track the mDNS response delay distribution per interface.
2175     // It is only initialized when the interface is mDNS-capable.
2176     mdns_multicast_delay_histogram_t delayHistogram;
2177 #endif
2178 
2179     mDNSu8 InterfaceActive;             // Set if interface is sending & receiving packets (see comment above)
2180     mDNSu8 IPv4Available;               // If InterfaceActive, set if v4 available on this InterfaceID
2181     mDNSu8 IPv6Available;               // If InterfaceActive, set if v6 available on this InterfaceID
2182 
2183 #if MDNSRESPONDER_SUPPORTS(COMMON, SPS_CLIENT)
2184     DNSQuestion NetWakeBrowse;
2185     DNSQuestion NetWakeResolve[3];      // For fault-tolerance, we try up to three Sleep Proxies
2186     mDNSAddr SPSAddr[3];
2187     mDNSIPPort SPSPort[3];
2188     mDNSs32 NextSPSAttempt;             // -1 if we're not currently attempting to register with any Sleep Proxy
2189     mDNSs32 NextSPSAttemptTime;
2190 #endif
2191 
2192     // Standard AuthRecords that every Responder host should have (one per active IP address)
2193     AuthRecord RR_A;                    // 'A' or 'AAAA' (address) record for our ".local" name
2194     AuthRecord RR_PTR;                  // PTR (reverse lookup) record
2195 #if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
2196     AuthRecord RR_AddrRand;             // For non-AWDL interfaces, this is the A or AAAA record of the randomized hostname.
2197 #endif
2198 
2199     // Client API fields: The client must set up these fields *before* calling mDNS_RegisterInterface()
2200     mDNSInterfaceID InterfaceID;        // Identifies physical interface; MUST NOT be 0, -1, or -2
2201     mDNSAddr ip;                        // The IPv4 or IPv6 address to advertise
2202     mDNSAddr mask;
2203     mDNSEthAddr MAC;
2204     char ifname[64];                    // Windows uses a GUID string for the interface name, which doesn't fit in 16 bytes
2205     mDNSu8 Advertise;                   // False if you are only searching on this interface
2206     mDNSu8 McastTxRx;                   // Send/Receive multicast on this { InterfaceID, address family } ?
2207     mDNSu8 NetWake;                     // Set if Wake-On-Magic-Packet is enabled on this interface
2208     mDNSu8 Loopback;                    // Set if this is the loopback interface
2209     mDNSu8 IgnoreIPv4LL;                // Set if IPv4 Link-Local addresses have to be ignored.
2210     mDNSu8 SendGoodbyes;                // Send goodbyes on this interface while sleeping
2211     mDNSBool DirectLink;                // a direct link, indicating we can skip the probe for
2212                                         // address records
2213     mDNSBool SupportsUnicastMDNSResponse;  // Indicates that the interface supports unicast responses
2214                                         // to Bonjour queries.  Generally true for an interface.
2215     mDNSBool MustNotPreventSleep;       // Set if this interface must not ever prevent sleep.
2216 };
2217 
2218 #define SLE_DELETE                      0x00000001
2219 #define SLE_WAB_BROWSE_QUERY_STARTED    0x00000002
2220 #define SLE_WAB_LBROWSE_QUERY_STARTED   0x00000004
2221 #define SLE_WAB_REG_QUERY_STARTED       0x00000008
2222 
2223 typedef struct SearchListElem
2224 {
2225     struct SearchListElem *next;
2226     domainname domain;
2227     int flag;
2228     mDNSInterfaceID InterfaceID;
2229     DNSQuestion BrowseQ;
2230     DNSQuestion DefBrowseQ;
2231     DNSQuestion AutomaticBrowseQ;
2232     DNSQuestion RegisterQ;
2233     DNSQuestion DefRegisterQ;
2234     int numCfAnswers;
2235     ARListElem *AuthRecs;
2236 } SearchListElem;
2237 
2238 typedef enum
2239 {
2240     mDNS_DomainTypeBrowse              = 0,
2241     mDNS_DomainTypeBrowseDefault       = 1,
2242     mDNS_DomainTypeBrowseAutomatic     = 2,
2243     mDNS_DomainTypeRegistration        = 3,
2244     mDNS_DomainTypeRegistrationDefault = 4,
2245 
2246     mDNS_DomainTypeMax      = 4,
2247     mDNS_DomainTypeMaxCount = 5
2248 } mDNS_DomainType;
2249 
2250 typedef struct EnumeratedDomainList
2251 {
2252     domainname name;
2253     struct EnumeratedDomainList *next;
2254 } EnumeratedDomainList;
2255 
2256 typedef enum {
2257     DomainEnumerationState_Stopped,         // Domain enumeration is inactive.
2258     DomainEnumerationState_Started,         // Domain enumeration is active.
2259     DomainEnumerationState_StopInProgress,  // Domain enumeration is active but will become inactive later.
2260 } DomainEnumerationState;
2261 
2262 typedef struct DomainEnumerationWithType DomainEnumerationWithType;
2263 struct DomainEnumerationWithType
2264 {
2265     EnumeratedDomainList    *domainList;        // Domain discovered through the domain enumeration.
2266     DNSQuestion             question;           // The DNS question that is used to do the domain enumeration.
2267     DomainEnumerationState  state;              // The state of the domain enumeration operation.
2268     mDNSu32                 activeClientCount;  // The number of active clients that need the domain enumeration.
2269     mDNSs32                 nextStopTime;       // If the operation state is DomainEnumerationState_StopInProgress, it indicates when the operation will be stopped.
2270 };
2271 
2272 typedef struct DomainEnumerationOp DomainEnumerationOp;
2273 struct DomainEnumerationOp
2274 {
2275     domainname                  name;                                   // The name of the domain that does domain enumeration.
2276     DomainEnumerationWithType   *enumerations[mDNS_DomainTypeMaxCount]; // The specific domain enumeration for different types.
2277     DomainEnumerationOp         *next;                                  // The next domain in the list to do enumeration.
2278 };
2279 
2280 // For domain enumeration and automatic browsing
2281 // This is the user's DNS search list.
2282 // In each of these domains we search for our special pointer records (lb._dns-sd._udp.<domain>, etc.)
2283 // to discover recommended domains for domain enumeration (browse, default browse, registration,
2284 // default registration) and possibly one or more recommended automatic browsing domains.
2285 extern SearchListElem *SearchList;      // This really ought to be part of mDNS_struct -- SC
2286 
2287 // ***************************************************************************
2288 #if 0
2289 #pragma mark -
2290 #pragma mark - Main mDNS object, used to hold all the mDNS state
2291 #endif
2292 
2293 typedef void mDNSCallback (mDNS *const m, mStatus result);
2294 
2295 #ifndef CACHE_HASH_SLOTS
2296 #define CACHE_HASH_SLOTS 499
2297 #endif
2298 
2299 enum
2300 {
2301     SleepState_Awake = 0,
2302     SleepState_Transferring = 1,
2303     SleepState_Sleeping = 2
2304 };
2305 
2306 typedef struct
2307 {
2308     mDNSu32 NameConflicts;                  // Normal Name conflicts
2309     mDNSu32 KnownUniqueNameConflicts;       // Name Conflicts for KnownUnique Records
2310     mDNSu32 DupQuerySuppressions;           // Duplicate query suppressions
2311     mDNSu32 KnownAnswerSuppressions;        // Known Answer suppressions
2312     mDNSu32 KnownAnswerMultiplePkts;        // Known Answer in queries spannign multiple packets
2313     mDNSu32 PoofCacheDeletions;             // Number of times the cache was deleted due to POOF
2314     mDNSu32 UnicastBitInQueries;            // Queries with QU bit set
2315     mDNSu32 NormalQueries;                  // Queries with QU bit not set
2316     mDNSu32 MatchingAnswersForQueries;      // Queries for which we had a response
2317     mDNSu32 UnicastResponses;               // Unicast responses to queries
2318     mDNSu32 MulticastResponses;             // Multicast responses to queries
2319     mDNSu32 UnicastDemotedToMulticast;      // Number of times unicast demoted to multicast
2320     mDNSu32 Sleeps;                         // Total sleeps
2321     mDNSu32 Wakes;                          // Total wakes
2322     mDNSu32 InterfaceUp;                    // Total Interface UP events
2323     mDNSu32 InterfaceUpFlap;                // Total Interface UP events with flaps
2324     mDNSu32 InterfaceDown;                  // Total Interface Down events
2325     mDNSu32 InterfaceDownFlap;              // Total Interface Down events with flaps
2326     mDNSu32 CacheRefreshQueries;            // Number of queries that we sent for refreshing cache
2327     mDNSu32 CacheRefreshed;                 // Number of times the cache was refreshed due to a response
2328     mDNSu32 WakeOnResolves;                 // Number of times we did a wake on resolve
2329 } mDNSStatistics;
2330 
2331 extern void LogMDNSStatisticsToFD(int fd, mDNS *const m);
2332 
2333 // Time constant (~= 260 hours ~= 10 days and 21 hours) used to set
2334 // various time values to a point well into the future.
2335 #define FutureTime   0x38000000
2336 
2337 // Seven days in seconds, used to limit the time since received in TSR record.
2338 #define MaxTimeSinceReceived   (7*86400)
2339 
2340 #if MDNSRESPONDER_SUPPORTS(APPLE, RUNTIME_MDNS_METRICS)
2341     // Print mDNS response delay distribution for every 30 minutes.
2342     #define RuntimeMDNSMetricsReportInterval (mDNSPlatformOneSecond * 1800)
2343 #endif
2344 
2345 struct mDNS_struct
2346 {
2347     // Internal state fields. These hold the main internal state of mDNSCore;
2348     // the client layer needn't be concerned with them.
2349     // No fields need to be set up by the client prior to calling mDNS_Init();
2350     // all required data is passed as parameters to that function.
2351 
2352     mDNS_PlatformSupport *p;            // Pointer to platform-specific data of indeterminite size
2353     mDNSs32 NetworkChanged;
2354     mDNSBool CanReceiveUnicastOn5353;
2355     mDNSBool AdvertiseLocalAddresses;
2356     mDNSBool DivertMulticastAdvertisements; // from interfaces that do not advertise local addresses to local-only
2357     mStatus mDNSPlatformStatus;
2358     mDNSIPPort UnicastPort4;
2359     mDNSIPPort UnicastPort6;
2360     mDNSEthAddr PrimaryMAC;             // Used as unique host ID
2361     mDNSCallback *MainCallback;
2362     void         *MainContext;
2363 
2364     // For debugging: To catch and report locking failures
2365     mDNSu32 mDNS_busy;                  // Incremented between mDNS_Lock/mDNS_Unlock section
2366     mDNSu32 mDNS_reentrancy;            // Incremented when calling a client callback
2367     const char *mDNS_Lock_functionname;           // Where was the last lock taken
2368     int   mDNS_Lock_lineno;                                 // and line number:
2369     mDNSu8 lock_rrcache;                // For debugging: Set at times when these lists may not be modified
2370     mDNSu8 lock_Questions;
2371     mDNSu8 lock_Records;
2372 
2373     // Task Scheduling variables
2374     mDNSs32 timenow_adjust;             // Correction applied if we ever discover time went backwards
2375     mDNSs32 timenow;                    // The time that this particular activation of the mDNS code started
2376     mDNSs32 timenow_last;               // The time the last time we ran
2377     mDNSs32 NextScheduledEvent;         // Derived from values below
2378     mDNSs32 ShutdownTime;               // Set when we're shutting down; allows us to skip some unnecessary steps
2379     mDNSs32 SuppressQueries;            // Don't send local-link mDNS queries during this time
2380     mDNSs32 SuppressResponses;          // Don't send local-link mDNS responses during this time
2381     mDNSs32 NextCacheCheck;             // Next time to refresh cache record before it expires
2382     mDNSs32 NextScheduledQuery;         // Next time to send query in its exponential backoff sequence
2383     mDNSs32 NextScheduledProbe;         // Next time to probe for new authoritative record
2384     mDNSs32 NextScheduledResponse;      // Next time to send authoritative record(s) in responses
2385     mDNSs32 NextScheduledNATOp;         // Next time to send NAT-traversal packets
2386     mDNSs32 NextScheduledSPS;           // Next time to purge expiring Sleep Proxy records
2387     mDNSs32 NextScheduledKA;            // Next time to send Keepalive packets (SPS)
2388 #if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
2389     mDNSs32 NextBonjourDisableTime;     // Next time to leave multicast group if Bonjour on Demand is enabled
2390     mDNSu8 BonjourEnabled;              // Non zero if Bonjour is currently enabled by the Bonjour on Demand logic
2391 #endif
2392     mDNSs32 RandomQueryDelay;           // For de-synchronization of query packets on the wire
2393     mDNSu32 RandomReconfirmDelay;       // For de-synchronization of reconfirmation queries on the wire
2394     mDNSs32 PktNum;                     // Unique sequence number assigned to each received packet
2395     mDNSs32 MPktNum;                    // Unique sequence number assigned to each received Multicast packet
2396     mDNSu8 LocalRemoveEvents;           // Set if we may need to deliver remove events for local-only questions and/or local-only records
2397     mDNSu8 SleepState;                  // Set if we're sleeping
2398     mDNSu8 SleepSeqNum;                 // "Epoch number" of our current period of wakefulness
2399     mDNSu8 SystemWakeOnLANEnabled;      // Set if we want to register with a Sleep Proxy before going to sleep
2400 #if MDNSRESPONDER_SUPPORTS(COMMON, SPS_CLIENT)
2401     mDNSu8 SentSleepProxyRegistration;  // Set if we registered (or tried to register) with a Sleep Proxy
2402 #endif
2403     mDNSu8 SystemSleepOnlyIfWakeOnLAN;  // Set if we may only sleep if we managed to register with a Sleep Proxy
2404 #if MDNSRESPONDER_SUPPORTS(COMMON, SPS_CLIENT)
2405     mDNSs32 AnnounceOwner;              // After waking from sleep, include OWNER option in packets until this time
2406 #endif
2407     mDNSs32 DelaySleep;                 // To inhibit re-sleeping too quickly right after wake
2408     mDNSs32 SleepLimit;                 // Time window to allow deregistrations, etc.,
2409                                         // during which underying platform layer should inhibit system sleep
2410     mDNSs32 TimeSlept;                  // Time we went to sleep.
2411 
2412 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
2413     mDNSs32 NextUpdateDNSSECValidatedCache; // Next time to update the cache with DNSSEC-validated records.
2414 #endif
2415 
2416 #if MDNSRESPONDER_SUPPORTS(APPLE, RUNTIME_MDNS_METRICS)
2417     mDNSs32 NextMDNSResponseDelayReport;    // Next time to generate a mDNS response delay report.
2418 #endif
2419 
2420     mDNSs32 UnicastPacketsSent;         // Number of unicast packets sent.
2421     mDNSs32 MulticastPacketsSent;       // Number of multicast packets sent.
2422     mDNSs32 RemoteSubnet;               // Multicast packets received from outside our subnet.
2423 
2424     mDNSs32 NextScheduledSPRetry;       // Time next sleep proxy registration action is required.
2425                                         // Only valid if SleepLimit is nonzero and DelaySleep is zero.
2426 
2427     mDNSs32 NextScheduledStopTime;      // Next time to stop a question
2428 
2429     mDNSs32 NextBLEServiceTime;         // Next time to call the BLE discovery management layer.  Non zero when active.
2430 
2431     // These fields only required for mDNS Searcher...
2432     DNSQuestion *Questions;             // List of all registered questions, active and inactive
2433     DNSQuestion *NewQuestions;          // Fresh questions not yet answered from cache
2434     DNSQuestion *CurrentQuestion;       // Next question about to be examined in AnswerLocalQuestions()
2435     DNSQuestion *LocalOnlyQuestions;    // Questions with InterfaceID set to mDNSInterface_LocalOnly or mDNSInterface_P2P
2436     DNSQuestion *NewLocalOnlyQuestions; // Fresh local-only or P2P questions not yet answered
2437     DNSQuestion *RestartQuestion;       // Questions that are being restarted (stop followed by start)
2438     mDNSu32 rrcache_size;               // Total number of available cache entries
2439     mDNSu32 rrcache_totalused;          // Number of cache entries currently occupied
2440     mDNSu32 rrcache_totalused_unicast;  // Number of cache entries currently occupied by unicast
2441     mDNSu32 rrcache_active;             // Number of cache entries currently occupied by records that answer active questions
2442     mDNSu32 rrcache_report;
2443     CacheEntity *rrcache_free;
2444     CacheGroup *rrcache_hash[CACHE_HASH_SLOTS];
2445     mDNSs32 rrcache_nextcheck[CACHE_HASH_SLOTS];
2446 
2447     AuthHash rrauth;
2448 
2449     // Fields below only required for mDNS Responder...
2450     domainlabel nicelabel;              // Rich text label encoded using canonically precomposed UTF-8
2451     domainlabel hostlabel;              // Conforms to RFC 1034 "letter-digit-hyphen" ARPANET host name rules
2452     domainname MulticastHostname;       // Fully Qualified "dot-local" Host Name, e.g. "Foo.local."
2453 #if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
2454     domainname RandomizedHostname;      // Randomized hostname to use for services involving AWDL interfaces. This is to
2455                                         // avoid using a hostname derived from the device's name, which may contain the
2456                                         // owner's real name, (e.g., "Steve's iPhone" -> "Steves-iPhone.local"), which is a
2457                                         // privacy concern.
2458     mDNSu32 AutoTargetAWDLIncludedCount;// Number of registered AWDL-included auto-target records.
2459     mDNSu32 AutoTargetAWDLOnlyCount;    // Number of registered AWDL-only auto-target records.
2460 #endif
2461     UTF8str255 HIHardware;
2462     UTF8str255 HISoftware;
2463     AuthRecord DeviceInfo;
2464     AuthRecord *ResourceRecords;
2465     AuthRecord *DuplicateRecords;       // Records currently 'on hold' because they are duplicates of existing records
2466     AuthRecord *NewLocalRecords;        // Fresh AuthRecords (public) not yet delivered to our local-only questions
2467     AuthRecord *CurrentRecord;          // Next AuthRecord about to be examined
2468     mDNSBool NewLocalOnlyRecords;       // Fresh AuthRecords (local only) not yet delivered to our local questions
2469     NetworkInterfaceInfo *HostInterfaces;
2470     mDNSs32 ProbeFailTime;
2471     mDNSu32 NumFailedProbes;
2472     mDNSs32 SuppressProbes;
2473     mDNSu8 mDNS_plat;               // Why is this here in the “only required for mDNS Responder” section? -- SC
2474 
2475     // Unicast-specific data
2476     mDNSs32 NextuDNSEvent;                  // uDNS next event
2477     mDNSs32 NextSRVUpdate;                  // Time to perform delayed update
2478 
2479 #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
2480     DNSServer        *DNSServers;           // list of DNS servers
2481 #endif
2482     McastResolver    *McastResolvers;       // list of Mcast Resolvers
2483 
2484     mDNSAddr Router;
2485     mDNSAddr AdvertisedV4;                  // IPv4 address pointed to by hostname
2486     mDNSAddr AdvertisedV6;                  // IPv6 address pointed to by hostname
2487 
2488     DomainAuthInfo   *AuthInfoList;         // list of domains requiring authentication for updates
2489 
2490     DNSQuestion ReverseMap;                 // Reverse-map query to find static hostname for service target
2491 
2492     DNSQuestion AutomaticBrowseDomainQ_Internal;    // The internal DNS question started to manage all automatic browse domain events from different sources.
2493 
2494     DomainEnumerationOp *domainsToDoEnumeration; // The list of domain(s) that possibly need(s) to do the domain enumeration.
2495 
2496     domainname StaticHostname;              // Current answer to reverse-map query
2497     domainname FQDN;
2498     HostnameInfo     *Hostnames;            // List of registered hostnames + hostname metadata
2499 
2500     mDNSu32 WABBrowseQueriesCount;          // Number of WAB Browse domain enumeration queries (b, db) callers
2501     mDNSu32 WABLBrowseQueriesCount;         // Number of legacy WAB Browse domain enumeration queries (lb) callers
2502     mDNSu32 WABRegQueriesCount;             // Number of WAB Registration domain enumeration queries (r, dr) callers
2503     mDNSu8 SearchDomainsHash[MD5_LEN];
2504 
2505     // NAT-Traversal fields
2506 #if MDNSRESPONDER_SUPPORTS(COMMON, DNS_LLQ)
2507     NATTraversalInfo LLQNAT;                    // Single shared NAT Traversal to receive inbound LLQ notifications
2508 #endif
2509     NATTraversalInfo *NATTraversals;
2510     NATTraversalInfo *CurrentNATTraversal;
2511     mDNSs32 retryIntervalGetAddr;               // delta between time sent and retry for NAT-PMP & UPnP/IGD external address request
2512     mDNSs32 retryGetAddr;                       // absolute time when we retry for NAT-PMP & UPnP/IGD external address request
2513     mDNSv4Addr ExtAddress;                      // the external address discovered via NAT-PMP or UPnP/IGD
2514     mDNSu32 PCPNonce[3];                        // the nonce if using PCP
2515 
2516     UDPSocket        *NATMcastRecvskt;          // For receiving PCP & NAT-PMP announcement multicasts from router on port 5350
2517     mDNSu32 LastNATupseconds;                   // NAT engine uptime in seconds, from most recent NAT packet
2518     mDNSs32 LastNATReplyLocalTime;              // Local time in ticks when most recent NAT packet was received
2519     mDNSu16 LastNATMapResultCode;               // Most recent error code for mappings
2520 
2521     tcpLNTInfo tcpAddrInfo;                     // legacy NAT traversal TCP connection info for external address
2522     tcpLNTInfo tcpDeviceInfo;                   // legacy NAT traversal TCP connection info for device info
2523     tcpLNTInfo       *tcpInfoUnmapList;         // list of pending unmap requests
2524     mDNSInterfaceID UPnPInterfaceID;
2525     UDPSocket        *SSDPSocket;               // For SSDP request/response
2526     mDNSBool SSDPWANPPPConnection;              // whether we should send the SSDP query for WANIPConnection or WANPPPConnection
2527     mDNSIPPort UPnPRouterPort;                  // port we send discovery messages to
2528     mDNSIPPort UPnPSOAPPort;                    // port we send SOAP messages to
2529     char             *UPnPRouterURL;            // router's URL string
2530     mDNSBool UPnPWANPPPConnection;              // whether we're using WANIPConnection or WANPPPConnection
2531     char             *UPnPSOAPURL;              // router's SOAP control URL string
2532     char             *UPnPRouterAddressString;  // holds both the router's address and port
2533     char             *UPnPSOAPAddressString;    // holds both address and port for SOAP messages
2534 
2535     // DNS Push fields
2536     DNSPushServer *DNSPushServers;
2537     DNSPushZone   *DNSPushZones;
2538 
2539     // Sleep Proxy client fields
2540     AuthRecord *SPSRRSet;                       // To help the client keep track of the records registered with the sleep proxy
2541 
2542     // Sleep Proxy Server fields
2543     mDNSu8 SPSType;                             // 0 = off, 10-99 encodes desirability metric
2544     mDNSu8 SPSPortability;                      // 10-99
2545     mDNSu8 SPSMarginalPower;                    // 10-99
2546     mDNSu8 SPSTotalPower;                       // 10-99
2547     mDNSu8 SPSFeatureFlags;                     // Features supported. Currently 1 = TCP KeepAlive supported.
2548     mDNSu8 SPSState;                            // 0 = off, 1 = running, 2 = shutting down, 3 = suspended during sleep
2549     mDNSInterfaceID SPSProxyListChanged;
2550     UDPSocket        *SPSSocket;
2551 #ifndef SPC_DISABLED
2552     ServiceRecordSet SPSRecords;
2553 #endif
2554 #if MDNSRESPONDER_SUPPORTS(COMMON, SPS_CLIENT)
2555     mDNSQuestionCallback *SPSBrowseCallback;    // So the platform layer can do something useful with SPS browse results
2556 #endif
2557     int ProxyRecords;                           // Total number of records we're holding as proxy
2558     #define           MAX_PROXY_RECORDS 10000   /* DOS protection: 400 machines at 25 records each */
2559 
2560 #if MDNSRESPONDER_SUPPORTS(APPLE, WEB_CONTENT_FILTER)
2561     WCFConnection    *WCF;
2562 #endif
2563     int             notifyToken;
2564     int             uds_listener_skt;           // Listening socket for incoming UDS clients. This should not be here -- it's private to uds_daemon.c and nothing to do with mDNSCore -- SC
2565     mDNSu32         AutoTargetServices;         // # of services that have AutoTarget set
2566 
2567 #if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
2568     // Counters used in Bonjour on Demand logic.
2569     mDNSu32         NumAllInterfaceRecords;     // Right now we count *all* multicast records here. Later we may want to change to count interface-specific records separately. (This count includes records on the DuplicateRecords list too.)
2570     mDNSu32         NumAllInterfaceQuestions;   // Right now we count *all* multicast questions here. Later we may want to change to count interface-specific questions separately.
2571 #endif
2572 
2573     mDNSStatistics   mDNSStats;
2574 
2575 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
2576     dnssec_obj_trust_anchor_manager_t   DNSSECTrustAnchorManager;   // The trust anchor manager manages all the useful anchors for DNSSEC.
2577 #endif
2578 
2579     // Fixed storage, to avoid creating large objects on the stack
2580     // The imsg is declared as a union with a pointer type to enforce CPU-appropriate alignment
2581     union { DNSMessage m; void *p; } imsg;  // Incoming message received from wire
2582     DNSMessage omsg;                        // Outgoing message we're building
2583     LargeCacheRecord rec;                   // Resource Record extracted from received message
2584 
2585 #ifndef MaxMsg
2586     #define MaxMsg 512
2587 #endif
2588     mDNSu8 RDataBuffer[MaxMsg];             // Temp storage used to construct rrtype + rdata bytes for logging.
2589     char MsgBuffer[MaxMsg];                 // Temp storage used while building error log messages (keep at end of struct)
2590 };
2591 
2592 #define FORALL_CACHEGROUPS(SLOT,CG)                               \
2593     for ((SLOT) = 0; (SLOT) < CACHE_HASH_SLOTS; (SLOT)++)         \
2594         for ((CG)=m->rrcache_hash[(SLOT)]; (CG); (CG)=(CG)->next)
2595 
2596 #define FORALL_CACHERECORDS(SLOT,CG,CR)                           \
2597     FORALL_CACHEGROUPS(SLOT,CG)                                   \
2598         for ((CR) = (CG)->members; (CR); (CR)=(CR)->next)
2599 
2600 // ***************************************************************************
2601 #if 0
2602 #pragma mark -
2603 #pragma mark - Useful Static Constants
2604 #endif
2605 
2606 extern const mDNSInterfaceID mDNSInterface_Any;             // Zero
2607 extern const mDNSInterfaceID mDNSInterface_LocalOnly;       // Special value
2608 extern const mDNSInterfaceID mDNSInterfaceMark;             // Special value
2609 extern const mDNSInterfaceID mDNSInterface_P2P;             // Special value
2610 extern const mDNSInterfaceID uDNSInterfaceMark;             // Special value
2611 extern const mDNSInterfaceID mDNSInterface_BLE;             // Special value
2612 
2613 #define LocalOnlyOrP2PInterface(INTERFACE)  (((INTERFACE) == mDNSInterface_LocalOnly) || ((INTERFACE) == mDNSInterface_P2P) || ((INTERFACE) == mDNSInterface_BLE))
2614 
2615 extern const mDNSIPPort DiscardPort;
2616 extern const mDNSIPPort SSHPort;
2617 extern const mDNSIPPort UnicastDNSPort;
2618 extern const mDNSIPPort SSDPPort;
2619 extern const mDNSIPPort IPSECPort;
2620 extern const mDNSIPPort NSIPCPort;
2621 extern const mDNSIPPort NATPMPAnnouncementPort;
2622 extern const mDNSIPPort NATPMPPort;
2623 extern const mDNSIPPort DNSEXTPort;
2624 extern const mDNSIPPort MulticastDNSPort;
2625 extern const mDNSIPPort LoopbackIPCPort;
2626 extern const mDNSIPPort PrivateDNSPort;
2627 
2628 extern const OwnerOptData zeroOwner;
2629 
2630 extern const mDNSIPPort zeroIPPort;
2631 extern const mDNSv4Addr zerov4Addr;
2632 extern const mDNSv6Addr zerov6Addr;
2633 extern const mDNSEthAddr zeroEthAddr;
2634 extern const mDNSv4Addr onesIPv4Addr;
2635 extern const mDNSv6Addr onesIPv6Addr;
2636 extern const mDNSEthAddr onesEthAddr;
2637 extern const mDNSAddr zeroAddr;
2638 
2639 extern const mDNSv4Addr AllDNSAdminGroup;
2640 extern const mDNSv4Addr AllHosts_v4;
2641 extern const mDNSv6Addr AllHosts_v6;
2642 extern const mDNSv6Addr NDP_prefix;
2643 extern const mDNSEthAddr AllHosts_v6_Eth;
2644 extern const mDNSAddr AllDNSLinkGroup_v4;
2645 extern const mDNSAddr AllDNSLinkGroup_v6;
2646 
2647 extern const mDNSOpaque16 zeroID;
2648 extern const mDNSOpaque16 onesID;
2649 extern const mDNSOpaque16 QueryFlags;
2650 extern const mDNSOpaque16 uQueryFlags;
2651 extern const mDNSOpaque16 ResponseFlags;
2652 extern const mDNSOpaque16 UpdateReqFlags;
2653 extern const mDNSOpaque16 UpdateRespFlags;
2654 extern const mDNSOpaque16 SubscribeFlags;
2655 extern const mDNSOpaque16 UnSubscribeFlags;
2656 extern const mDNSOpaque16 uDNSSecQueryFlags;
2657 
2658 extern const mDNSOpaque64 zeroOpaque64;
2659 extern const mDNSOpaque128 zeroOpaque128;
2660 
2661 extern mDNSBool StrictUnicastOrdering;
2662 
2663 #define localdomain           (*(const domainname *)"\x5" "local")
2664 #define DeviceInfoName        (*(const domainname *)"\xC" "_device-info" "\x4" "_tcp")
2665 #define LocalDeviceInfoName   (*(const domainname *)"\xC" "_device-info" "\x4" "_tcp" "\x5" "local")
2666 #define SleepProxyServiceType (*(const domainname *)"\xC" "_sleep-proxy" "\x4" "_udp")
2667 
2668 #if MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
2669     // Change `Do53_UNICAST_DISCOVERY_DOMAIN` to a non-root domain to do Do53 service discovery under this domain.
2670     #define Do53_UNICAST_DISCOVERY_DOMAIN ((const domainname *) "")
2671 #endif // MDNSRESPONDER_SUPPORTS(COMMON, LOCAL_DNS_RESOLVER_DISCOVERY)
2672 
2673 // ***************************************************************************
2674 #if 0
2675 #pragma mark -
2676 #pragma mark - Inline functions
2677 #endif
2678 
2679 #if (defined(_MSC_VER))
2680     #define mDNSinline static __inline
2681 #elif ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9))) || defined(__lint__)
2682     #define mDNSinline static inline
2683 #endif
2684 
2685 // If we're not doing inline functions, then this header needs to have the extern declarations
2686 #if !defined(mDNSinline)
2687 #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
2688 extern int          CountOfUnicastDNSServers(mDNS *const m);
2689 #endif
2690 extern mDNSs32      NonZeroTime(mDNSs32 t);
2691 extern mDNSu16      mDNSVal16(mDNSOpaque16 x);
2692 extern mDNSOpaque16 mDNSOpaque16fromIntVal(mDNSu16 v);
2693 #endif
2694 
2695 // If we're compiling the particular C file that instantiates our inlines, then we
2696 // define "mDNSinline" (to empty string) so that we generate code in the following section
2697 #if (!defined(mDNSinline) && mDNS_InstantiateInlines)
2698 #define mDNSinline
2699 #endif
2700 
2701 #ifdef mDNSinline
2702 
2703 #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
CountOfUnicastDNSServers(mDNS * const m)2704 mDNSinline int CountOfUnicastDNSServers(mDNS *const m)
2705 {
2706     int count = 0;
2707     DNSServer *ptr = m->DNSServers;
2708     while(ptr) { if(!(ptr->flags & DNSServerFlag_Delete)) count++; ptr = ptr->next; }
2709     return (count);
2710 }
2711 #endif
2712 
NonZeroTime(mDNSs32 t)2713 mDNSinline mDNSs32 NonZeroTime(mDNSs32 t) { if (t) return(t);else return(1);}
2714 
mDNSVal16(mDNSOpaque16 x)2715 mDNSinline mDNSu16 mDNSVal16(mDNSOpaque16 x) { return((mDNSu16)((mDNSu16)x.b[0] <<  8 | (mDNSu16)x.b[1])); }
2716 
mDNSOpaque16fromIntVal(mDNSu16 v)2717 mDNSinline mDNSOpaque16 mDNSOpaque16fromIntVal(mDNSu16 v)
2718 {
2719     mDNSOpaque16 x;
2720     x.b[0] = (mDNSu8)(v >> 8);
2721     x.b[1] = (mDNSu8)(v & 0xFF);
2722     return(x);
2723 }
2724 
mDNSVal32(mDNSOpaque32 x)2725 mDNSinline mDNSu32 mDNSVal32(mDNSOpaque32 x)
2726 {
2727     return((mDNSu32)((((mDNSu32)x.b[0]) << 24) | (((mDNSu32)x.b[1]) << 16) | (((mDNSu32)x.b[2]) << 8) | (mDNSu32)x.b[3]));
2728 }
2729 
2730 #endif
2731 
2732 // ***************************************************************************
2733 #if 0
2734 #pragma mark -
2735 #pragma mark - Main Client Functions
2736 #endif
2737 
2738 // Every client should call mDNS_Init, passing in storage for the mDNS object and the mDNS_PlatformSupport object.
2739 //
2740 // Clients that are only advertising services should use mDNS_Init_NoCache and mDNS_Init_ZeroCacheSize.
2741 // Clients that plan to perform queries (mDNS_StartQuery, mDNS_StartBrowse, etc.)
2742 // need to provide storage for the resource record cache, or the query calls will return 'mStatus_NoCache'.
2743 // The rrcachestorage parameter is the address of memory for the resource record cache, and
2744 // the rrcachesize parameter is the number of entries in the CacheRecord array passed in.
2745 // (i.e. the size of the cache memory needs to be sizeof(CacheRecord) * rrcachesize).
2746 // OS X 10.3 Panther uses an initial cache size of 64 entries, and then mDNSCore sends an
2747 // mStatus_GrowCache message if it needs more.
2748 //
2749 // Most clients should use mDNS_Init_AdvertiseLocalAddresses. This causes mDNSCore to automatically
2750 // create the correct address records for all the hosts interfaces. If you plan to advertise
2751 // services being offered by the local machine, this is almost always what you want.
2752 // There are two cases where you might use mDNS_Init_DontAdvertiseLocalAddresses:
2753 // 1. A client-only device, that browses for services but doesn't advertise any of its own.
2754 // 2. A proxy-registration service, that advertises services being offered by other machines, and takes
2755 //    the appropriate steps to manually create the correct address records for those other machines.
2756 // In principle, a proxy-like registration service could manually create address records for its own machine too,
2757 // but this would be pointless extra effort when using mDNS_Init_AdvertiseLocalAddresses does that for you.
2758 //
2759 // Note that a client-only device that wishes to prohibit multicast advertisements (e.g. from
2760 // higher-layer API calls) must also set DivertMulticastAdvertisements in the mDNS structure and
2761 // advertise local address(es) on a loopback interface.
2762 //
2763 // When mDNS has finished setting up the client's callback is called
2764 // A client can also spin and poll the mDNSPlatformStatus field to see when it changes from mStatus_Waiting to mStatus_NoError
2765 //
2766 // Call mDNS_StartExit to tidy up before exiting
2767 // Because exiting may be an asynchronous process (e.g. if unicast records need to be deregistered)
2768 // client layer may choose to wait until mDNS_ExitNow() returns true before calling mDNS_FinalExit().
2769 //
2770 // Call mDNS_Register with a completed AuthRecord object to register a resource record
2771 // If the resource record type is kDNSRecordTypeUnique (or kDNSknownunique) then if a conflicting resource record is discovered,
2772 // the resource record's mDNSRecordCallback will be called with error code mStatus_NameConflict. The callback should deregister
2773 // the record, and may then try registering the record again after picking a new name (e.g. by automatically appending a number).
2774 // Following deregistration, the RecordCallback will be called with result mStatus_MemFree to signal that it is safe to deallocate
2775 // the record's storage (memory must be freed asynchronously to allow for goodbye packets and dynamic update deregistration).
2776 //
2777 // Call mDNS_StartQuery to initiate a query. mDNS will proceed to issue Multicast DNS query packets, and any time a response
2778 // is received containing a record which matches the question, the DNSQuestion's mDNSAnswerCallback function will be called
2779 // Call mDNS_StopQuery when no more answers are required
2780 //
2781 // Care should be taken on multi-threaded or interrupt-driven environments.
2782 // The main mDNS routines call mDNSPlatformLock() on entry and mDNSPlatformUnlock() on exit;
2783 // each platform layer needs to implement these appropriately for its respective platform.
2784 // For example, if the support code on a particular platform implements timer callbacks at interrupt time, then
2785 // mDNSPlatformLock/Unlock need to disable interrupts or do similar concurrency control to ensure that the mDNS
2786 // code is not entered by an interrupt-time timer callback while in the middle of processing a client call.
2787 
2788 extern mStatus mDNS_Init      (mDNS *const m, mDNS_PlatformSupport *const p,
2789                                CacheEntity *rrcachestorage, mDNSu32 rrcachesize,
2790                                mDNSBool AdvertiseLocalAddresses,
2791                                mDNSCallback *Callback, void *Context);
2792 // See notes above on use of NoCache/ZeroCacheSize
2793 #define mDNS_Init_NoCache                     mDNSNULL
2794 #define mDNS_Init_ZeroCacheSize               0
2795 // See notes above on use of Advertise/DontAdvertiseLocalAddresses
2796 #define mDNS_Init_AdvertiseLocalAddresses     mDNStrue
2797 #define mDNS_Init_DontAdvertiseLocalAddresses mDNSfalse
2798 #define mDNS_Init_NoInitCallback              mDNSNULL
2799 #define mDNS_Init_NoInitCallbackContext       mDNSNULL
2800 
2801 extern void    mDNS_ConfigChanged(mDNS *const m);
2802 extern void    mDNS_GrowCache (mDNS *const m, CacheEntity *storage, mDNSu32 numrecords);
2803 extern void    mDNS_StartExit (mDNS *const m);
2804 extern void    mDNS_FinalExit (mDNS *const m);
2805 #define mDNS_Close(m) do { mDNS_StartExit(m); mDNS_FinalExit(m); } while(0)
2806 #define mDNS_ExitNow(m, now) ((now) - (m)->ShutdownTime >= 0 || (!(m)->ResourceRecords))
2807 
2808 extern mDNSs32 mDNS_Execute   (mDNS *const m);
2809 
2810 extern mStatus mDNS_Register  (mDNS *const m, AuthRecord *const rr);
2811 extern mStatus mDNS_Update    (mDNS *const m, AuthRecord *const rr, mDNSu32 newttl,
2812                                const mDNSu16 newrdlength, RData *const newrdata, mDNSRecordUpdateCallback *Callback);
2813 extern mStatus mDNS_Deregister(mDNS *const m, AuthRecord *const rr);
2814 
2815 extern mStatus mDNS_StartQuery(mDNS *const m, DNSQuestion *const question);
2816 extern mStatus mDNS_StopQuery (mDNS *const m, DNSQuestion *const question);
2817 extern mStatus mDNS_StopQueryWithRemoves(mDNS *const m, DNSQuestion *const question);
2818 extern mStatus mDNS_Reconfirm (mDNS *const m, CacheRecord *const cacherr);
2819 extern mStatus mDNS_Reconfirm_internal(mDNS *const m, CacheRecord *const rr, mDNSu32 interval);
2820 extern mStatus mDNS_ReconfirmByValue(mDNS *const m, ResourceRecord *const rr);
2821 extern void    mDNS_PurgeCacheResourceRecord(mDNS *const m, CacheRecord *rr);
2822 extern mDNSs32 mDNS_TimeNow(const mDNS *const m);
2823 
2824 extern mStatus mDNS_StartNATOperation(mDNS *const m, NATTraversalInfo *traversal);
2825 extern mStatus mDNS_StopNATOperation(mDNS *const m, NATTraversalInfo *traversal);
2826 extern mStatus mDNS_StopNATOperation_internal(mDNS *m, NATTraversalInfo *traversal);
2827 
2828 extern DomainAuthInfo *GetAuthInfoForName(mDNS *m, const domainname *const name);
2829 
2830 extern void    mDNS_UpdateAllowSleep(mDNS *const m);
2831 
2832 // ***************************************************************************
2833 #if 0
2834 #pragma mark -
2835 #pragma mark - Platform support functions that are accessible to the client layer too
2836 #endif
2837 
2838 extern mDNSs32 mDNSPlatformOneSecond;
2839 
2840 // ***************************************************************************
2841 #if 0
2842 #pragma mark -
2843 #pragma mark - General utility and helper functions
2844 #endif
2845 
2846 // mDNS_Dereg_normal is used for most calls to mDNS_Deregister_internal
2847 // mDNS_Dereg_rapid is used to send one goodbye instead of three, when we want the memory available for reuse sooner
2848 // mDNS_Dereg_conflict is used to indicate that this record is being forcibly deregistered because of a conflict
2849 // mDNS_Dereg_repeat is used when cleaning up, for records that may have already been forcibly deregistered
2850 // mDNS_Dereg_stale is used when the registered record has been superseded by another host
2851 typedef enum { mDNS_Dereg_normal, mDNS_Dereg_rapid, mDNS_Dereg_conflict, mDNS_Dereg_repeat, mDNS_Dereg_stale } mDNS_Dereg_type;
2852 
2853 // mDNS_RegisterService is a single call to register the set of resource records associated with a given named service.
2854 //
2855 //
2856 // mDNS_AddRecordToService adds an additional record to a Service Record Set.  This record may be deregistered
2857 // via mDNS_RemoveRecordFromService, or by deregistering the service.  mDNS_RemoveRecordFromService is passed a
2858 // callback to free the memory associated with the extra RR when it is safe to do so.  The ExtraResourceRecord
2859 // object can be found in the record's context pointer.
2860 
2861 // mDNS_GetBrowseDomains is a special case of the mDNS_StartQuery call, where the resulting answers
2862 // are a list of PTR records indicating (in the rdata) domains that are recommended for browsing.
2863 // After getting the list of domains to browse, call mDNS_StopQuery to end the search.
2864 // mDNS_GetDefaultBrowseDomain returns the name of the domain that should be highlighted by default.
2865 //
2866 // mDNS_GetRegistrationDomains and mDNS_GetDefaultRegistrationDomain are the equivalent calls to get the list
2867 // of one or more domains that should be offered to the user as choices for where they may register their service,
2868 // and the default domain in which to register in the case where the user has made no selection.
2869 
2870 extern void    mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mDNSInterfaceID InterfaceID,
2871                                         mDNSu16 rrtype, mDNSu32 ttl, mDNSu8 RecordType, AuthRecType artype, mDNSRecordCallback Callback, void *Context);
2872 
2873 extern mStatus mDNS_RegisterService  (mDNS *const m, ServiceRecordSet *sr,
2874                                       const domainlabel *const name, const domainname *const type, const domainname *const domain,
2875                                       const domainname *const host, mDNSIPPort port, RData *txtrdata, const mDNSu8 txtinfo[], mDNSu16 txtlen,
2876                                       AuthRecord *SubTypes, mDNSu32 NumSubTypes,
2877                                       mDNSInterfaceID InterfaceID, mDNSServiceCallback Callback, void *Context, mDNSu32 flags);
2878 extern mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra, RData *rdata, mDNSu32 ttl,  mDNSu32 flags);
2879 extern mStatus mDNS_RemoveRecordFromService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra, mDNSRecordCallback MemFreeCallback, void *Context);
2880 extern mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordSet *const sr, const domainlabel *newname);
2881 extern mStatus mDNS_DeregisterService_drt(mDNS *const m, ServiceRecordSet *sr, mDNS_Dereg_type drt);
2882 #define mDNS_DeregisterService(M,S) mDNS_DeregisterService_drt((M), (S), mDNS_Dereg_normal)
2883 
2884 extern mStatus mDNS_RegisterNoSuchService(mDNS *const m, AuthRecord *const rr,
2885                                           const domainlabel *const name, const domainname *const type, const domainname *const domain,
2886                                           const domainname *const host,
2887                                           const mDNSInterfaceID InterfaceID, mDNSRecordCallback Callback, void *Context, mDNSu32 flags);
2888 #define        mDNS_DeregisterNoSuchService mDNS_Deregister
2889 
2890 extern void mDNS_SetupQuestion(DNSQuestion *const q, const mDNSInterfaceID InterfaceID, const domainname *const name,
2891                                const mDNSu16 qtype, mDNSQuestionCallback *const callback, void *const context);
2892 
2893 extern mStatus mDNS_StartBrowse(mDNS *const m, DNSQuestion *const question,
2894                                 const domainname *const srv, const domainname *const domain,
2895                                 const mDNSInterfaceID InterfaceID, mDNSu32 flags,
2896                                 mDNSBool ForceMCast, mDNSBool useBackgroundTrafficClass,
2897                                 mDNSQuestionCallback *Callback, void *Context);
2898 #define        mDNS_StopBrowse mDNS_StopQuery
2899 
2900 
2901 extern const char *const mDNS_DomainTypeNames[];
2902 
2903 extern mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, mDNS_DomainType DomainType, const domainname *dom,
2904                                const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *Callback, void *Context);
2905 #define        mDNS_StopGetDomains mDNS_StopQuery
2906 #define        mDNS_StopGetDomains_Internal mDNS_StopQuery_internal
2907 extern mStatus mDNS_AdvertiseDomains(mDNS *const m, AuthRecord *rr, mDNS_DomainType DomainType, const mDNSInterfaceID InterfaceID, char *domname);
2908 #define        mDNS_StopAdvertiseDomains mDNS_Deregister
2909 
2910 // Function that is used to do domain enumeration.
2911 extern mStatus mDNS_StartDomainEnumeration(mDNS *m, const domainname *domain, mDNS_DomainType type);
2912 extern mStatus mDNS_StopDomainEnumeration(mDNS *m, const domainname *domain, mDNS_DomainType type);
2913 extern mStatus mDNS_AddDomainDiscoveredForDomainEnumeration(mDNS *m, const domainname *domain, mDNS_DomainType type,
2914                                                             const domainname *domainDiscovered);
2915 extern mStatus mDNS_RemoveDomainDiscoveredForDomainEnumeration(mDNS *m, const domainname *domain, mDNS_DomainType type,
2916                                                                const domainname *domainDiscovered);
2917 extern void FoundNonLocalOnlyAutomaticBrowseDomain(mDNS *m, DNSQuestion *q, const ResourceRecord *answer, QC_result add_record);
2918 extern void DeregisterLocalOnlyDomainEnumPTR_Internal(mDNS *m, const domainname *d, int type, mDNSBool lockHeld);
2919 
2920 extern mDNSOpaque16 mDNS_NewMessageID(mDNS *const m);
2921 extern mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr);
2922 
2923 #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
2924 extern DNSServer *GetServerForQuestion(mDNS *m, DNSQuestion *question);
2925 #endif
2926 extern mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question);
2927 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
2928 extern mDNSBool ShouldSuppressUnicastQuery(const DNSQuestion *q, mdns_dns_service_t dnsservice);
2929 extern mDNSBool LocalRecordRmvEventsForQuestion(mDNS *m, DNSQuestion *q);
2930 #endif
2931 
2932 // ***************************************************************************
2933 #if 0
2934 #pragma mark -
2935 #pragma mark - DNS name utility functions
2936 #endif
2937 
2938 // In order to expose the full capabilities of the DNS protocol (which allows any arbitrary eight-bit values
2939 // in domain name labels, including unlikely characters like ascii nulls and even dots) all the mDNS APIs
2940 // work with DNS's native length-prefixed strings. For convenience in C, the following utility functions
2941 // are provided for converting between C's null-terminated strings and DNS's length-prefixed strings.
2942 
2943 // Assignment
2944 // A simple C structure assignment of a domainname can cause a protection fault by accessing unmapped memory,
2945 // because that object is defined to be 256 bytes long, but not all domainname objects are truly the full size.
2946 // This macro uses mDNSPlatformMemCopy() to make sure it only touches the actual bytes that are valid.
2947 #define AssignDomainName(DST, SRC) do { mDNSu16 len__ = DomainNameLength((SRC)); \
2948     if (len__ <= MAX_DOMAIN_NAME) mDNSPlatformMemCopy((DST)->c, (SRC)->c, len__); else (DST)->c[0] = 0; } while(0)
2949 #define AssignConstStringDomainName(DST, SRC) do { \
2950     mDNSu16 len__ = DomainNameLengthLimit((domainname *)(SRC), (mDNSu8 *)(SRC) + sizeof (SRC)); \
2951     if (len__ <= MAX_DOMAIN_NAME) \
2952         mDNSPlatformMemCopy((DST)->c, (SRC), len__); else (DST)->c[0] = 0; } while(0)
2953 
2954 // Comparison functions
2955 #define SameDomainLabelCS(A,B) ((A)[0] == (B)[0] && mDNSPlatformMemSame((A)+1, (B)+1, (A)[0]))
2956 extern mDNSBool SameDomainLabel(const mDNSu8 *a, const mDNSu8 *b);
2957 extern mDNSBool SameDomainName(const domainname *const d1, const domainname *const d2);
2958 extern mDNSBool SameDomainNameBytes(const mDNSu8 *d1, const mDNSu8 *d2);
2959 extern mDNSBool SameDomainNameCS(const domainname *const d1, const domainname *const d2);
2960 typedef mDNSBool DomainNameComparisonFn (const domainname *const d1, const domainname *const d2);
2961 extern mDNSBool IsLocalDomain(const domainname *d);     // returns true for domains that by default should be looked up using link-local multicast
2962 extern mDNSBool SameResourceRecordNameClassInterface(const AuthRecord *r1, const AuthRecord *r2);
2963 
2964 #define StripFirstLabel(X) ((const domainname *)& (X)->c[(X)->c[0] ? 1 + (X)->c[0] : 0])
2965 
2966 #define FirstLabel(X)  ((const domainlabel *)(X))
2967 #define SecondLabel(X) ((const domainlabel *)StripFirstLabel(X))
2968 #define ThirdLabel(X)  ((const domainlabel *)StripFirstLabel(StripFirstLabel(X)))
2969 
2970 extern mDNSBool IsRootDomain(const domainname *d);
2971 extern const mDNSu8 *LastLabel(const domainname *d);
2972 
2973 // Get total length of domain name, in native DNS format, including terminal root label
2974 //   (e.g. length of "com." is 5 (length byte, three data bytes, final zero)
2975 extern mDNSu16  DomainNameLengthLimit(const domainname *const name, const mDNSu8 *limit);
2976 #define DomainNameLength(name) DomainNameLengthLimit((name), (name)->c + MAX_DOMAIN_NAME)
2977 extern mDNSu16 DomainNameBytesLength(const mDNSu8 *name, const mDNSu8 *limit);
2978 
2979 extern mDNSu8 DomainLabelLength(const domainlabel *const label);
2980 
2981 // Append functions to append one or more labels to an existing native format domain name:
2982 //   AppendLiteralLabelString adds a single label from a literal C string, with no escape character interpretation.
2983 //   AppendDNSNameString      adds zero or more labels from a C string using conventional DNS dots-and-escaping interpretation
2984 //   AppendDomainLabel        adds a single label from a native format domainlabel
2985 //   AppendDomainName         adds zero or more labels from a native format domainname
2986 extern mDNSu8  *AppendLiteralLabelString(domainname *const name, const char *cstr);
2987 extern mDNSu8  *AppendDNSNameString     (domainname *const name, const char *cstr);
2988 extern mDNSu8  *AppendDomainLabel       (domainname *const name, const domainlabel *const label);
2989 extern mDNSu8  *AppendDomainName        (domainname *const name, const domainname *const append);
2990 
2991 // Convert from null-terminated string to native DNS format:
2992 //   The DomainLabel form makes a single label from a literal C string, with no escape character interpretation.
2993 //   The DomainName form makes native format domain name from a C string using conventional DNS interpretation:
2994 //     dots separate labels, and within each label, '\.' represents a literal dot, '\\' represents a literal
2995 //     backslash and backslash with three decimal digits (e.g. \000) represents an arbitrary byte value.
2996 extern mDNSBool MakeDomainLabelFromLiteralString(domainlabel *const label, const char *cstr);
2997 extern mDNSu8  *MakeDomainNameFromDNSNameString (domainname  *const name,  const char *cstr);
2998 
2999 // Convert native format domainlabel or domainname back to C string format
3000 // IMPORTANT:
3001 // When using ConvertDomainLabelToCString, the target buffer must be MAX_ESCAPED_DOMAIN_LABEL (254) bytes long
3002 // to guarantee there will be no buffer overrun. It is only safe to use a buffer shorter than this in rare cases
3003 // where the label is known to be constrained somehow (for example, if the label is known to be either "_tcp" or "_udp").
3004 // Similarly, when using ConvertDomainNameToCString, the target buffer must be MAX_ESCAPED_DOMAIN_NAME (1009) bytes long.
3005 // See definitions of MAX_ESCAPED_DOMAIN_LABEL and MAX_ESCAPED_DOMAIN_NAME for more detailed explanation.
3006 extern char    *ConvertDomainLabelToCString_withescape(const domainlabel *const name, char *cstr, char esc);
3007 #define         ConvertDomainLabelToCString_unescaped(D,C) ConvertDomainLabelToCString_withescape((D), (C), 0)
3008 #define         ConvertDomainLabelToCString(D,C)           ConvertDomainLabelToCString_withescape((D), (C), '\\')
3009 extern char    *ConvertDomainNameToCString_withescape(const domainname *const name, char *cstr, char esc);
3010 #define         ConvertDomainNameToCString_unescaped(D,C) ConvertDomainNameToCString_withescape((D), (C), 0)
3011 #define         ConvertDomainNameToCString(D,C)           ConvertDomainNameToCString_withescape((D), (C), '\\')
3012 
3013 extern void     ConvertUTF8PstringToRFC1034HostLabel(const mDNSu8 UTF8Name[], domainlabel *const hostlabel);
3014 
3015 #define ValidTransportProtocol(X) ( (X)[0] == 4 && (X)[1] == '_' && \
3016                                     ((((X)[2] | 0x20) == 'u' && ((X)[3] | 0x20) == 'd') || (((X)[2] | 0x20) == 't' && ((X)[3] | 0x20) == 'c')) && \
3017                                     ((X)[4] | 0x20) == 'p')
3018 
3019 extern mDNSu8  *ConstructServiceName(domainname *const fqdn, const domainlabel *name, const domainname *type, const domainname *const domain);
3020 extern mDNSBool DeconstructServiceName(const domainname *const fqdn, domainlabel *const name, domainname *const type, domainname *const domain);
3021 
3022 // Note: Some old functions have been replaced by more sensibly-named versions.
3023 // You can uncomment the hash-defines below if you don't want to have to change your source code right away.
3024 // When updating your code, note that (unlike the old versions) *all* the new routines take the target object
3025 // as their first parameter.
3026 //#define ConvertCStringToDomainName(SRC,DST)  MakeDomainNameFromDNSNameString((DST),(SRC))
3027 //#define ConvertCStringToDomainLabel(SRC,DST) MakeDomainLabelFromLiteralString((DST),(SRC))
3028 //#define AppendStringLabelToName(DST,SRC)     AppendLiteralLabelString((DST),(SRC))
3029 //#define AppendStringNameToName(DST,SRC)      AppendDNSNameString((DST),(SRC))
3030 //#define AppendDomainLabelToName(DST,SRC)     AppendDomainLabel((DST),(SRC))
3031 //#define AppendDomainNameToName(DST,SRC)      AppendDomainName((DST),(SRC))
3032 
3033 // ***************************************************************************
3034 #if 0
3035 #pragma mark -
3036 #pragma mark - Other utility functions and macros
3037 #endif
3038 
3039 // mDNS_vsnprintf/snprintf return the number of characters written, excluding the final terminating null.
3040 // The output is always null-terminated: for example, if the output turns out to be exactly buflen long,
3041 // then the output will be truncated by one character to allow space for the terminating null.
3042 // Unlike standard C vsnprintf/snprintf, they return the number of characters *actually* written,
3043 // not the number of characters that *would* have been printed were buflen unlimited.
3044 extern mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, va_list arg) IS_A_PRINTF_STYLE_FUNCTION(3,0);
3045 extern mDNSu32 mDNS_snprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, ...) IS_A_PRINTF_STYLE_FUNCTION(3,4);
3046 extern void mDNS_snprintf_add(char **dst, const char *lim, const char *fmt, ...) IS_A_PRINTF_STYLE_FUNCTION(3,4);
3047 extern mDNSu32 NumCacheRecordsForInterfaceID(const mDNS *const m, mDNSInterfaceID id);
3048 extern char *DNSTypeName(mDNSu16 rrtype);
3049 extern const char *mStatusDescription(mStatus error);
3050 extern char *GetRRDisplayString_rdb(const ResourceRecord *const rr, const RDataBody *const rd1, char *const buffer);
3051 #define RRDisplayString(m, rr) GetRRDisplayString_rdb(rr, &(rr)->rdata->u, (m)->MsgBuffer)
3052 #define ARDisplayString(m, rr) GetRRDisplayString_rdb(&(rr)->resrec, &(rr)->resrec.rdata->u, (m)->MsgBuffer)
3053 #define CRDisplayString(m, rr) GetRRDisplayString_rdb(&(rr)->resrec, &(rr)->resrec.rdata->u, (m)->MsgBuffer)
3054 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
3055 extern const mDNSu8 *GetPrintableRDataBytes(mDNSu8 *outBuffer, mDNSu32 bufferLen, mDNSu16 recordType,
3056     const mDNSu8 *rdata, mDNSu32 rdataLen);
3057 #endif
3058 #define MortalityDisplayString(M) (M == Mortality_Mortal ? "mortal" : (M == Mortality_Immortal ? "immortal" : "ghost"))
3059 extern mDNSBool mDNSSameAddress(const mDNSAddr *ip1, const mDNSAddr *ip2);
3060 extern void IncrementLabelSuffix(domainlabel *name, mDNSBool RichText);
3061 extern mDNSBool mDNSv4AddrIsRFC1918(const mDNSv4Addr * const addr);  // returns true for RFC1918 private addresses
3062 #define mDNSAddrIsRFC1918(X) ((X)->type == mDNSAddrType_IPv4 && mDNSv4AddrIsRFC1918(&(X)->ip.v4))
3063 extern const char *DNSScopeToString(mDNSu32 scope);
3064 
3065 // For PCP
3066 extern void mDNSAddrMapIPv4toIPv6(mDNSv4Addr* in, mDNSv6Addr* out);
3067 extern mDNSBool mDNSAddrIPv4FromMappedIPv6(mDNSv6Addr *in, mDNSv4Addr *out);
3068 
3069 #define mDNSSameIPPort(A,B)      ((A).NotAnInteger == (B).NotAnInteger)
3070 #define mDNSSameOpaque16(A,B)    ((A).NotAnInteger == (B).NotAnInteger)
3071 #define mDNSSameOpaque32(A,B)    ((A).NotAnInteger == (B).NotAnInteger)
3072 #define mDNSSameOpaque64(A,B)    ((A)->l[0] == (B)->l[0] && (A)->l[1] == (B)->l[1])
3073 
3074 #define mDNSSameIPv4Address(A,B) ((A).NotAnInteger == (B).NotAnInteger)
3075 #define mDNSSameIPv6Address(A,B) ((A).l[0] == (B).l[0] && (A).l[1] == (B).l[1] && (A).l[2] == (B).l[2] && (A).l[3] == (B).l[3])
3076 #define mDNSSameIPv6NetworkPart(A,B) ((A).l[0] == (B).l[0] && (A).l[1] == (B).l[1])
3077 #define mDNSSameEthAddress(A,B)  ((A)->w[0] == (B)->w[0] && (A)->w[1] == (B)->w[1] && (A)->w[2] == (B)->w[2])
3078 
3079 #define mDNSIPPortIsZero(A)      ((A).NotAnInteger                            == 0)
3080 #define mDNSOpaque16IsZero(A)    ((A).NotAnInteger                            == 0)
3081 #define mDNSOpaque64IsZero(A)    (((A)->l[0] | (A)->l[1]                    ) == 0)
3082 #define mDNSOpaque128IsZero(A)   (((A)->l[0] | (A)->l[1] | (A)->l[2] | (A)->l[3]) == 0)
3083 #define mDNSIPv4AddressIsZero(A) ((A).NotAnInteger                            == 0)
3084 #define mDNSIPv6AddressIsZero(A) (((A).l[0] | (A).l[1] | (A).l[2] | (A).l[3]) == 0)
3085 #define mDNSEthAddressIsZero(A)  (((A).w[0] | (A).w[1] | (A).w[2]           ) == 0)
3086 
3087 #define mDNSIPv4AddressIsOnes(A) ((A).NotAnInteger == 0xFFFFFFFF)
3088 #define mDNSIPv6AddressIsOnes(A) (((A).l[0] & (A).l[1] & (A).l[2] & (A).l[3]) == 0xFFFFFFFF)
3089 
3090 #define mDNSAddressIsAllDNSLinkGroup(X) (                                                            \
3091         ((X)->type == mDNSAddrType_IPv4 && mDNSSameIPv4Address((X)->ip.v4, AllDNSLinkGroup_v4.ip.v4)) || \
3092         ((X)->type == mDNSAddrType_IPv6 && mDNSSameIPv6Address((X)->ip.v6, AllDNSLinkGroup_v6.ip.v6))    )
3093 
3094 #define mDNSAddressIsZero(X) (                                                \
3095         ((X)->type == mDNSAddrType_IPv4 && mDNSIPv4AddressIsZero((X)->ip.v4))  || \
3096         ((X)->type == mDNSAddrType_IPv6 && mDNSIPv6AddressIsZero((X)->ip.v6))     )
3097 
3098 #define mDNSAddressIsValidNonZero(X) (                                        \
3099         ((X)->type == mDNSAddrType_IPv4 && !mDNSIPv4AddressIsZero((X)->ip.v4)) || \
3100         ((X)->type == mDNSAddrType_IPv6 && !mDNSIPv6AddressIsZero((X)->ip.v6))    )
3101 
3102 #define mDNSAddressIsOnes(X) (                                                \
3103         ((X)->type == mDNSAddrType_IPv4 && mDNSIPv4AddressIsOnes((X)->ip.v4))  || \
3104         ((X)->type == mDNSAddrType_IPv6 && mDNSIPv6AddressIsOnes((X)->ip.v6))     )
3105 
3106 #define mDNSAddressIsValid(X) (                                                                                             \
3107         ((X)->type == mDNSAddrType_IPv4) ? !(mDNSIPv4AddressIsZero((X)->ip.v4) || mDNSIPv4AddressIsOnes((X)->ip.v4)) :          \
3108         ((X)->type == mDNSAddrType_IPv6) ? !(mDNSIPv6AddressIsZero((X)->ip.v6) || mDNSIPv6AddressIsOnes((X)->ip.v6)) : mDNSfalse)
3109 
3110 #define mDNSv4AddressIsLinkLocal(X) ((X)->b[0] ==  169 &&  (X)->b[1]         ==  254)
3111 #define mDNSv6AddressIsLinkLocal(X) ((X)->b[0] == 0xFE && ((X)->b[1] & 0xC0) == 0x80)
3112 
3113 #define mDNSAddressIsLinkLocal(X)  (                                                    \
3114         ((X)->type == mDNSAddrType_IPv4) ? mDNSv4AddressIsLinkLocal(&(X)->ip.v4) :          \
3115         ((X)->type == mDNSAddrType_IPv6) ? mDNSv6AddressIsLinkLocal(&(X)->ip.v6) : mDNSfalse)
3116 
3117 
3118 // ***************************************************************************
3119 #if 0
3120 #pragma mark -
3121 #pragma mark - Authentication Support
3122 #endif
3123 
3124 // Unicast DNS and Dynamic Update specific Client Calls
3125 //
3126 // mDNS_SetSecretForDomain tells the core to authenticate (via TSIG with an HMAC_MD5 hash of the shared secret)
3127 // when dynamically updating a given zone (and its subdomains).  The key used in authentication must be in
3128 // domain name format.  The shared secret must be a null-terminated base64 encoded string.  A minimum size of
3129 // 16 bytes (128 bits) is recommended for an MD5 hash as per RFC 2485.
3130 // Calling this routine multiple times for a zone replaces previously entered values.  Call with a NULL key
3131 // to disable authentication for the zone.  A non-NULL autoTunnelPrefix means this is an AutoTunnel domain,
3132 // and the value is prepended to the IPSec identifier (used for key lookup)
3133 
3134 extern mStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info,
3135                                        const domainname *domain, const domainname *keyname, const char *b64keydata, const domainname *hostname, mDNSIPPort *port);
3136 
3137 extern void RecreateNATMappings(mDNS *const m, const mDNSu32 waitTicks);
3138 
3139 // Hostname/Unicast Interface Configuration
3140 
3141 // All hostnames advertised point to one IPv4 address and/or one IPv6 address, set via SetPrimaryInterfaceInfo.  Invoking this routine
3142 // updates all existing hostnames to point to the new address.
3143 
3144 // A hostname is added via AddDynDNSHostName, which points to the primary interface's v4 and/or v6 addresss
3145 
3146 // The status callback is invoked to convey success or failure codes - the callback should not modify the AuthRecord or free memory.
3147 // Added hostnames may be removed (deregistered) via mDNS_RemoveDynDNSHostName.
3148 
3149 // Host domains added prior to specification of the primary interface address and computer name will be deferred until
3150 // these values are initialized.
3151 
3152 // DNS servers used to resolve unicast queries are specified by mDNS_AddDNSServer.
3153 // For "split" DNS configurations, in which queries for different domains are sent to different servers (e.g. VPN and external),
3154 // a domain may be associated with a DNS server.  For standard configurations, specify the root label (".") or NULL.
3155 
3156 extern void mDNS_AddDynDNSHostName(mDNS *m, const domainname *fqdn, mDNSRecordCallback *StatusCallback, const void *StatusContext);
3157 extern void mDNS_RemoveDynDNSHostName(mDNS *m, const domainname *fqdn);
3158 extern void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr,  const mDNSAddr *v6addr, const mDNSAddr *router);
3159 #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
3160 extern DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, mDNSs32 serviceID, const mDNSAddr *addr,
3161                                     const mDNSIPPort port, ScopeType scopeType, mDNSu32 timeout, mDNSBool cellIntf, mDNSBool isExpensive, mDNSBool isConstrained, mDNSBool isCLAT46,
3162                                     mDNSu32 resGroupID, mDNSBool reqA, mDNSBool reqAAAA, mDNSBool reqDO);
3163 extern void PenalizeDNSServer(mDNS *const m, DNSQuestion *q, mDNSOpaque16 responseFlags);
3164 #endif
3165 extern void mDNS_AddSearchDomain(const domainname *const domain, mDNSInterfaceID InterfaceID);
3166 
3167 extern McastResolver *mDNS_AddMcastResolver(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, mDNSu32 timeout);
3168 
3169 // We use ((void *)0) here instead of mDNSNULL to avoid compile warnings on gcc 4.2
3170 #define mDNS_AddSearchDomain_CString(X, I) \
3171     do { domainname d__; if (((X) != (void*)0) && MakeDomainNameFromDNSNameString(&d__, (X)) && d__.c[0]) mDNS_AddSearchDomain(&d__, I);} while(0)
3172 
3173 // Routines called by the core, exported by DNSDigest.c
3174 
3175 // Convert an arbitrary base64 encoded key key into an HMAC key (stored in AuthInfo struct)
3176 extern mDNSs32 DNSDigest_ConstructHMACKeyfromBase64(DomainAuthInfo *info, const char *b64key);
3177 
3178 // sign a DNS message.  The message must be complete, with all values in network byte order.  end points to the end
3179 // of the message, and is modified by this routine.  numAdditionals is a pointer to the number of additional
3180 // records in HOST byte order, which is incremented upon successful completion of this routine.  The function returns
3181 // the new end pointer on success, and NULL on failure.
3182 extern void DNSDigest_SignMessage(DNSMessage *msg, mDNSu8 **end, DomainAuthInfo *info, mDNSu16 tcode);
3183 
SwapDNSHeaderBytesWithHeader(DNSMessageHeader * const hdr)3184 static inline void SwapDNSHeaderBytesWithHeader(DNSMessageHeader *const hdr)
3185 {
3186     const mDNSu8 *const questions   = ((const mDNSu8 *)&hdr->numQuestions);
3187     const mDNSu8 *const answers     = ((const mDNSu8 *)&hdr->numAnswers);
3188     const mDNSu8 *const authorities = ((const mDNSu8 *)&hdr->numAuthorities);
3189     const mDNSu8 *const additionals = ((const mDNSu8 *)&hdr->numAdditionals);
3190 
3191     hdr->numQuestions   = (mDNSu16) ((mDNSu16)questions[0]    << 8 | questions[1]);
3192     hdr->numAnswers     = (mDNSu16) ((mDNSu16)answers[0]      << 8 | answers[1]);
3193     hdr->numAuthorities = (mDNSu16) ((mDNSu16)authorities[0]  << 8 | authorities[1]);
3194     hdr->numAdditionals = (mDNSu16) ((mDNSu16)additionals[0]  << 8 | additionals[1]);
3195 }
3196 
SwapDNSHeaderBytes(DNSMessage * const msg)3197 static inline void SwapDNSHeaderBytes(DNSMessage *const msg)
3198 {
3199     SwapDNSHeaderBytesWithHeader(&msg->h);
3200 }
3201 
3202 // verify a DNS message.  The message must be complete, with all values in network byte order.  end points to the
3203 // end of the record.  tsig is a pointer to the resource record that contains the TSIG OPT record.  info is
3204 // the matching key to use for verifying the message.  This function expects that the additionals member
3205 // of the DNS message header has already had one subtracted from it.
3206 extern mDNSBool DNSDigest_VerifyMessage(const DNSMessage *msg, const mDNSu8 *end, const LargeCacheRecord *tsig,
3207     const DomainAuthInfo *info, mDNSu16 *rcode, mDNSu16 *tcode);
3208 
3209 #if defined(DEBUG) && DEBUG
3210 extern void DNSDigest_VerifyMessage_Verify(DNSMessage *msg, const mDNSu8 *end, const DomainAuthInfo *authInfo);
3211 #endif
3212 
3213 // ***************************************************************************
3214 #if 0
3215 #pragma mark -
3216 #pragma mark - PlatformSupport interface
3217 #endif
3218 
3219 // This section defines the interface to the Platform Support layer.
3220 // Normal client code should not use any of types defined here, or directly call any of the functions defined here.
3221 // The definitions are placed here because sometimes clients do use these calls indirectly, via other supported client operations.
3222 // For example, AssignDomainName is a macro defined using mDNSPlatformMemCopy()
3223 
3224 // Every platform support module must provide the following functions.
3225 // mDNSPlatformInit() typically opens a communication endpoint, and starts listening for mDNS packets.
3226 // When Setup is complete, the platform support layer calls mDNSCoreInitComplete().
3227 // mDNSPlatformSendUDP() sends one UDP packet
3228 // When a packet is received, the PlatformSupport code calls mDNSCoreReceive()
3229 // mDNSPlatformClose() tidies up on exit
3230 //
3231 // Note: mDNSPlatformMemAllocate/mDNSPlatformMemFree are only required for handling oversized resource records and unicast DNS.
3232 // If your target platform has a well-defined specialized application, and you know that all the records it uses
3233 // are InlineCacheRDSize or less, then you can just make a simple mDNSPlatformMemAllocate() stub that always returns
3234 // NULL. InlineCacheRDSize is a compile-time constant, which is set by default to 68. If you need to handle records
3235 // a little larger than this and you don't want to have to implement run-time allocation and freeing, then you
3236 // can raise the value of this constant to a suitable value (at the expense of increased memory usage).
3237 //
3238 // USE CAUTION WHEN CALLING mDNSPlatformRawTime: The m->timenow_adjust correction factor needs to be added
3239 // Generally speaking:
3240 // Code that's protected by the main mDNS lock should just use the m->timenow value
3241 // Code outside the main mDNS lock should use mDNS_TimeNow(m) to get properly adjusted time
3242 // In certain cases there may be reasons why it's necessary to get the time without taking the lock first
3243 // (e.g. inside the routines that are doing the locking and unlocking, where a call to get the lock would result in a
3244 // recursive loop); in these cases use mDNS_TimeNow_NoLock(m) to get mDNSPlatformRawTime with the proper correction factor added.
3245 //
3246 // mDNSPlatformUTC returns the time, in seconds, since Jan 1st 1970 UTC and is required for generating TSIG records
3247 
3248 #ifdef MDNS_MALLOC_DEBUGGING
3249 typedef void mDNSListValidationFunction(void *);
3250 typedef struct listValidator mDNSListValidator;
3251 struct listValidator {
3252     struct listValidator *next;
3253     const char *validationFunctionName;
3254     mDNSListValidationFunction *validator;
3255     void *context;
3256 };
3257 #endif // MDNS_MALLOC_DEBUGGING
3258 
3259 extern mStatus  mDNSPlatformInit        (mDNS *const m);
3260 extern void     mDNSPlatformClose       (mDNS *const m);
3261 extern mStatus  mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end,
3262                                     mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst,
3263                                     mDNSIPPort dstport, mDNSBool useBackgroundTrafficClass);
3264 
3265 extern void     mDNSPlatformLock        (const mDNS *const m);
3266 extern void     mDNSPlatformUnlock      (const mDNS *const m);
3267 
3268 extern void     mDNSPlatformStrLCopy    (      void *dst, const void *src, mDNSu32 len);
3269 extern mDNSu32  mDNSPlatformStrLen      (                 const void *src);
3270 extern void     mDNSPlatformMemCopy     (      void *dst, const void *src, mDNSu32 len);
3271 extern mDNSBool mDNSPlatformMemSame     (const void *dst, const void *src, mDNSu32 len);
3272 extern int      mDNSPlatformMemCmp      (const void *dst, const void *src, mDNSu32 len);
3273 extern void     mDNSPlatformMemZero     (      void *dst,                  mDNSu32 len);
3274 extern void mDNSPlatformQsort       (void *base, int nel, int width, int (*compar)(const void *, const void *));
3275 #if MDNS_MALLOC_DEBUGGING
3276 #define         mDNSPlatformMemAllocate(X)      mallocL(# X, X)
3277 #define         mDNSPlatformMemAllocateClear(X)   callocL(# X, X)
3278 #define         mDNSPlatformMemFree(X)          freeL(# X, X)
3279 extern void     mDNSPlatformValidateLists (void);
3280 extern void     mDNSPlatformAddListValidator(mDNSListValidator *validator,
3281                                              mDNSListValidationFunction *vf, const char *vfName, void *context);
3282 #else
3283 extern void *   mDNSPlatformMemAllocate(mDNSu32 len);
3284 extern void *   mDNSPlatformMemAllocateClear(mDNSu32 len);
3285 extern void     mDNSPlatformMemFree(void *mem);
3286 #endif // MDNS_MALLOC_DEBUGGING
3287 
3288 #define mDNSPlatformMemForget(PTR)          \
3289     do                                      \
3290     {                                       \
3291         if (*(PTR))                         \
3292         {                                   \
3293             mDNSPlatformMemFree(*(PTR));    \
3294             *(PTR) = NULL;                  \
3295         }                                   \
3296     } while(0)
3297 
3298 // If the platform doesn't have a strong PRNG, we define a naive multiply-and-add based on a seed
3299 // from the platform layer.  Long-term, we should embed an arc4 implementation, but the strength
3300 // will still depend on the randomness of the seed.
3301 #if !defined(_PLATFORM_HAS_STRONG_PRNG_) && (_BUILDING_XCODE_PROJECT_ || defined(_WIN32))
3302 #define _PLATFORM_HAS_STRONG_PRNG_ 1
3303 #endif
3304 #if _PLATFORM_HAS_STRONG_PRNG_
3305 extern mDNSu32  mDNSPlatformRandomNumber(void);
3306 #else
3307 extern mDNSu32  mDNSPlatformRandomSeed  (void);
3308 #endif // _PLATFORM_HAS_STRONG_PRNG_
3309 
3310 extern mStatus  mDNSPlatformTimeInit              (void);
3311 extern mDNSs32  mDNSPlatformRawTime               (void);
3312 extern mDNSs32  mDNSPlatformUTC                   (void);
3313 extern mDNSs32  mDNSPlatformContinuousTimeSeconds (void);
3314 
3315 // strlen("1900-01-01 00:00:00.000000-0000" + "\0") == 32;
3316 // bufferLen must be greater than MIN_TIMESTAMP_STRING_LENGTH to avoid the string truncation.
3317 #define MIN_TIMESTAMP_STRING_LENGTH 32
3318 extern void getLocalTimestampFromPlatformTime(mDNSs32 platformTimeNow, mDNSs32 platformTime,
3319                                               char *outBuffer, mDNSu32 bufferLen);
3320 extern void getLocalTimestampNow(char *outBuffer, mDNSu32 bufferLen);
3321 
3322 /*!
3323  *  @brief
3324  *      Convert the Platform time in ticks to millisecond.
3325  *
3326  *  @param ticks
3327  *      The time interval calculated by subtracting one absolute platform time from another.
3328  *
3329  *  @result
3330  *      The time interval in millisecond.
3331  *
3332  *  @discussion
3333  *      if the number of milliseconds represented by `ticks` is greater than `UINT_MAX`,
3334  *      `UINT_MAX` will be returned.
3335  *
3336  *      Calling this function with absolute platform time is undefined.
3337  */
3338 extern mDNSu32 getMillisecondsFromTicks(mDNSs32 ticks);
3339 
3340 #define mDNS_TimeNow_NoLock(m) (mDNSPlatformRawTime() + (m)->timenow_adjust)
3341 
3342 #if MDNS_DEBUGMSGS
3343 extern void mDNSPlatformWriteDebugMsg(const char *msg);
3344 #endif
3345 extern void mDNSPlatformWriteLogMsg(const char *ident, const char *msg, mDNSLogLevel_t loglevel);
3346 
3347 // Platform support modules should provide the following functions to map between opaque interface IDs
3348 // and interface indexes in order to support the DNS-SD API. If your target platform does not support
3349 // multiple interfaces and/or does not support the DNS-SD API, these functions can be empty.
3350 extern mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 ifindex);
3351 extern mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id, mDNSBool suppressNetworkChange);
3352 
3353 // Every platform support module must provide the following functions if it is to support unicast DNS
3354 // and Dynamic Update.
3355 // All TCP socket operations implemented by the platform layer MUST NOT BLOCK.
3356 // mDNSPlatformTCPConnect initiates a TCP connection with a peer, adding the socket descriptor to the
3357 // main event loop.  The return value indicates whether the connection succeeded, failed, or is pending
3358 // (i.e. the call would block.)  On return, the descriptor parameter is set to point to the connected socket.
3359 // The TCPConnectionCallback is subsequently invoked when the connection
3360 // completes (in which case the ConnectionEstablished parameter is true), or data is available for
3361 // reading on the socket (indicated by the ConnectionEstablished parameter being false.)  If the connection
3362 // asynchronously fails, the TCPConnectionCallback should be invoked as usual, with the error being
3363 // returned in subsequent calls to PlatformReadTCP or PlatformWriteTCP.  (This allows for platforms
3364 // with limited asynchronous error detection capabilities.)  PlatformReadTCP and PlatformWriteTCP must
3365 // return the number of bytes read/written, 0 if the call would block, and -1 if an error.  PlatformReadTCP
3366 // should set the closed argument if the socket has been closed.
3367 // PlatformTCPCloseConnection must close the connection to the peer and remove the descriptor from the
3368 // event loop.  CloseConnectin may be called at any time, including in a ConnectionCallback.
3369 
3370 typedef enum
3371 {
3372     kTCPSocketFlags_Zero   = 0,
3373     kTCPSocketFlags_UseTLS = (1 << 0),
3374           kTCPSocketFlags_TLSValidationNotRequired = (1 << 1)
3375 } TCPSocketFlags;
3376 
3377 typedef void (*TCPConnectionCallback)(TCPSocket *sock, void *context, mDNSBool ConnectionEstablished, mStatus err);
3378 typedef void (*TCPAcceptedCallback)(TCPSocket *sock, mDNSAddr *addr, mDNSIPPort *port,
3379                                                                                           const char *remoteName, void *context);
3380 extern TCPSocket *mDNSPlatformTCPSocket(TCPSocketFlags flags, mDNSAddr_Type addrtype, mDNSIPPort *port, domainname *hostname, mDNSBool useBackgroundTrafficClass); // creates a TCP socket
3381 extern TCPListener *mDNSPlatformTCPListen(mDNSAddr_Type addrtype, mDNSIPPort *port, mDNSAddr *addr,
3382                                                                                                       TCPSocketFlags socketFlags, mDNSBool reuseAddr, int queueLength,
3383                                                                                                       TCPAcceptedCallback callback, void *context); // Listen on a port
3384 extern mStatus mDNSPlatformTCPSocketSetCallback(TCPSocket *sock, TCPConnectionCallback callback, void *context);
3385 extern TCPSocket *mDNSPlatformTCPAccept(TCPSocketFlags flags, int sd);
3386 extern int        mDNSPlatformTCPGetFD(TCPSocket *sock);
3387 extern mDNSBool   mDNSPlatformTCPWritable(TCPSocket *sock);
3388 extern mStatus    mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, mDNSOpaque16 dstport,
3389                                          mDNSInterfaceID InterfaceID, TCPConnectionCallback callback, void *context);
3390 extern void       mDNSPlatformTCPCloseConnection(TCPSocket *sock);
3391 extern long       mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool *closed);
3392 extern long       mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned long len);
3393 extern UDPSocket *mDNSPlatformUDPSocket(const mDNSIPPort requestedport);
3394 extern mDNSu16    mDNSPlatformGetUDPPort(UDPSocket *sock);
3395 extern void       mDNSPlatformUDPClose(UDPSocket *sock);
3396 extern mDNSBool   mDNSPlatformUDPSocketEncounteredEOF(const UDPSocket *sock);
3397 extern void       mDNSPlatformReceiveBPF_fd(int fd);
3398 extern void       mDNSPlatformUpdateProxyList(const mDNSInterfaceID InterfaceID);
3399 extern void       mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID);
3400 extern void       mDNSPlatformSetLocalAddressCacheEntry(const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID);
3401 extern void       mDNSPlatformSourceAddrForDest(mDNSAddr *const src, const mDNSAddr *const dst);
3402 extern void       mDNSPlatformSendKeepalive(mDNSAddr *sadd, mDNSAddr *dadd, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu32 seq, mDNSu32 ack, mDNSu16 win);
3403 extern mStatus    mDNSPlatformRetrieveTCPInfo(mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr,  mDNSIPPort *rport, mDNSTCPInfo *mti);
3404 extern mStatus    mDNSPlatformGetRemoteMacAddr(mDNSAddr *raddr);
3405 extern mStatus    mDNSPlatformStoreSPSMACAddr(mDNSAddr *spsaddr, char *ifname);
3406 extern mStatus    mDNSPlatformClearSPSData(void);
3407 extern mStatus    mDNSPlatformStoreOwnerOptRecord(char *ifname, DNSMessage *msg, int length);
3408 
3409 // mDNSPlatformTLSSetupCerts/mDNSPlatformTLSTearDownCerts used by dnsextd
3410 extern mStatus    mDNSPlatformTLSSetupCerts(void);
3411 extern void       mDNSPlatformTLSTearDownCerts(void);
3412 
3413 // Platforms that support unicast browsing and dynamic update registration for clients who do not specify a domain
3414 // in browse/registration calls must implement these routines to get the "default" browse/registration list.
3415 
3416 extern mDNSBool   mDNSPlatformSetDNSConfig(mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **RegDomains,
3417                                            DNameListElem **BrowseDomains, mDNSBool ackConfig);
3418 extern mStatus    mDNSPlatformGetPrimaryInterface(mDNSAddr *v4, mDNSAddr *v6, mDNSAddr *router);
3419 extern void       mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status);
3420 
3421 extern void       mDNSPlatformSetAllowSleep(mDNSBool allowSleep, const char *reason);
3422 extern void       mDNSPlatformPreventSleep(mDNSu32 timeout, const char *reason);
3423 extern void       mDNSPlatformSendWakeupPacket(mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration);
3424 
3425 extern mDNSBool   mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID);
3426 #if MDNSRESPONDER_SUPPORTS(APPLE, AWDL)
3427 extern mDNSBool   mDNSPlatformInterfaceIsAWDL(mDNSInterfaceID interfaceID);
3428 #endif
3429 extern mDNSBool   mDNSPlatformValidRecordForQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
3430 extern mDNSBool   mDNSPlatformValidRecordForInterface(const AuthRecord *rr, mDNSInterfaceID InterfaceID);
3431 extern mDNSBool   mDNSPlatformValidQuestionForInterface(const DNSQuestion *q, const NetworkInterfaceInfo *intf);
3432 
3433 extern void mDNSPlatformFormatTime(unsigned long t, mDNSu8 *buf, int bufsize);
3434 
3435 // Platform event API
3436 
3437 #ifdef _LEGACY_NAT_TRAVERSAL_
3438 // Support for legacy NAT traversal protocols, implemented by the platform layer and callable by the core.
3439 extern void     LNT_SendDiscoveryMsg(mDNS *m);
3440 extern void     LNT_ConfigureRouterInfo(mDNS *m, const mDNSInterfaceID InterfaceID, const mDNSu8 *const data, const mDNSu16 len);
3441 extern mStatus  LNT_GetExternalAddress(mDNS *m);
3442 extern mStatus  LNT_MapPort(mDNS *m, NATTraversalInfo *const n);
3443 extern mStatus  LNT_UnmapPort(mDNS *m, NATTraversalInfo *const n);
3444 extern void     LNT_ClearState(mDNS *const m);
3445 #endif // _LEGACY_NAT_TRAVERSAL_
3446 
3447 // The core mDNS code provides these functions, for the platform support code to call at appropriate times
3448 //
3449 // mDNS_SetFQDN() is called once on startup (typically from mDNSPlatformInit())
3450 // and then again on each subsequent change of the host name.
3451 //
3452 // mDNS_RegisterInterface() is used by the platform support layer to inform mDNSCore of what
3453 // physical and/or logical interfaces are available for sending and receiving packets.
3454 // Typically it is called on startup for each available interface, but register/deregister may be
3455 // called again later, on multiple occasions, to inform the core of interface configuration changes.
3456 // If set->Advertise is set non-zero, then mDNS_RegisterInterface() also registers the standard
3457 // resource records that should be associated with every publicised IP address/interface:
3458 // -- Name-to-address records (A/AAAA)
3459 // -- Address-to-name records (PTR)
3460 // -- Host information (HINFO)
3461 // IMPORTANT: The specified mDNSInterfaceID MUST NOT be 0, -1, or -2; these values have special meaning
3462 // mDNS_RegisterInterface does not result in the registration of global hostnames via dynamic update -
3463 // see mDNS_SetPrimaryInterfaceInfo, mDNS_AddDynDNSHostName, etc. for this purpose.
3464 // Note that the set may be deallocated immediately after it is deregistered via mDNS_DeegisterInterface.
3465 //
3466 // mDNS_RegisterDNS() is used by the platform support layer to provide the core with the addresses of
3467 // available domain name servers for unicast queries/updates.  RegisterDNS() should be called once for
3468 // each name server, typically at startup, or when a new name server becomes available.  DeregiterDNS()
3469 // must be called whenever a registered name server becomes unavailable.  DeregisterDNSList deregisters
3470 // all registered servers.  mDNS_DNSRegistered() returns true if one or more servers are registered in the core.
3471 //
3472 // mDNSCoreInitComplete() is called when the platform support layer is finished.
3473 // Typically this is at the end of mDNSPlatformInit(), but may be later
3474 // (on platforms like OT that allow asynchronous initialization of the networking stack).
3475 //
3476 // mDNSCoreReceive() is called when a UDP packet is received
3477 //
3478 // mDNSCoreMachineSleep() is called when the machine sleeps or wakes
3479 // (This refers to heavyweight laptop-style sleep/wake that disables network access,
3480 // not lightweight second-by-second CPU power management modes.)
3481 
3482 extern void     mDNS_SetFQDN(mDNS *const m);
3483 extern void     mDNS_ActivateNetWake_internal  (mDNS *const m, NetworkInterfaceInfo *set);
3484 extern void     mDNS_DeactivateNetWake_internal(mDNS *const m, NetworkInterfaceInfo *set);
3485 
3486 // Attributes that controls the Bonjour operation initiation and response speed for an interface.
3487 typedef enum
3488 {
3489     FastActivation,     // For p2p* and DirectLink type interfaces
3490     NormalActivation,   // For standard interface timing
3491 #if MDNSRESPONDER_SUPPORTS(APPLE, SLOW_ACTIVATION)
3492     SlowActivation      // For flapping interfaces
3493 #endif
3494 } InterfaceActivationSpeed;
3495 
3496 extern mStatus  mDNS_RegisterInterface  (mDNS *const m, NetworkInterfaceInfo *set, InterfaceActivationSpeed probeDelay);
3497 extern void     mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, InterfaceActivationSpeed probeDelay);
3498 extern void     mDNSCoreInitComplete(mDNS *const m, mStatus result);
3499 extern void     mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end,
3500                                 const mDNSAddr *const srcaddr, const mDNSIPPort srcport,
3501                                 const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID);
3502 #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
3503 extern void     mDNSCoreReceiveForQuerier(mDNS *m, DNSMessage *msg, const mDNSu8 *end, mdns_client_t client,
3504                                           mdns_dns_service_t service, mDNSInterfaceID InterfaceID);
3505 #endif
3506 extern CacheRecord *mDNSCheckCacheFlushRecords(mDNS *m, CacheRecord *CacheFlushRecords, mDNSBool id_is_zero, int numAnswers,
3507                                                                                                                  DNSQuestion *unicastQuestion, CacheRecord *NSECCachePtr, CacheRecord *NSECRecords,
3508                                                                                                                  mDNSu8 rcode);
3509 extern void     mDNSCoreRestartQueries(mDNS *const m);
3510 extern void     mDNSCoreRestartQuestion(mDNS *const m, DNSQuestion *q);
3511 extern void     mDNSCoreRestartRegistration(mDNS *const m, AuthRecord  *rr, int announceCount);
3512 typedef void (*FlushCache)(mDNS *const m);
3513 typedef void (*CallbackBeforeStartQuery)(mDNS *const m, void *context);
3514 extern void     mDNSCoreRestartAddressQueries(mDNS *const m, mDNSBool SearchDomainsChanged, FlushCache flushCacheRecords,
3515                                               CallbackBeforeStartQuery beforeQueryStart, void *context);
3516 extern mDNSBool mDNSCoreHaveAdvertisedMulticastServices(mDNS *const m);
3517 extern void     mDNSCoreMachineSleep(mDNS *const m, mDNSBool wake);
3518 extern mDNSBool mDNSCoreReadyForSleep(mDNS *m, mDNSs32 now);
3519 
3520 typedef enum
3521 {
3522     mDNSNextWakeReason_Null                        = 0,
3523     mDNSNextWakeReason_NATPortMappingRenewal       = 1,
3524     mDNSNextWakeReason_RecordRegistrationRenewal   = 2,
3525     mDNSNextWakeReason_UpkeepWake                  = 3,
3526     mDNSNextWakeReason_DHCPLeaseRenewal            = 4,
3527     mDNSNextWakeReason_SleepProxyRegistrationRetry = 5
3528 } mDNSNextWakeReason;
3529 
3530 extern mDNSs32  mDNSCoreIntervalToNextWake(mDNS *const m, mDNSs32 now, mDNSNextWakeReason *outReason);
3531 
3532 extern void     mDNSCoreReceiveRawPacket  (mDNS *const m, const mDNSu8 *const p, const mDNSu8 *const end, const mDNSInterfaceID InterfaceID);
3533 
3534 extern mDNSBool mDNSAddrIsDNSMulticast(const mDNSAddr *ip);
3535 
3536 typedef mDNSu32 CreateNewCacheEntryFlags;
3537 #define kCreateNewCacheEntryFlagsNone 0
3538 #if MDNSRESPONDER_SUPPORTS(COMMON, DNS_PUSH) || MDNSRESPONDER_SUPPORTS(APPLE, DNS_PUSH)
3539 #define kCreateNewCacheEntryFlagsDNSPushSubscribed (1U << 0)
3540 #endif
3541 #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
3542 // Set this flag if the record being created comes from a DNSSEC-aware response.
3543 #define kCreateNewCacheEntryFlagsDNSSECRRToValidate                 (1U << 1)
3544 #define kCreateNewCacheEntryFlagsDNSSECRRValidatedSecure            (1U << 2)
3545 #define kCreateNewCacheEntryFlagsDNSSECRRValidatedInsecure          (1U << 3)
3546 #define kCreateNewCacheEntryFlagsDNSSECInsecureValidationUsable     (1U << 4)
3547 #endif
3548 extern CacheRecord *CreateNewCacheEntryEx(mDNS *m, mDNSu32 slot, CacheGroup *cg, mDNSs32 delay, mDNSBool add,
3549                                           const mDNSAddr *sourceAddress, CreateNewCacheEntryFlags flags);
3550 extern CacheRecord *CreateNewCacheEntry(mDNS *const m, const mDNSu32 slot, CacheGroup *cg, mDNSs32 delay, mDNSBool Add, const mDNSAddr *sourceAddress);
3551 extern CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 namehash, const domainname *const name);
3552 extern void ReleaseCacheRecord(mDNS *const m, CacheRecord *r);
3553 extern void ScheduleNextCacheCheckTime(mDNS *const m, const mDNSu32 slot, const mDNSs32 event);
3554 extern void SetNextCacheCheckTimeForRecord(mDNS *const m, CacheRecord *const rr);
3555 extern void RefreshCacheRecord(mDNS *const m, CacheRecord *rr, mDNSu32 ttl);
3556 extern void GrantCacheExtensions(mDNS *const m, DNSQuestion *q, mDNSu32 lease);
3557 extern void MakeNegativeCacheRecordForQuestion(mDNS *m, CacheRecord *cr, const DNSQuestion *q, mDNSu32 ttl,
3558     mDNSInterfaceID InterfaceID, mDNSOpaque16 responseFlags);
3559 extern void CompleteDeregistration(mDNS *const m, AuthRecord *rr);
3560 extern void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheRecord *const rr, const QC_result AddRecord);
3561 extern void AnswerQuestionByFollowingCNAME(mDNS *const m, DNSQuestion *q, ResourceRecord *rr);
3562 extern NetworkInterfaceInfo *FirstInterfaceForID(mDNS *const m, const mDNSInterfaceID InterfaceID);
3563 extern NetworkInterfaceInfo *FirstIPv4LLInterfaceForID(mDNS *const m, const mDNSInterfaceID InterfaceID);
3564 extern char *InterfaceNameForID(mDNS *const m, const mDNSInterfaceID InterfaceID);
3565 extern const char *InterfaceNameForIDOrEmptyString(mDNSInterfaceID InterfaceID);
3566 extern void CacheRecordSetResponseFlags(CacheRecord *const cr, const mDNSOpaque16 responseFlags);
3567 extern void mDNSCoreResetRecord(mDNS *const m);
3568 extern mDNSBool getValidContinousTSRTime(mDNSs32 *timestampContinuous, mDNSu32 tsrTimestamp);
3569 extern AuthRecord *mDNSGetTSRForAuthRecord(mDNS *m, const AuthRecord *rr);
3570 extern CacheRecord *mDNSGetTSRForCacheGroup(const CacheGroup *const cg);
3571 typedef enum { eTSRCheckLose = -1, eTSRCheckNoKeyMatch = 0, eTSRCheckKeyMatch, eTSRCheckWin } eTSRCheckResult;
3572 extern eTSRCheckResult CheckTSRForResourceRecord(const TSROptData *curTSROpt, const ResourceRecord *ourTSRRec);
3573 #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
3574 extern void DNSServerChangeForQuestion(mDNS *const m, DNSQuestion *q, DNSServer *newServer);
3575 #endif
3576 extern void ActivateUnicastRegistration(mDNS *const m, AuthRecord *const rr);
3577 #if MDNSRESPONDER_SUPPORTS(APPLE, D2D)
3578 extern void mDNSCoreReceiveD2DResponse(mDNS *const m, const DNSMessage *const response, const mDNSu8 *end,
3579     const mDNSAddr *srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, mDNSIPPort dstport,
3580     const mDNSInterfaceID InterfaceID);
3581 #endif
3582 extern void CheckSuppressUnusableQuestions(mDNS *const m);
3583 extern void RetrySearchDomainQuestions(mDNS *const m);
3584 extern mDNSBool DomainEnumQuery(const domainname *qname);
3585 extern mStatus UpdateKeepaliveRData(mDNS *const m, AuthRecord *rr, NetworkInterfaceInfo *const intf, mDNSBool updateMac, char *ethAddr);
3586 extern void  UpdateKeepaliveRMACAsync(mDNS *const m, void *context);
3587 extern void UpdateRMAC(mDNS *const m, void *context);
3588 
3589 // Used only in logging to restrict the number of /etc/hosts entries printed
3590 extern void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result);
3591 // exported for using the hash for /etc/hosts AuthRecords
3592 extern AuthGroup *AuthGroupForName(AuthHash *r, const mDNSu32 namehash, const domainname *const name);
3593 extern AuthGroup *AuthGroupForRecord(AuthHash *r, const ResourceRecord *const rr);
3594 extern AuthGroup *InsertAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr);
3595 extern AuthGroup *RemoveAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr);
3596 
3597 
3598 typedef void ProxyCallback (void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr,
3599     const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context);
3600 extern void mDNSPlatformInitDNSProxySkts(ProxyCallback *UDPCallback, ProxyCallback *TCPCallback);
3601 extern void mDNSPlatformCloseDNSProxySkts(mDNS *const m);
3602 extern void mDNSPlatformDisposeProxyContext(void *context);
3603 extern mDNSu8 *DNSProxySetAttributes(DNSQuestion *q, DNSMessageHeader *h, DNSMessage *msg, mDNSu8 *start, mDNSu8 *limit);
3604 
3605 extern void mDNSPlatformSetSocktOpt(void *sock, mDNSTransport_Type transType, mDNSAddr_Type addrType, const DNSQuestion *q);
3606 extern mDNSs32 mDNSPlatformGetPID(void);
3607 extern mDNSBool mDNSValidKeepAliveRecord(AuthRecord *rr);
3608 extern mDNSBool CacheRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q);
3609 #if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
3610 extern void GetRandomUUIDLabel(domainlabel *label);
3611 extern void GetRandomUUIDLocalHostname(domainname *hostname);
3612 #endif
3613 #if MDNSRESPONDER_SUPPORTS(APPLE, DNS_ANALYTICS) || MDNSRESPONDER_SUPPORTS(APPLE, RUNTIME_MDNS_METRICS)
3614 extern void DNSMetricsClear(DNSMetrics *metrics);
3615 #endif
3616 
3617 // ***************************************************************************
3618 #if 0
3619 #pragma mark -
3620 #pragma mark - Sleep Proxy
3621 #endif
3622 
3623 // Sleep Proxy Server Property Encoding
3624 //
3625 // Sleep Proxy Servers are advertised using a structured service name, consisting of four
3626 // metrics followed by a human-readable name. The metrics assist clients in deciding which
3627 // Sleep Proxy Server(s) to use when multiple are available on the network. Each metric
3628 // is a two-digit decimal number in the range 10-99. Lower metrics are generally better.
3629 //
3630 //   AA-BB-CC-DD.FF Name
3631 //
3632 // Metrics:
3633 //
3634 // AA = Intent
3635 // BB = Portability
3636 // CC = Marginal Power
3637 // DD = Total Power
3638 // FF = Features Supported (Currently TCP Keepalive only)
3639 //
3640 //
3641 // ** Intent Metric **
3642 //
3643 // 20 = Dedicated Sleep Proxy Server -- a device, permanently powered on,
3644 //      installed for the express purpose of providing Sleep Proxy Service.
3645 //
3646 // 30 = Primary Network Infrastructure Hardware -- a router, DHCP server, NAT gateway,
3647 //      or similar permanently installed device which is permanently powered on.
3648 //      This is hardware designed for the express purpose of being network
3649 //      infrastructure, and for most home users is typically a single point
3650 //      of failure for the local network -- e.g. most home users only have
3651 //      a single NAT gateway / DHCP server. Even though in principle the
3652 //      hardware might technically be capable of running different software,
3653 //      a typical user is unlikely to do that. e.g. AirPort base station.
3654 //
3655 // 40 = Primary Network Infrastructure Software -- a general-purpose computer
3656 //      (e.g. Mac, Windows, Linux, etc.) which is currently running DHCP server
3657 //      or NAT gateway software, but the user could choose to turn that off
3658 //      fairly easily. e.g. iMac running Internet Sharing
3659 //
3660 // 50 = Secondary Network Infrastructure Hardware -- like primary infrastructure
3661 //      hardware, except not a single point of failure for the entire local network.
3662 //      For example, an AirPort base station in bridge mode. This may have clients
3663 //      associated with it, and if it goes away those clients will be inconvenienced,
3664 //      but unlike the NAT gateway / DHCP server, the entire local network is not
3665 //      dependent on it.
3666 //
3667 // 60 = Secondary Network Infrastructure Software -- like 50, but in a general-
3668 //      purpose CPU.
3669 //
3670 // 70 = Incidentally Available Hardware -- a device which has no power switch
3671 //      and is generally left powered on all the time. Even though it is not a
3672 //      part of what we conventionally consider network infrastructure (router,
3673 //      DHCP, NAT, DNS, etc.), and the rest of the network can operate fine
3674 //      without it, since it's available and unlikely to be turned off, it is a
3675 //      reasonable candidate for providing Sleep Proxy Service e.g. Apple TV,
3676 //      or an AirPort base station in client mode, associated with an existing
3677 //      wireless network (e.g. AirPort Express connected to a music system, or
3678 //      being used to share a USB printer).
3679 //
3680 // 80 = Incidentally Available Software -- a general-purpose computer which
3681 //      happens at this time to be set to "never sleep", and as such could be
3682 //      useful as a Sleep Proxy Server, but has not been intentionally provided
3683 //      for this purpose. Of all the Intent Metric categories this is the
3684 //      one most likely to be shut down or put to sleep without warning.
3685 //      However, if nothing else is availalable, it may be better than nothing.
3686 //      e.g. Office computer in the workplace which has been set to "never sleep"
3687 //
3688 //
3689 // ** Portability Metric **
3690 //
3691 // Inversely related to mass of device, on the basis that, all other things
3692 // being equal, heavier devices are less likely to be moved than lighter devices.
3693 // E.g. A MacBook running Internet Sharing is probably more likely to be
3694 // put to sleep and taken away than a Mac Pro running Internet Sharing.
3695 // The Portability Metric is a logarithmic decibel scale, computed by taking the
3696 // (approximate) mass of the device in milligrammes, taking the base 10 logarithm
3697 // of that, multiplying by 10, and subtracting the result from 100:
3698 //
3699 //   Portability Metric = 100 - (log10(mg) * 10)
3700 //
3701 // The Portability Metric is not necessarily computed literally from the actual
3702 // mass of the device; the intent is just that lower numbers indicate more
3703 // permanent devices, and higher numbers indicate devices more likely to be
3704 // removed from the network, e.g., in order of increasing portability:
3705 //
3706 // Mac Pro < iMac < Laptop < iPhone
3707 //
3708 // Example values:
3709 //
3710 // 10 = 1 metric tonne
3711 // 40 = 1kg
3712 // 70 = 1g
3713 // 90 = 10mg
3714 //
3715 //
3716 // ** Marginal Power and Total Power Metrics **
3717 //
3718 // The Marginal Power Metric is the power difference between sleeping and staying awake
3719 // to be a Sleep Proxy Server.
3720 //
3721 // The Total Power Metric is the total power consumption when being Sleep Proxy Server.
3722 //
3723 // The Power Metrics use a logarithmic decibel scale, computed as ten times the
3724 // base 10 logarithm of the (approximate) power in microwatts:
3725 //
3726 //   Power Metric = log10(uW) * 10
3727 //
3728 // Higher values indicate higher power consumption. Example values:
3729 //
3730 // 10 =  10 uW
3731 // 20 = 100 uW
3732 // 30 =   1 mW
3733 // 60 =   1 W
3734 // 90 =   1 kW
3735 
3736 typedef enum
3737 {
3738     mDNSSleepProxyMetric_Dedicated          = 20,
3739     mDNSSleepProxyMetric_PrimaryHardware    = 30,
3740     mDNSSleepProxyMetric_PrimarySoftware    = 40,
3741     mDNSSleepProxyMetric_SecondaryHardware  = 50,
3742     mDNSSleepProxyMetric_SecondarySoftware  = 60,
3743     mDNSSleepProxyMetric_IncidentalHardware = 70,
3744     mDNSSleepProxyMetric_IncidentalSoftware = 80
3745 } mDNSSleepProxyMetric;
3746 
3747 typedef enum
3748 {
3749     mDNS_NoWake        = 0, // System does not support Wake on LAN
3750     mDNS_WakeOnAC      = 1, // System supports Wake on LAN when connected to AC power only
3751     mDNS_WakeOnBattery = 2  // System supports Wake on LAN on battery
3752 } mDNSWakeForNetworkAccess;
3753 
3754 extern void mDNSCoreBeSleepProxyServer_internal(mDNS *const m, mDNSu8 sps, mDNSu8 port, mDNSu8 marginalpower, mDNSu8 totpower, mDNSu8 features);
3755 #define mDNSCoreBeSleepProxyServer(M,S,P,MP,TP,F)                       \
3756     do { mDNS_Lock(m); mDNSCoreBeSleepProxyServer_internal((M),(S),(P),(MP),(TP),(F)); mDNS_Unlock(m); } while(0)
3757 
3758 #if MDNSRESPONDER_SUPPORTS(COMMON, SPS_CLIENT)
3759 extern void FindSPSInCache(mDNS *const m, const DNSQuestion *const q, const CacheRecord *sps[3]);
3760 #endif
3761 #define PrototypeSPSName(X) ((X)[0] >= 11 && (X)[3] == '-' && (X)[ 4] == '9' && (X)[ 5] == '9' && \
3762                              (X)[6] == '-' && (X)[ 7] == '9' && (X)[ 8] == '9' && \
3763                              (X)[9] == '-' && (X)[10] == '9' && (X)[11] == '9'    )
3764 #define ValidSPSName(X) ((X)[0] >= 5 && mDNSIsDigit((X)[1]) && mDNSIsDigit((X)[2]) && mDNSIsDigit((X)[4]) && mDNSIsDigit((X)[5]))
3765 #define SPSMetric(X) (!ValidSPSName(X) || PrototypeSPSName(X) ? 1000000 : \
3766                       ((X)[1]-'0') * 100000 + ((X)[2]-'0') * 10000 + ((X)[4]-'0') * 1000 + ((X)[5]-'0') * 100 + ((X)[7]-'0') * 10 + ((X)[8]-'0'))
3767 #define LocalSPSMetric(X) ( (X)->SPSType * 10000 + (X)->SPSPortability * 100 + (X)->SPSMarginalPower)
3768 #define SPSFeatures(X) ((X)[0] >= 13 && (X)[12] =='.' ? ((X)[13]-'0') : 0 )
3769 
3770 #define MD5_DIGEST_LENGTH   16          /* digest length in bytes */
3771 #define MD5_BLOCK_BYTES     64          /* block size in bytes */
3772 #define MD5_BLOCK_LONG       (MD5_BLOCK_BYTES / sizeof(mDNSu32))
3773 
3774 typedef struct MD5state_st
3775 {
3776     mDNSu32 A,B,C,D;
3777     mDNSu32 Nl,Nh;
3778     mDNSu32 data[MD5_BLOCK_LONG];
3779     mDNSu32 num;
3780 } MD5_CTX;
3781 
3782 extern int MD5_Init(MD5_CTX *c);
3783 extern int MD5_Update(MD5_CTX *c, const void *data, unsigned long len);
3784 extern int MD5_Final(unsigned char *md, MD5_CTX *c);
3785 
3786 // ***************************************************************************
3787 #if 0
3788 #pragma mark -
3789 #pragma mark - Compile-Time assertion checks
3790 #endif
3791 
3792 // Some C compiler cleverness. We can make the compiler check certain things for
3793 // us, and report compile-time errors if anything is wrong. The usual way to do
3794 // this would be to use a run-time "if" statement, but then you don't find out
3795 // what's wrong until you run the software. This way, if the assertion condition
3796 // is false, the array size is negative, and the complier complains immediately.
3797 
3798 struct CompileTimeAssertionChecks_mDNS
3799 {
3800 #ifndef __lint__
3801     // Check that the compiler generated our on-the-wire packet format structure definitions
3802     // properly packed, without adding padding bytes to align fields on 32-bit or 64-bit boundaries.
3803     char assert0[(sizeof(rdataSRV)         == 262                          ) ? 1 : -1];
3804     char assert1[(sizeof(DNSMessageHeader) ==  12                          ) ? 1 : -1];
3805     char assert2[(sizeof(DNSMessage)       ==  12+AbsoluteMaxDNSMessageData) ? 1 : -1];
3806     char assert3[(sizeof(mDNSs8)           ==   1                          ) ? 1 : -1];
3807     char assert4[(sizeof(mDNSu8)           ==   1                          ) ? 1 : -1];
3808     char assert5[(sizeof(mDNSs16)          ==   2                          ) ? 1 : -1];
3809     char assert6[(sizeof(mDNSu16)          ==   2                          ) ? 1 : -1];
3810     char assert7[(sizeof(mDNSs32)          ==   4                          ) ? 1 : -1];
3811     char assert8[(sizeof(mDNSu32)          ==   4                          ) ? 1 : -1];
3812     char assert9[(sizeof(mDNSOpaque16)     ==   2                          ) ? 1 : -1];
3813     char assertA[(sizeof(mDNSOpaque32)     ==   4                          ) ? 1 : -1];
3814     char assertB[(sizeof(mDNSOpaque128)    ==  16                          ) ? 1 : -1];
3815     char assertC[(sizeof(CacheRecord  )    ==  sizeof(CacheGroup)          ) ? 1 : -1];
3816     char assertD[(sizeof(int)              >=  4                           ) ? 1 : -1];
3817     char assertE[(StandardAuthRDSize       >=  256                         ) ? 1 : -1];
3818     char assertF[(sizeof(EthernetHeader)   ==   14                         ) ? 1 : -1];
3819     char assertG[(sizeof(ARP_EthIP     )   ==   28                         ) ? 1 : -1];
3820     char assertH[(sizeof(IPv4Header    )   ==   20                         ) ? 1 : -1];
3821     char assertI[(sizeof(IPv6Header    )   ==   40                         ) ? 1 : -1];
3822     char assertJ[(sizeof(IPv6NDP       )   ==   24                         ) ? 1 : -1];
3823     char assertK[(sizeof(UDPHeader     )   ==    8                         ) ? 1 : -1];
3824     char assertL[(sizeof(IKEHeader     )   ==   28                         ) ? 1 : -1];
3825     char assertM[(sizeof(TCPHeader     )   ==   20                         ) ? 1 : -1];
3826           char assertN[(sizeof(rdataOPT)                       ==   24                         ) ? 1 : -1];
3827           char assertP[(sizeof(PCPMapRequest)    ==   60                         ) ? 1 : -1];
3828           char assertQ[(sizeof(PCPMapReply)      ==   60                         ) ? 1 : -1];
3829 
3830 
3831     // Check our structures are reasonable sizes. Including overly-large buffers, or embedding
3832     // other overly-large structures instead of having a pointer to them, can inadvertently
3833     // cause structure sizes (and therefore memory usage) to balloon unreasonably.
3834     char sizecheck_RDataBody           [(sizeof(RDataBody)            ==   264) ? 1 : -1];
3835     char sizecheck_ResourceRecord      [(sizeof(ResourceRecord)       <=    64) ? 1 : -1];
3836     char sizecheck_AuthRecord          [(sizeof(AuthRecord)           <=  1176) ? 1 : -1];
3837     char sizecheck_CacheRecord         [(sizeof(CacheRecord)          <=   224) ? 1 : -1];
3838     char sizecheck_CacheGroup          [(sizeof(CacheGroup)           <=   224) ? 1 : -1];
3839     char sizecheck_DNSQuestion         [(sizeof(DNSQuestion)          <=   712) ? 1 : -1];
3840     char sizecheck_ZoneData            [(sizeof(ZoneData)             <=  1544) ? 1 : -1];
3841     char sizecheck_NATTraversalInfo    [(sizeof(NATTraversalInfo)     <=   200) ? 1 : -1];
3842     char sizecheck_HostnameInfo        [(sizeof(HostnameInfo)         <=  3050) ? 1 : -1];
3843 #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
3844     char sizecheck_DNSServer           [(sizeof(DNSServer)            <=   328) ? 1 : -1];
3845 #endif
3846     char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <=  6576) ? 1 : -1];
3847     char sizecheck_ServiceRecordSet    [(sizeof(ServiceRecordSet)     <=  4792) ? 1 : -1];
3848     char sizecheck_DomainAuthInfo      [(sizeof(DomainAuthInfo)       <=   944) ? 1 : -1];
3849 #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
3850     // structure size is assumed by LogRedact routine.
3851     char sizecheck_mDNSAddr            [(sizeof(mDNSAddr)             ==    20) ? 1 : -1];
3852     char sizecheck_mDNSv4Addr          [(sizeof(mDNSv4Addr)           ==     4) ? 1 : -1];
3853     char sizecheck_mDNSv6Addr          [(sizeof(mDNSv6Addr)           ==    16) ? 1 : -1];
3854 #endif
3855 #endif
3856 };
3857 mdns_compile_time_max_size_check(DupSuppressState, 128);
3858 
3859 // Routine to initialize device-info TXT record contents
3860 mDNSu32 initializeDeviceInfoTXT(mDNS *m, mDNSu8 *ptr);
3861 
3862 // ***************************************************************************
3863 
3864 #ifdef __cplusplus
3865 }
3866 #endif
3867 
3868 #endif
3869