Home | History | Annotate | Line # | Download | only in mDNSCore
      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)
   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 
   2713 mDNSinline mDNSs32 NonZeroTime(mDNSs32 t) { if (t) return(t);else return(1);}
   2714 
   2715 mDNSinline mDNSu16 mDNSVal16(mDNSOpaque16 x) { return((mDNSu16)((mDNSu16)x.b[0] <<  8 | (mDNSu16)x.b[1])); }
   2716 
   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 
   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 
   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 
   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