1*472cd20dSToomas Soome /*
2*472cd20dSToomas Soome  * Copyright (c) 2002-2020 Apple Inc. All rights reserved.
34b22b933Srs  *
44b22b933Srs  * Licensed under the Apache License, Version 2.0 (the "License");
54b22b933Srs  * you may not use this file except in compliance with the License.
64b22b933Srs  * You may obtain a copy of the License at
75ffb0c9bSToomas Soome  *
84b22b933Srs  *     http://www.apache.org/licenses/LICENSE-2.0
95ffb0c9bSToomas Soome  *
104b22b933Srs  * Unless required by applicable law or agreed to in writing, software
114b22b933Srs  * distributed under the License is distributed on an "AS IS" BASIS,
124b22b933Srs  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134b22b933Srs  * See the License for the specific language governing permissions and
144b22b933Srs  * limitations under the License.
154b22b933Srs 
164b22b933Srs    NOTE:
174b22b933Srs    If you're building an application that uses DNS Service Discovery
184b22b933Srs    this is probably NOT the header file you're looking for.
194b22b933Srs    In most cases you will want to use /usr/include/dns_sd.h instead.
204b22b933Srs 
214b22b933Srs    This header file defines the lowest level raw interface to mDNSCore,
224b22b933Srs    which is appropriate *only* on tiny embedded systems where everything
234b22b933Srs    runs in a single address space and memory is extremely constrained.
244b22b933Srs    All the APIs here are malloc-free, which means that the caller is
254b22b933Srs    responsible for passing in a pointer to the relevant storage that
264b22b933Srs    will be used in the execution of that call, and (when called with
274b22b933Srs    correct parameters) all the calls are guaranteed to succeed. There
284b22b933Srs    is never a case where a call can suffer intermittent failures because
294b22b933Srs    the implementation calls malloc() and sometimes malloc() returns NULL
304b22b933Srs    because memory is so limited that no more is available.
314b22b933Srs    This is primarily for devices that need to have precisely known fixed
324b22b933Srs    memory requirements, with absolutely no uncertainty or run-time variation,
334b22b933Srs    but that certainty comes at a cost of more difficult programming.
345ffb0c9bSToomas Soome 
354b22b933Srs    For applications running on general-purpose desktop operating systems
364b22b933Srs    (Mac OS, Linux, Solaris, Windows, etc.) the API you should use is
374b22b933Srs    /usr/include/dns_sd.h, which defines the API by which multiple
384b22b933Srs    independent client processes communicate their DNS Service Discovery
394b22b933Srs    requests to a single "mdnsd" daemon running in the background.
405ffb0c9bSToomas Soome 
414b22b933Srs    Even on platforms that don't run multiple independent processes in
424b22b933Srs    multiple independent address spaces, you can still use the preferred
434b22b933Srs    dns_sd.h APIs by linking in "dnssd_clientshim.c", which implements
444b22b933Srs    the standard "dns_sd.h" API calls, allocates any required storage
454b22b933Srs    using malloc(), and then calls through to the low-level malloc-free
464b22b933Srs    mDNSCore routines defined here. This has the benefit that even though
474b22b933Srs    you're running on a small embedded system with a single address space,
484b22b933Srs    you can still use the exact same client C code as you'd use on a
494b22b933Srs    general-purpose desktop system.
504b22b933Srs 
515ffb0c9bSToomas Soome  */
524b22b933Srs 
535ffb0c9bSToomas Soome #ifndef __mDNSEmbeddedAPI_h
545ffb0c9bSToomas Soome #define __mDNSEmbeddedAPI_h
554b22b933Srs 
565ffb0c9bSToomas Soome #if defined(EFI32) || defined(EFI64) || defined(EFIX64)
575ffb0c9bSToomas Soome // EFI doesn't have stdarg.h unless it's building with GCC.
585ffb0c9bSToomas Soome #include "Tiano.h"
595ffb0c9bSToomas Soome #if !defined(__GNUC__)
605ffb0c9bSToomas Soome #define va_list         VA_LIST
615ffb0c9bSToomas Soome #define va_start(a, b)  VA_START(a, b)
625ffb0c9bSToomas Soome #define va_end(a)       VA_END(a)
635ffb0c9bSToomas Soome #define va_arg(a, b)    VA_ARG(a, b)
645ffb0c9bSToomas Soome #endif
655ffb0c9bSToomas Soome #else
665ffb0c9bSToomas Soome #include <stdarg.h>     // stdarg.h is required for for va_list support for the mDNS_vsnprintf declaration
675ffb0c9bSToomas Soome #endif
684b22b933Srs 
695ffb0c9bSToomas Soome #if APPLE_OSX_mDNSResponder
705ffb0c9bSToomas Soome #include <uuid/uuid.h>
715ffb0c9bSToomas Soome #endif
724b22b933Srs 
73*472cd20dSToomas Soome #include "mDNSFeatures.h"
74*472cd20dSToomas Soome #include "mDNSDebug.h"
754b22b933Srs 
765ffb0c9bSToomas Soome // ***************************************************************************
775ffb0c9bSToomas Soome // Feature removal compile options & limited resource targets
784b22b933Srs 
795ffb0c9bSToomas Soome // The following compile options are responsible for removing certain features from mDNSCore to reduce the
805ffb0c9bSToomas Soome // memory footprint for use in embedded systems with limited resources.
814b22b933Srs 
825ffb0c9bSToomas Soome // UNICAST_DISABLED - disables unicast DNS functionality, including Wide Area Bonjour
835ffb0c9bSToomas Soome // SPC_DISABLED - disables Bonjour Sleep Proxy client
845ffb0c9bSToomas Soome // IDLESLEEPCONTROL_DISABLED - disables sleep control for Bonjour Sleep Proxy clients
854b22b933Srs 
865ffb0c9bSToomas Soome // In order to disable the above features pass the option to your compiler, e.g. -D UNICAST_DISABLED
874b22b933Srs 
88*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, WEB_CONTENT_FILTER)
89*472cd20dSToomas Soome #include <WebFilterDNS/WebFilterDNS.h>
90*472cd20dSToomas Soome #endif
91*472cd20dSToomas Soome 
92*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
93*472cd20dSToomas Soome #include "dnssec_v2_embedded.h"
94*472cd20dSToomas Soome #endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
95*472cd20dSToomas Soome 
96cda73f64SToomas Soome // Additionally, the LIMITED_RESOURCES_TARGET compile option will reduce the maximum DNS message sizes.
974b22b933Srs 
985ffb0c9bSToomas Soome #ifdef LIMITED_RESOURCES_TARGET
995ffb0c9bSToomas Soome // Don't support jumbo frames
100cda73f64SToomas Soome // 40 (IPv6 header) + 8 (UDP header) + 12 (DNS message header) + 1440 (DNS message body) = 1500 total
101c65ebfc7SToomas Soome #define AbsoluteMaxDNSMessageData   1440
1025ffb0c9bSToomas Soome // StandardAuthRDSize is 264 (256+8), which is large enough to hold a maximum-sized SRV record (6 + 256 bytes)
103c65ebfc7SToomas Soome #define MaximumRDSize               264
1044b22b933Srs #endif
1054b22b933Srs 
106*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
107*472cd20dSToomas Soome #include "mdns_private.h"
108*472cd20dSToomas Soome #endif
109*472cd20dSToomas Soome 
110*472cd20dSToomas Soome #ifdef __cplusplus
111*472cd20dSToomas Soome extern "C" {
1123b436d06SToomas Soome #endif
1133b436d06SToomas Soome 
1144b22b933Srs // ***************************************************************************
1154b22b933Srs // Function scope indicators
1164b22b933Srs 
1174b22b933Srs // If you see "mDNSlocal" before a function name in a C file, it means the function is not callable outside this file
1184b22b933Srs #ifndef mDNSlocal
1194b22b933Srs #define mDNSlocal static
1204b22b933Srs #endif
1214b22b933Srs // If you see "mDNSexport" before a symbol in a C file, it means the symbol is exported for use by clients
1224b22b933Srs // For every "mDNSexport" in a C file, there needs to be a corresponding "extern" declaration in some header file
1234b22b933Srs // (When a C file #includes a header file, the "extern" declarations tell the compiler:
1244b22b933Srs // "This symbol exists -- but not necessarily in this C file.")
1254b22b933Srs #ifndef mDNSexport
1264b22b933Srs #define mDNSexport
1274b22b933Srs #endif
1284b22b933Srs 
1294b22b933Srs // Explanation: These local/export markers are a little habit of mine for signaling the programmers' intentions.
1304b22b933Srs // When "mDNSlocal" is just a synonym for "static", and "mDNSexport" is a complete no-op, you could be
1314b22b933Srs // forgiven for asking what purpose they serve. The idea is that if you see "mDNSexport" in front of a
1324b22b933Srs // function definition it means the programmer intended it to be exported and callable from other files
1334b22b933Srs // in the project. If you see "mDNSlocal" in front of a function definition it means the programmer
1344b22b933Srs // intended it to be private to that file. If you see neither in front of a function definition it
1354b22b933Srs // means the programmer forgot (so you should work out which it is supposed to be, and fix it).
1364b22b933Srs // Using "mDNSlocal" instead of "static" makes it easier to do a textual searches for one or the other.
1374b22b933Srs // For example you can do a search for "static" to find if any functions declare any local variables as "static"
1384b22b933Srs // (generally a bad idea unless it's also "const", because static storage usually risks being non-thread-safe)
1394b22b933Srs // without the results being cluttered with hundreds of matches for functions declared static.
1404b22b933Srs // - Stuart Cheshire
1414b22b933Srs 
1424b22b933Srs // ***************************************************************************
1434b22b933Srs // Structure packing macro
1444b22b933Srs 
1454b22b933Srs // If we're not using GNUC, it's not fatal.
1464b22b933Srs // Most compilers naturally pack the on-the-wire structures correctly anyway, so a plain "struct" is usually fine.
1474b22b933Srs // In the event that structures are not packed correctly, mDNS_Init() will detect this and report an error, so the
1484b22b933Srs // developer will know what's wrong, and can investigate what needs to be done on that compiler to provide proper packing.
1494b22b933Srs #ifndef packedstruct
1504b22b933Srs  #if ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9)))
1514b22b933Srs   #define packedstruct struct __attribute__((__packed__))
1524b22b933Srs   #define packedunion  union  __attribute__((__packed__))
1534b22b933Srs  #else
1544b22b933Srs   #define packedstruct struct
1554b22b933Srs   #define packedunion  union
1564b22b933Srs  #endif
1574b22b933Srs #endif
1584b22b933Srs 
159*472cd20dSToomas Soome #ifndef fallthrough
160*472cd20dSToomas Soome  #if __clang__
161*472cd20dSToomas Soome   #if __has_c_attribute(fallthrough)
162*472cd20dSToomas Soome    #define fallthrough() [[fallthrough]]
163*472cd20dSToomas Soome   #else
164*472cd20dSToomas Soome    #define fallthrough()
165*472cd20dSToomas Soome   #endif
166*472cd20dSToomas Soome  #elif __GNUC__
167*472cd20dSToomas Soome   #define fallthrough() __attribute__((fallthrough))
168*472cd20dSToomas Soome  #else
169*472cd20dSToomas Soome   #define fallthrough()
170*472cd20dSToomas Soome  #endif // __GNUC__
171*472cd20dSToomas Soome #endif // fallthrough
172*472cd20dSToomas Soome 
1734b22b933Srs // ***************************************************************************
1744b22b933Srs #if 0
1754b22b933Srs #pragma mark - DNS Resource Record class and type constants
1764b22b933Srs #endif
1774b22b933Srs 
1785ffb0c9bSToomas Soome typedef enum                            // From RFC 1035
1795ffb0c9bSToomas Soome {
1805ffb0c9bSToomas Soome     kDNSClass_IN               = 1,     // Internet
1815ffb0c9bSToomas Soome     kDNSClass_CS               = 2,     // CSNET
1825ffb0c9bSToomas Soome     kDNSClass_CH               = 3,     // CHAOS
1835ffb0c9bSToomas Soome     kDNSClass_HS               = 4,     // Hesiod
1845ffb0c9bSToomas Soome     kDNSClass_NONE             = 254,   // Used in DNS UPDATE [RFC 2136]
1855ffb0c9bSToomas Soome 
1865ffb0c9bSToomas Soome     kDNSClass_Mask             = 0x7FFF, // Multicast DNS uses the bottom 15 bits to identify the record class...
1875ffb0c9bSToomas Soome     kDNSClass_UniqueRRSet      = 0x8000, // ... and the top bit indicates that all other cached records are now invalid
1885ffb0c9bSToomas Soome 
1895ffb0c9bSToomas Soome     kDNSQClass_ANY             = 255,   // Not a DNS class, but a DNS query class, meaning "all classes"
1905ffb0c9bSToomas Soome     kDNSQClass_UnicastResponse = 0x8000 // Top bit set in a question means "unicast response acceptable"
1915ffb0c9bSToomas Soome } DNS_ClassValues;
1925ffb0c9bSToomas Soome 
1935ffb0c9bSToomas Soome typedef enum                // From RFC 1035
1945ffb0c9bSToomas Soome {
1955ffb0c9bSToomas Soome     kDNSType_A = 1,         //  1 Address
1965ffb0c9bSToomas Soome     kDNSType_NS,            //  2 Name Server
1975ffb0c9bSToomas Soome     kDNSType_MD,            //  3 Mail Destination
1985ffb0c9bSToomas Soome     kDNSType_MF,            //  4 Mail Forwarder
1995ffb0c9bSToomas Soome     kDNSType_CNAME,         //  5 Canonical Name
2005ffb0c9bSToomas Soome     kDNSType_SOA,           //  6 Start of Authority
2015ffb0c9bSToomas Soome     kDNSType_MB,            //  7 Mailbox
2025ffb0c9bSToomas Soome     kDNSType_MG,            //  8 Mail Group
2035ffb0c9bSToomas Soome     kDNSType_MR,            //  9 Mail Rename
2045ffb0c9bSToomas Soome     kDNSType_NULL,          // 10 NULL RR
2055ffb0c9bSToomas Soome     kDNSType_WKS,           // 11 Well-known-service
2065ffb0c9bSToomas Soome     kDNSType_PTR,           // 12 Domain name pointer
2075ffb0c9bSToomas Soome     kDNSType_HINFO,         // 13 Host information
2085ffb0c9bSToomas Soome     kDNSType_MINFO,         // 14 Mailbox information
2095ffb0c9bSToomas Soome     kDNSType_MX,            // 15 Mail Exchanger
2105ffb0c9bSToomas Soome     kDNSType_TXT,           // 16 Arbitrary text string
2115ffb0c9bSToomas Soome     kDNSType_RP,            // 17 Responsible person
2125ffb0c9bSToomas Soome     kDNSType_AFSDB,         // 18 AFS cell database
2135ffb0c9bSToomas Soome     kDNSType_X25,           // 19 X_25 calling address
2145ffb0c9bSToomas Soome     kDNSType_ISDN,          // 20 ISDN calling address
2155ffb0c9bSToomas Soome     kDNSType_RT,            // 21 Router
2165ffb0c9bSToomas Soome     kDNSType_NSAP,          // 22 NSAP address
2175ffb0c9bSToomas Soome     kDNSType_NSAP_PTR,      // 23 Reverse NSAP lookup (deprecated)
2185ffb0c9bSToomas Soome     kDNSType_SIG,           // 24 Security signature
2195ffb0c9bSToomas Soome     kDNSType_KEY,           // 25 Security key
2205ffb0c9bSToomas Soome     kDNSType_PX,            // 26 X.400 mail mapping
2215ffb0c9bSToomas Soome     kDNSType_GPOS,          // 27 Geographical position (withdrawn)
2225ffb0c9bSToomas Soome     kDNSType_AAAA,          // 28 IPv6 Address
2235ffb0c9bSToomas Soome     kDNSType_LOC,           // 29 Location Information
2245ffb0c9bSToomas Soome     kDNSType_NXT,           // 30 Next domain (security)
2255ffb0c9bSToomas Soome     kDNSType_EID,           // 31 Endpoint identifier
2265ffb0c9bSToomas Soome     kDNSType_NIMLOC,        // 32 Nimrod Locator
2275ffb0c9bSToomas Soome     kDNSType_SRV,           // 33 Service record
2285ffb0c9bSToomas Soome     kDNSType_ATMA,          // 34 ATM Address
2295ffb0c9bSToomas Soome     kDNSType_NAPTR,         // 35 Naming Authority PoinTeR
2305ffb0c9bSToomas Soome     kDNSType_KX,            // 36 Key Exchange
2315ffb0c9bSToomas Soome     kDNSType_CERT,          // 37 Certification record
2325ffb0c9bSToomas Soome     kDNSType_A6,            // 38 IPv6 Address (deprecated)
2335ffb0c9bSToomas Soome     kDNSType_DNAME,         // 39 Non-terminal DNAME (for IPv6)
2345ffb0c9bSToomas Soome     kDNSType_SINK,          // 40 Kitchen sink (experimental)
2355ffb0c9bSToomas Soome     kDNSType_OPT,           // 41 EDNS0 option (meta-RR)
2365ffb0c9bSToomas Soome     kDNSType_APL,           // 42 Address Prefix List
2375ffb0c9bSToomas Soome     kDNSType_DS,            // 43 Delegation Signer
2385ffb0c9bSToomas Soome     kDNSType_SSHFP,         // 44 SSH Key Fingerprint
2395ffb0c9bSToomas Soome     kDNSType_IPSECKEY,      // 45 IPSECKEY
2405ffb0c9bSToomas Soome     kDNSType_RRSIG,         // 46 RRSIG
2415ffb0c9bSToomas Soome     kDNSType_NSEC,          // 47 Denial of Existence
2425ffb0c9bSToomas Soome     kDNSType_DNSKEY,        // 48 DNSKEY
2435ffb0c9bSToomas Soome     kDNSType_DHCID,         // 49 DHCP Client Identifier
2445ffb0c9bSToomas Soome     kDNSType_NSEC3,         // 50 Hashed Authenticated Denial of Existence
2455ffb0c9bSToomas Soome     kDNSType_NSEC3PARAM,    // 51 Hashed Authenticated Denial of Existence
2465ffb0c9bSToomas Soome 
2475ffb0c9bSToomas Soome     kDNSType_HIP = 55,      // 55 Host Identity Protocol
2485ffb0c9bSToomas Soome 
249*472cd20dSToomas Soome     kDNSType_SVCB = 64,     // 64 Service Binding
250*472cd20dSToomas Soome     kDNSType_HTTPS,         // 65 HTTPS Service Binding
251*472cd20dSToomas Soome 
2525ffb0c9bSToomas Soome     kDNSType_SPF = 99,      // 99 Sender Policy Framework for E-Mail
2535ffb0c9bSToomas Soome     kDNSType_UINFO,         // 100 IANA-Reserved
2545ffb0c9bSToomas Soome     kDNSType_UID,           // 101 IANA-Reserved
2555ffb0c9bSToomas Soome     kDNSType_GID,           // 102 IANA-Reserved
2565ffb0c9bSToomas Soome     kDNSType_UNSPEC,        // 103 IANA-Reserved
2575ffb0c9bSToomas Soome 
2585ffb0c9bSToomas Soome     kDNSType_TKEY = 249,    // 249 Transaction key
2595ffb0c9bSToomas Soome     kDNSType_TSIG,          // 250 Transaction signature
2605ffb0c9bSToomas Soome     kDNSType_IXFR,          // 251 Incremental zone transfer
2615ffb0c9bSToomas Soome     kDNSType_AXFR,          // 252 Transfer zone of authority
2625ffb0c9bSToomas Soome     kDNSType_MAILB,         // 253 Transfer mailbox records
2635ffb0c9bSToomas Soome     kDNSType_MAILA,         // 254 Transfer mail agent records
264*472cd20dSToomas Soome     kDNSQType_ANY          // Not a DNS type, but a DNS query type, meaning "all types"
2655ffb0c9bSToomas Soome } DNS_TypeValues;
2664b22b933Srs 
2674b22b933Srs // ***************************************************************************
2684b22b933Srs #if 0
2695ffb0c9bSToomas Soome #pragma mark -
2704b22b933Srs #pragma mark - Simple types
2714b22b933Srs #endif
2724b22b933Srs 
2734b22b933Srs // mDNS defines its own names for these common types to simplify portability across
2744b22b933Srs // multiple platforms that may each have their own (different) names for these types.
2755ffb0c9bSToomas Soome typedef unsigned char mDNSBool;
2765ffb0c9bSToomas Soome typedef   signed char mDNSs8;
2775ffb0c9bSToomas Soome typedef unsigned char mDNSu8;
2784b22b933Srs typedef   signed short mDNSs16;
2794b22b933Srs typedef unsigned short mDNSu16;
2804b22b933Srs 
2815ffb0c9bSToomas Soome // Source: http://www.unix.org/version2/whatsnew/lp64_wp.html
2825ffb0c9bSToomas Soome // http://software.intel.com/sites/products/documentation/hpc/mkl/lin/MKL_UG_structure/Support_for_ILP64_Programming.htm
2835ffb0c9bSToomas Soome // It can be safely assumed that int is 32bits on the platform
2844b22b933Srs #if defined(_ILP64) || defined(__ILP64__)
2854b22b933Srs typedef   signed int32 mDNSs32;
2864b22b933Srs typedef unsigned int32 mDNSu32;
2874b22b933Srs #else
2885ffb0c9bSToomas Soome typedef   signed int mDNSs32;
2895ffb0c9bSToomas Soome typedef unsigned int mDNSu32;
2904b22b933Srs #endif
2914b22b933Srs 
2924b22b933Srs // To enforce useful type checking, we make mDNSInterfaceID be a pointer to a dummy struct
2934b22b933Srs // This way, mDNSInterfaceIDs can be assigned, and compared with each other, but not with other types
2944b22b933Srs // Declaring the type to be the typical generic "void *" would lack this type checking
295*472cd20dSToomas Soome typedef const struct mDNSInterfaceID_dummystruct { void *dummy; } *mDNSInterfaceID;
296*472cd20dSToomas Soome 
297*472cd20dSToomas Soome // Use when printing interface IDs; the interface ID is actually a pointer, but we're only using
298*472cd20dSToomas Soome // the pointer as a unique identifier, and in special cases it's actually a small number.   So there's
299*472cd20dSToomas Soome // little point in printing all 64 bits--the upper 32 bits in particular will not add information.
300*472cd20dSToomas Soome #define IIDPrintable(x) ((uint32_t)(uintptr_t)(x))
3014b22b933Srs 
3024b22b933Srs // These types are for opaque two- and four-byte identifiers.
3034b22b933Srs // The "NotAnInteger" fields of the unions allow the value to be conveniently passed around in a
3044b22b933Srs // register for the sake of efficiency, and compared for equality or inequality, but don't forget --
3054b22b933Srs // just because it is in a register doesn't mean it is an integer. Operations like greater than,
3064b22b933Srs // less than, add, multiply, increment, decrement, etc., are undefined for opaque identifiers,
3074b22b933Srs // and if you make the mistake of trying to do those using the NotAnInteger field, then you'll
3084b22b933Srs // find you get code that doesn't work consistently on big-endian and little-endian machines.
3095ffb0c9bSToomas Soome #if defined(_WIN32)
3105ffb0c9bSToomas Soome  #pragma pack(push,2)
3113b436d06SToomas Soome #elif !defined(__GNUC__)
3123b436d06SToomas Soome  #pragma pack(1)
3135ffb0c9bSToomas Soome #endif
3145ffb0c9bSToomas Soome typedef       union { mDNSu8 b[ 2]; mDNSu16 NotAnInteger; } mDNSOpaque16;
3155ffb0c9bSToomas Soome typedef       union { mDNSu8 b[ 4]; mDNSu32 NotAnInteger; } mDNSOpaque32;
3164b22b933Srs typedef packedunion { mDNSu8 b[ 6]; mDNSu16 w[3]; mDNSu32 l[1]; } mDNSOpaque48;
3175ffb0c9bSToomas Soome typedef       union { mDNSu8 b[ 8]; mDNSu16 w[4]; mDNSu32 l[2]; } mDNSOpaque64;
3185ffb0c9bSToomas Soome typedef       union { mDNSu8 b[16]; mDNSu16 w[8]; mDNSu32 l[4]; } mDNSOpaque128;
3195ffb0c9bSToomas Soome #if defined(_WIN32)
3205ffb0c9bSToomas Soome  #pragma pack(pop)
3213b436d06SToomas Soome #elif !defined(__GNUC__)
3223b436d06SToomas Soome  #pragma pack()
3235ffb0c9bSToomas Soome #endif
3245ffb0c9bSToomas Soome 
3255ffb0c9bSToomas Soome typedef mDNSOpaque16 mDNSIPPort;        // An IP port is a two-byte opaque identifier (not an integer)
3265ffb0c9bSToomas Soome typedef mDNSOpaque32 mDNSv4Addr;        // An IP address is a four-byte opaque identifier (not an integer)
3275ffb0c9bSToomas Soome typedef mDNSOpaque128 mDNSv6Addr;       // An IPv6 address is a 16-byte opaque identifier (not an integer)
3285ffb0c9bSToomas Soome typedef mDNSOpaque48 mDNSEthAddr;       // An Ethernet address is a six-byte opaque identifier (not an integer)
3294b22b933Srs 
3305ffb0c9bSToomas Soome // Bit operations for opaque 64 bit quantity. Uses the 32 bit quantity(l[2]) to set and clear bits
3315ffb0c9bSToomas Soome #define mDNSNBBY 8
3325ffb0c9bSToomas Soome #define bit_set_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] |= (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
3335ffb0c9bSToomas Soome #define bit_clr_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] &= ~(1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
3345ffb0c9bSToomas Soome #define bit_get_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] & (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
3354b22b933Srs 
336c65ebfc7SToomas Soome // Bit operations for opaque 128 bit quantity. Uses the 32 bit quantity(l[4]) to set and clear bits
337c65ebfc7SToomas Soome #define bit_set_opaque128(op128, index) (op128.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] |= (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
338c65ebfc7SToomas Soome #define bit_clr_opaque128(op128, index) (op128.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] &= ~(1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
339c65ebfc7SToomas Soome #define bit_get_opaque128(op128, index) (op128.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] & (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
340c65ebfc7SToomas Soome 
341c65ebfc7SToomas Soome typedef enum
3425ffb0c9bSToomas Soome {
3435ffb0c9bSToomas Soome     mDNSAddrType_None    = 0,
3445ffb0c9bSToomas Soome     mDNSAddrType_IPv4    = 4,
3455ffb0c9bSToomas Soome     mDNSAddrType_IPv6    = 6,
3465ffb0c9bSToomas Soome     mDNSAddrType_Unknown = ~0   // Special marker value used in known answer list recording
347c65ebfc7SToomas Soome } mDNSAddr_Type;
3485ffb0c9bSToomas Soome 
349c65ebfc7SToomas Soome typedef enum
3505ffb0c9bSToomas Soome {
3515ffb0c9bSToomas Soome     mDNSTransport_None = 0,
3525ffb0c9bSToomas Soome     mDNSTransport_UDP  = 1,
3535ffb0c9bSToomas Soome     mDNSTransport_TCP  = 2
354c65ebfc7SToomas Soome } mDNSTransport_Type;
3554b22b933Srs 
3564b22b933Srs typedef struct
3575ffb0c9bSToomas Soome {
3585ffb0c9bSToomas Soome     mDNSs32 type;
3595ffb0c9bSToomas Soome     union { mDNSv6Addr v6; mDNSv4Addr v4; } ip;
3605ffb0c9bSToomas Soome } mDNSAddr;
3614b22b933Srs 
3624b22b933Srs enum { mDNSfalse = 0, mDNStrue = 1 };
3634b22b933Srs 
3644b22b933Srs #define mDNSNULL 0L
3654b22b933Srs 
3664b22b933Srs enum
3675ffb0c9bSToomas Soome {
3685ffb0c9bSToomas Soome     mStatus_Waiting           = 1,
3695ffb0c9bSToomas Soome     mStatus_NoError           = 0,
3705ffb0c9bSToomas Soome 
3715ffb0c9bSToomas Soome     // mDNS return values are in the range FFFE FF00 (-65792) to FFFE FFFF (-65537)
3725ffb0c9bSToomas Soome     // The top end of the range (FFFE FFFF) is used for error codes;
3735ffb0c9bSToomas Soome     // the bottom end of the range (FFFE FF00) is used for non-error values;
3745ffb0c9bSToomas Soome 
3755ffb0c9bSToomas Soome     // Error codes:
3765ffb0c9bSToomas Soome     mStatus_UnknownErr                = -65537,     // First value: 0xFFFE FFFF
3775ffb0c9bSToomas Soome     mStatus_NoSuchNameErr             = -65538,
3785ffb0c9bSToomas Soome     mStatus_NoMemoryErr               = -65539,
3795ffb0c9bSToomas Soome     mStatus_BadParamErr               = -65540,
3805ffb0c9bSToomas Soome     mStatus_BadReferenceErr           = -65541,
3815ffb0c9bSToomas Soome     mStatus_BadStateErr               = -65542,
3825ffb0c9bSToomas Soome     mStatus_BadFlagsErr               = -65543,
3835ffb0c9bSToomas Soome     mStatus_UnsupportedErr            = -65544,
3845ffb0c9bSToomas Soome     mStatus_NotInitializedErr         = -65545,
3855ffb0c9bSToomas Soome     mStatus_NoCache                   = -65546,
3865ffb0c9bSToomas Soome     mStatus_AlreadyRegistered         = -65547,
3875ffb0c9bSToomas Soome     mStatus_NameConflict              = -65548,
3885ffb0c9bSToomas Soome     mStatus_Invalid                   = -65549,
3895ffb0c9bSToomas Soome     mStatus_Firewall                  = -65550,
3905ffb0c9bSToomas Soome     mStatus_Incompatible              = -65551,
3915ffb0c9bSToomas Soome     mStatus_BadInterfaceErr           = -65552,
3925ffb0c9bSToomas Soome     mStatus_Refused                   = -65553,
3935ffb0c9bSToomas Soome     mStatus_NoSuchRecord              = -65554,
3945ffb0c9bSToomas Soome     mStatus_NoAuth                    = -65555,
3955ffb0c9bSToomas Soome     mStatus_NoSuchKey                 = -65556,
3965ffb0c9bSToomas Soome     mStatus_NATTraversal              = -65557,
3975ffb0c9bSToomas Soome     mStatus_DoubleNAT                 = -65558,
3985ffb0c9bSToomas Soome     mStatus_BadTime                   = -65559,
3995ffb0c9bSToomas Soome     mStatus_BadSig                    = -65560,     // while we define this per RFC 2845, BIND 9 returns Refused for bad/missing signatures
4005ffb0c9bSToomas Soome     mStatus_BadKey                    = -65561,
4015ffb0c9bSToomas Soome     mStatus_TransientErr              = -65562,     // transient failures, e.g. sending packets shortly after a network transition or wake from sleep
4025ffb0c9bSToomas Soome     mStatus_ServiceNotRunning         = -65563,     // Background daemon not running
4035ffb0c9bSToomas Soome     mStatus_NATPortMappingUnsupported = -65564,     // NAT doesn't support PCP, NAT-PMP or UPnP
4045ffb0c9bSToomas Soome     mStatus_NATPortMappingDisabled    = -65565,     // NAT supports PCP, NAT-PMP or UPnP, but it's disabled by the administrator
4055ffb0c9bSToomas Soome     mStatus_NoRouter                  = -65566,
4065ffb0c9bSToomas Soome     mStatus_PollingMode               = -65567,
4075ffb0c9bSToomas Soome     mStatus_Timeout                   = -65568,
408*472cd20dSToomas Soome     mStatus_DefunctConnection         = -65569,
409*472cd20dSToomas Soome     mStatus_PolicyDenied              = -65570,
410*472cd20dSToomas Soome     // -65571 to -65785 currently unused; available for allocation
411*472cd20dSToomas Soome 
412*472cd20dSToomas Soome     // udp connection status
413*472cd20dSToomas Soome     mStatus_HostUnreachErr    = -65786,
4145ffb0c9bSToomas Soome 
4155ffb0c9bSToomas Soome     // tcp connection status
4165ffb0c9bSToomas Soome     mStatus_ConnPending       = -65787,
4175ffb0c9bSToomas Soome     mStatus_ConnFailed        = -65788,
4185ffb0c9bSToomas Soome     mStatus_ConnEstablished   = -65789,
4195ffb0c9bSToomas Soome 
4205ffb0c9bSToomas Soome     // Non-error values:
4215ffb0c9bSToomas Soome     mStatus_GrowCache         = -65790,
4225ffb0c9bSToomas Soome     mStatus_ConfigChanged     = -65791,
4235ffb0c9bSToomas Soome     mStatus_MemFree           = -65792      // Last value: 0xFFFE FF00
424*472cd20dSToomas Soome 
425*472cd20dSToomas Soome     // mStatus_MemFree is the last legal mDNS error code, at the end of the range allocated for mDNS
4265ffb0c9bSToomas Soome };
4274b22b933Srs 
4284b22b933Srs typedef mDNSs32 mStatus;
429*472cd20dSToomas Soome 
4305ffb0c9bSToomas Soome #define MaxIp 5 // Needs to be consistent with MaxInputIf in dns_services.h
4315ffb0c9bSToomas Soome 
4325ffb0c9bSToomas Soome typedef enum { q_stop = 0, q_start } q_state;
4335ffb0c9bSToomas Soome typedef enum { reg_stop = 0, reg_start } reg_state;
4344b22b933Srs 
4354b22b933Srs // RFC 1034/1035 specify that a domain label consists of a length byte plus up to 63 characters
4364b22b933Srs #define MAX_DOMAIN_LABEL 63
4375ffb0c9bSToomas Soome typedef struct { mDNSu8 c[ 64]; } domainlabel;      // One label: length byte and up to 63 characters
4384b22b933Srs 
4395ffb0c9bSToomas Soome // RFC 1034/1035/2181 specify that a domain name (length bytes and data bytes) may be up to 255 bytes long,
4405ffb0c9bSToomas Soome // plus the terminating zero at the end makes 256 bytes total in the on-the-wire format.
4415ffb0c9bSToomas Soome #define MAX_DOMAIN_NAME 256
4425ffb0c9bSToomas Soome typedef struct { mDNSu8 c[256]; } domainname;       // Up to 256 bytes of length-prefixed domainlabels
4434b22b933Srs 
4445ffb0c9bSToomas Soome typedef struct { mDNSu8 c[256]; } UTF8str255;       // Null-terminated C string
4454b22b933Srs 
4465ffb0c9bSToomas Soome // The longest legal textual form of a DNS name is 1009 bytes, including the C-string terminating NULL at the end.
4474b22b933Srs // Explanation:
4484b22b933Srs // When a native domainname object is converted to printable textual form using ConvertDomainNameToCString(),
4494b22b933Srs // non-printing characters are represented in the conventional DNS way, as '\ddd', where ddd is a three-digit decimal number.
4505ffb0c9bSToomas Soome // The longest legal domain name is 256 bytes, in the form of four labels as shown below:
4515ffb0c9bSToomas Soome // Length byte, 63 data bytes, length byte, 63 data bytes, length byte, 63 data bytes, length byte, 62 data bytes, zero byte.
4524b22b933Srs // Each label is encoded textually as characters followed by a trailing dot.
4534b22b933Srs // If every character has to be represented as a four-byte escape sequence, then this makes the maximum textual form four labels
4544b22b933Srs // plus the C-string terminating NULL as shown below:
4555ffb0c9bSToomas Soome // 63*4+1 + 63*4+1 + 63*4+1 + 62*4+1 + 1 = 1009.
4564b22b933Srs // Note that MAX_ESCAPED_DOMAIN_LABEL is not normally used: If you're only decoding a single label, escaping is usually not required.
4574b22b933Srs // It is for domain names, where dots are used as label separators, that proper escaping is vital.
4584b22b933Srs #define MAX_ESCAPED_DOMAIN_LABEL 254
4595ffb0c9bSToomas Soome #define MAX_ESCAPED_DOMAIN_NAME 1009
4605ffb0c9bSToomas Soome 
4615ffb0c9bSToomas Soome // MAX_REVERSE_MAPPING_NAME
4625ffb0c9bSToomas Soome // For IPv4: "123.123.123.123.in-addr.arpa."  30 bytes including terminating NUL
4635ffb0c9bSToomas Soome // 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
4645ffb0c9bSToomas Soome 
4655ffb0c9bSToomas Soome #define MAX_REVERSE_MAPPING_NAME_V4 30
4665ffb0c9bSToomas Soome #define MAX_REVERSE_MAPPING_NAME_V6 74
4675ffb0c9bSToomas Soome #define MAX_REVERSE_MAPPING_NAME    74
4684b22b933Srs 
4694b22b933Srs // Most records have a TTL of 75 minutes, so that their 80% cache-renewal query occurs once per hour.
4704b22b933Srs // For records containing a hostname (in the name on the left, or in the rdata on the right),
4714b22b933Srs // like A, AAAA, reverse-mapping PTR, and SRV, we use a two-minute TTL by default, because we don't want
4724b22b933Srs // them to hang around for too long in the cache if the host in question crashes or otherwise goes away.
4735ffb0c9bSToomas Soome 
4744b22b933Srs #define kStandardTTL (3600UL * 100 / 80)
4754b22b933Srs #define kHostNameTTL 120UL
4765ffb0c9bSToomas Soome 
4775ffb0c9bSToomas Soome // Multicast DNS uses announcements (gratuitous responses) to update peer caches.
4785ffb0c9bSToomas Soome // This means it is feasible to use relatively larger TTL values than we might otherwise
4795ffb0c9bSToomas Soome // use, because we have a cache coherency protocol to keep the peer caches up to date.
4805ffb0c9bSToomas Soome // With Unicast DNS, once an authoritative server gives a record with a certain TTL value to a client
4815ffb0c9bSToomas Soome // or caching server, that client or caching server is entitled to hold onto the record until its TTL
4825ffb0c9bSToomas Soome // expires, and has no obligation to contact the authoritative server again until that time arrives.
4835ffb0c9bSToomas Soome // This means that whereas Multicast DNS can use announcements to pre-emptively update stale data
4845ffb0c9bSToomas Soome // before it would otherwise have expired, standard Unicast DNS (not using LLQs) has no equivalent
4855ffb0c9bSToomas Soome // mechanism, and TTL expiry is the *only* mechanism by which stale data gets deleted. Because of this,
4865ffb0c9bSToomas Soome // we currently limit the TTL to ten seconds in such cases where no dynamic cache updating is possible.
4875ffb0c9bSToomas Soome #define kStaticCacheTTL 10
4884b22b933Srs 
4894b22b933Srs #define DefaultTTLforRRType(X) (((X) == kDNSType_A || (X) == kDNSType_AAAA || (X) == kDNSType_SRV) ? kHostNameTTL : kStandardTTL)
4905ffb0c9bSToomas Soome #define mDNS_KeepaliveRecord(rr) ((rr)->rrtype == kDNSType_NULL && SameDomainLabel(SecondLabel((rr)->name)->c, (mDNSu8 *)"\x0A_keepalive"))
4915ffb0c9bSToomas Soome 
4925ffb0c9bSToomas Soome // Number of times keepalives are sent if no ACK is received before waking up the system
4935ffb0c9bSToomas Soome // this is analogous to net.inet.tcp.keepcnt
4945ffb0c9bSToomas Soome #define kKeepaliveRetryCount    10
4955ffb0c9bSToomas Soome // The frequency at which keepalives are retried if no ACK is received
4965ffb0c9bSToomas Soome #define kKeepaliveRetryInterval 30
4975ffb0c9bSToomas Soome 
4985ffb0c9bSToomas Soome typedef struct AuthRecord_struct AuthRecord;
4995ffb0c9bSToomas Soome typedef struct ServiceRecordSet_struct ServiceRecordSet;
5005ffb0c9bSToomas Soome typedef struct CacheRecord_struct CacheRecord;
5015ffb0c9bSToomas Soome typedef struct CacheGroup_struct CacheGroup;
5025ffb0c9bSToomas Soome typedef struct AuthGroup_struct AuthGroup;
5035ffb0c9bSToomas Soome typedef struct DNSQuestion_struct DNSQuestion;
5045ffb0c9bSToomas Soome typedef struct ZoneData_struct ZoneData;
5055ffb0c9bSToomas Soome typedef struct mDNS_struct mDNS;
5065ffb0c9bSToomas Soome typedef struct mDNS_PlatformSupport_struct mDNS_PlatformSupport;
5075ffb0c9bSToomas Soome typedef struct NATTraversalInfo_struct NATTraversalInfo;
5085ffb0c9bSToomas Soome typedef struct ResourceRecord_struct ResourceRecord;
5095ffb0c9bSToomas Soome 
5105ffb0c9bSToomas Soome // Structure to abstract away the differences between TCP/SSL sockets, and one for UDP sockets
5115ffb0c9bSToomas Soome // The actual definition of these structures appear in the appropriate platform support code
512*472cd20dSToomas Soome typedef struct TCPListener_struct TCPListener;
5135ffb0c9bSToomas Soome typedef struct TCPSocket_struct TCPSocket;
5145ffb0c9bSToomas Soome typedef struct UDPSocket_struct UDPSocket;
5154b22b933Srs 
5164b22b933Srs // ***************************************************************************
5174b22b933Srs #if 0
5185ffb0c9bSToomas Soome #pragma mark -
5194b22b933Srs #pragma mark - DNS Message structures
5204b22b933Srs #endif
5214b22b933Srs 
5224b22b933Srs #define mDNS_numZones   numQuestions
5234b22b933Srs #define mDNS_numPrereqs numAnswers
5244b22b933Srs #define mDNS_numUpdates numAuthorities
5254b22b933Srs 
526c65ebfc7SToomas Soome typedef struct
5275ffb0c9bSToomas Soome {
5285ffb0c9bSToomas Soome     mDNSOpaque16 id;
5295ffb0c9bSToomas Soome     mDNSOpaque16 flags;
5305ffb0c9bSToomas Soome     mDNSu16 numQuestions;
5315ffb0c9bSToomas Soome     mDNSu16 numAnswers;
5325ffb0c9bSToomas Soome     mDNSu16 numAuthorities;
5335ffb0c9bSToomas Soome     mDNSu16 numAdditionals;
5345ffb0c9bSToomas Soome } DNSMessageHeader;
5354b22b933Srs 
5364b22b933Srs // We can send and receive packets up to 9000 bytes (Ethernet Jumbo Frame size, if that ever becomes widely used)
5374b22b933Srs // However, in the normal case we try to limit packets to 1500 bytes so that we don't get IP fragmentation on standard Ethernet
5384b22b933Srs // 40 (IPv6 header) + 8 (UDP header) + 12 (DNS message header) + 1440 (DNS message body) = 1500 total
5395ffb0c9bSToomas Soome #ifndef AbsoluteMaxDNSMessageData
5404b22b933Srs #define AbsoluteMaxDNSMessageData 8940
5415ffb0c9bSToomas Soome #endif
5424b22b933Srs #define NormalMaxDNSMessageData 1440
543c65ebfc7SToomas Soome typedef struct
5445ffb0c9bSToomas Soome {
5455ffb0c9bSToomas Soome     DNSMessageHeader h;                     // Note: Size 12 bytes
5465ffb0c9bSToomas Soome     mDNSu8 data[AbsoluteMaxDNSMessageData]; // 40 (IPv6) + 8 (UDP) + 12 (DNS header) + 8940 (data) = 9000
5475ffb0c9bSToomas Soome } DNSMessage;
5485ffb0c9bSToomas Soome 
5495ffb0c9bSToomas Soome typedef struct tcpInfo_t
5505ffb0c9bSToomas Soome {
5515ffb0c9bSToomas Soome     mDNS             *m;
5525ffb0c9bSToomas Soome     TCPSocket        *sock;
5535ffb0c9bSToomas Soome     DNSMessage request;
5545ffb0c9bSToomas Soome     int requestLen;
5555ffb0c9bSToomas Soome     DNSQuestion      *question;   // For queries
5565ffb0c9bSToomas Soome     AuthRecord       *rr;         // For record updates
5575ffb0c9bSToomas Soome     mDNSAddr Addr;
5585ffb0c9bSToomas Soome     mDNSIPPort Port;
5595ffb0c9bSToomas Soome     mDNSIPPort SrcPort;
5605ffb0c9bSToomas Soome     DNSMessage       *reply;
5615ffb0c9bSToomas Soome     mDNSu16 replylen;
5625ffb0c9bSToomas Soome     unsigned long nread;
5635ffb0c9bSToomas Soome     int numReplies;
5645ffb0c9bSToomas Soome } tcpInfo_t;
5655ffb0c9bSToomas Soome 
5665ffb0c9bSToomas Soome // ***************************************************************************
5675ffb0c9bSToomas Soome #if 0
5685ffb0c9bSToomas Soome #pragma mark -
5695ffb0c9bSToomas Soome #pragma mark - Other Packet Format Structures
5705ffb0c9bSToomas Soome #endif
5715ffb0c9bSToomas Soome 
5725ffb0c9bSToomas Soome typedef packedstruct
5735ffb0c9bSToomas Soome {
5745ffb0c9bSToomas Soome     mDNSEthAddr dst;
5755ffb0c9bSToomas Soome     mDNSEthAddr src;
5765ffb0c9bSToomas Soome     mDNSOpaque16 ethertype;
5775ffb0c9bSToomas Soome } EthernetHeader;           // 14 bytes
5785ffb0c9bSToomas Soome 
5795ffb0c9bSToomas Soome typedef packedstruct
5805ffb0c9bSToomas Soome {
5815ffb0c9bSToomas Soome     mDNSOpaque16 hrd;
5825ffb0c9bSToomas Soome     mDNSOpaque16 pro;
5835ffb0c9bSToomas Soome     mDNSu8 hln;
5845ffb0c9bSToomas Soome     mDNSu8 pln;
5855ffb0c9bSToomas Soome     mDNSOpaque16 op;
5865ffb0c9bSToomas Soome     mDNSEthAddr sha;
5875ffb0c9bSToomas Soome     mDNSv4Addr spa;
5885ffb0c9bSToomas Soome     mDNSEthAddr tha;
5895ffb0c9bSToomas Soome     mDNSv4Addr tpa;
5905ffb0c9bSToomas Soome } ARP_EthIP;                // 28 bytes
5915ffb0c9bSToomas Soome 
5925ffb0c9bSToomas Soome typedef packedstruct
5935ffb0c9bSToomas Soome {
5945ffb0c9bSToomas Soome     mDNSu8 vlen;
5955ffb0c9bSToomas Soome     mDNSu8 tos;
596cda73f64SToomas Soome     mDNSOpaque16 totlen;
5975ffb0c9bSToomas Soome     mDNSOpaque16 id;
5985ffb0c9bSToomas Soome     mDNSOpaque16 flagsfrags;
5995ffb0c9bSToomas Soome     mDNSu8 ttl;
6005ffb0c9bSToomas Soome     mDNSu8 protocol;        // Payload type: 0x06 = TCP, 0x11 = UDP
6015ffb0c9bSToomas Soome     mDNSu16 checksum;
6025ffb0c9bSToomas Soome     mDNSv4Addr src;
6035ffb0c9bSToomas Soome     mDNSv4Addr dst;
6045ffb0c9bSToomas Soome } IPv4Header;               // 20 bytes
6055ffb0c9bSToomas Soome 
6065ffb0c9bSToomas Soome typedef packedstruct
6075ffb0c9bSToomas Soome {
6085ffb0c9bSToomas Soome     mDNSu32 vcf;            // Version, Traffic Class, Flow Label
6095ffb0c9bSToomas Soome     mDNSu16 len;            // Payload Length
6105ffb0c9bSToomas Soome     mDNSu8 pro;             // Type of next header: 0x06 = TCP, 0x11 = UDP, 0x3A = ICMPv6
6115ffb0c9bSToomas Soome     mDNSu8 ttl;             // Hop Limit
6125ffb0c9bSToomas Soome     mDNSv6Addr src;
6135ffb0c9bSToomas Soome     mDNSv6Addr dst;
6145ffb0c9bSToomas Soome } IPv6Header;               // 40 bytes
6155ffb0c9bSToomas Soome 
6165ffb0c9bSToomas Soome typedef packedstruct
6175ffb0c9bSToomas Soome {
6185ffb0c9bSToomas Soome     mDNSv6Addr src;
6195ffb0c9bSToomas Soome     mDNSv6Addr dst;
6205ffb0c9bSToomas Soome     mDNSOpaque32 len;
6215ffb0c9bSToomas Soome     mDNSOpaque32 pro;
6225ffb0c9bSToomas Soome } IPv6PseudoHeader;         // 40 bytes
6235ffb0c9bSToomas Soome 
6245ffb0c9bSToomas Soome typedef union
6255ffb0c9bSToomas Soome {
6265ffb0c9bSToomas Soome     mDNSu8 bytes[20];
6275ffb0c9bSToomas Soome     ARP_EthIP arp;
6285ffb0c9bSToomas Soome     IPv4Header v4;
6295ffb0c9bSToomas Soome     IPv6Header v6;
6305ffb0c9bSToomas Soome } NetworkLayerPacket;
6315ffb0c9bSToomas Soome 
6325ffb0c9bSToomas Soome typedef packedstruct
6335ffb0c9bSToomas Soome {
6345ffb0c9bSToomas Soome     mDNSIPPort src;
6355ffb0c9bSToomas Soome     mDNSIPPort dst;
6365ffb0c9bSToomas Soome     mDNSu32 seq;
6375ffb0c9bSToomas Soome     mDNSu32 ack;
6385ffb0c9bSToomas Soome     mDNSu8 offset;
6395ffb0c9bSToomas Soome     mDNSu8 flags;
6405ffb0c9bSToomas Soome     mDNSu16 window;
6415ffb0c9bSToomas Soome     mDNSu16 checksum;
6425ffb0c9bSToomas Soome     mDNSu16 urgent;
6435ffb0c9bSToomas Soome } TCPHeader;                // 20 bytes; IP protocol type 0x06
6445ffb0c9bSToomas Soome 
6455ffb0c9bSToomas Soome typedef struct
6465ffb0c9bSToomas Soome {
6475ffb0c9bSToomas Soome     mDNSInterfaceID IntfId;
6485ffb0c9bSToomas Soome     mDNSu32 seq;
6495ffb0c9bSToomas Soome     mDNSu32 ack;
6505ffb0c9bSToomas Soome     mDNSu16 window;
6515ffb0c9bSToomas Soome } mDNSTCPInfo;
6525ffb0c9bSToomas Soome 
6535ffb0c9bSToomas Soome typedef packedstruct
6545ffb0c9bSToomas Soome {
6555ffb0c9bSToomas Soome     mDNSIPPort src;
6565ffb0c9bSToomas Soome     mDNSIPPort dst;
6575ffb0c9bSToomas Soome     mDNSu16 len;            // Length including UDP header (i.e. minimum value is 8 bytes)
6585ffb0c9bSToomas Soome     mDNSu16 checksum;
6595ffb0c9bSToomas Soome } UDPHeader;                // 8 bytes; IP protocol type 0x11
6605ffb0c9bSToomas Soome 
661c65ebfc7SToomas Soome typedef struct
6625ffb0c9bSToomas Soome {
6635ffb0c9bSToomas Soome     mDNSu8 type;            // 0x87 == Neighbor Solicitation, 0x88 == Neighbor Advertisement
6645ffb0c9bSToomas Soome     mDNSu8 code;
6655ffb0c9bSToomas Soome     mDNSu16 checksum;
6665ffb0c9bSToomas Soome     mDNSu32 flags_res;      // R/S/O flags and reserved bits
6675ffb0c9bSToomas Soome     mDNSv6Addr target;
6685ffb0c9bSToomas Soome     // Typically 8 bytes of options are also present
6695ffb0c9bSToomas Soome } IPv6NDP;                  // 24 bytes or more; IP protocol type 0x3A
6705ffb0c9bSToomas Soome 
6715ffb0c9bSToomas Soome typedef struct
6725ffb0c9bSToomas Soome {
6735ffb0c9bSToomas Soome     mDNSAddr    ipaddr;
6745ffb0c9bSToomas Soome     char        ethaddr[18];
6755ffb0c9bSToomas Soome } IPAddressMACMapping;
6765ffb0c9bSToomas Soome 
6775ffb0c9bSToomas Soome #define NDP_Sol 0x87
6785ffb0c9bSToomas Soome #define NDP_Adv 0x88
6795ffb0c9bSToomas Soome 
6805ffb0c9bSToomas Soome #define NDP_Router    0x80
6815ffb0c9bSToomas Soome #define NDP_Solicited 0x40
6825ffb0c9bSToomas Soome #define NDP_Override  0x20
6835ffb0c9bSToomas Soome 
6845ffb0c9bSToomas Soome #define NDP_SrcLL 1
6855ffb0c9bSToomas Soome #define NDP_TgtLL 2
6865ffb0c9bSToomas Soome 
6875ffb0c9bSToomas Soome typedef union
6885ffb0c9bSToomas Soome {
6895ffb0c9bSToomas Soome     mDNSu8 bytes[20];
6905ffb0c9bSToomas Soome     TCPHeader tcp;
6915ffb0c9bSToomas Soome     UDPHeader udp;
6925ffb0c9bSToomas Soome     IPv6NDP ndp;
6935ffb0c9bSToomas Soome } TransportLayerPacket;
6945ffb0c9bSToomas Soome 
6955ffb0c9bSToomas Soome typedef packedstruct
6965ffb0c9bSToomas Soome {
6975ffb0c9bSToomas Soome     mDNSOpaque64 InitiatorCookie;
6985ffb0c9bSToomas Soome     mDNSOpaque64 ResponderCookie;
6995ffb0c9bSToomas Soome     mDNSu8 NextPayload;
7005ffb0c9bSToomas Soome     mDNSu8 Version;
7015ffb0c9bSToomas Soome     mDNSu8 ExchangeType;
7025ffb0c9bSToomas Soome     mDNSu8 Flags;
7035ffb0c9bSToomas Soome     mDNSOpaque32 MessageID;
7045ffb0c9bSToomas Soome     mDNSu32 Length;
7055ffb0c9bSToomas Soome } IKEHeader;                // 28 bytes
7064b22b933Srs 
7074b22b933Srs // ***************************************************************************
7084b22b933Srs #if 0
7095ffb0c9bSToomas Soome #pragma mark -
7104b22b933Srs #pragma mark - Resource Record structures
7114b22b933Srs #endif
7124b22b933Srs 
7134b22b933Srs // Authoritative Resource Records:
7144b22b933Srs // There are four basic types: Shared, Advisory, Unique, Known Unique
7154b22b933Srs 
7164b22b933Srs // * Shared Resource Records do not have to be unique
7174b22b933Srs // -- Shared Resource Records are used for DNS-SD service PTRs
7184b22b933Srs // -- It is okay for several hosts to have RRs with the same name but different RDATA
7194b22b933Srs // -- We use a random delay on responses to reduce collisions when all the hosts respond to the same query
7204b22b933Srs // -- These RRs typically have moderately high TTLs (e.g. one hour)
7214b22b933Srs // -- These records are announced on startup and topology changes for the benefit of passive listeners
7224b22b933Srs // -- These records send a goodbye packet when deregistering
7234b22b933Srs //
7244b22b933Srs // * Advisory Resource Records are like Shared Resource Records, except they don't send a goodbye packet
7254b22b933Srs //
7264b22b933Srs // * Unique Resource Records should be unique among hosts within any given mDNS scope
7274b22b933Srs // -- The majority of Resource Records are of this type
7284b22b933Srs // -- If two entities on the network have RRs with the same name but different RDATA, this is a conflict
7294b22b933Srs // -- Responses may be sent immediately, because only one host should be responding to any particular query
7304b22b933Srs // -- These RRs typically have low TTLs (e.g. a few minutes)
7314b22b933Srs // -- On startup and after topology changes, a host issues queries to verify uniqueness
7324b22b933Srs 
7334b22b933Srs // * Known Unique Resource Records are treated like Unique Resource Records, except that mDNS does
7344b22b933Srs // not have to verify their uniqueness because this is already known by other means (e.g. the RR name
7354b22b933Srs // is derived from the host's IP or Ethernet address, which is already known to be a unique identifier).
7364b22b933Srs 
7374b22b933Srs // Summary of properties of different record types:
7384b22b933Srs // Probe?    Does this record type send probes before announcing?
7394b22b933Srs // Conflict? Does this record type react if we observe an apparent conflict?
7404b22b933Srs // Goodbye?  Does this record type send a goodbye packet on departure?
7414b22b933Srs //
7424b22b933Srs //               Probe? Conflict? Goodbye? Notes
7434b22b933Srs // Unregistered                            Should not appear in any list (sanity check value)
7444b22b933Srs // Shared         No      No       Yes     e.g. Service PTR record
7454b22b933Srs // Deregistering  No      No       Yes     Shared record about to announce its departure and leave the list
7464b22b933Srs // Advisory       No      No       No
7474b22b933Srs // Unique         Yes     Yes      No      Record intended to be unique -- will probe to verify
7484b22b933Srs // Verified       Yes     Yes      No      Record has completed probing, and is verified unique
7494b22b933Srs // KnownUnique    No      Yes      No      Record is assumed by other means to be unique
7504b22b933Srs 
7514b22b933Srs // Valid lifecycle of a record:
7524b22b933Srs // Unregistered ->                   Shared      -> Deregistering -(goodbye)-> Unregistered
7534b22b933Srs // Unregistered ->                   Advisory                               -> Unregistered
7544b22b933Srs // Unregistered -> Unique -(probe)-> Verified                               -> Unregistered
7554b22b933Srs // Unregistered ->                   KnownUnique                            -> Unregistered
7564b22b933Srs 
7574b22b933Srs // Each Authoritative kDNSRecordType has only one bit set. This makes it easy to quickly see if a record
7584b22b933Srs // is one of a particular set of types simply by performing the appropriate bitwise masking operation.
7594b22b933Srs 
7605ffb0c9bSToomas Soome // Cache Resource Records (received from the network):
7615ffb0c9bSToomas Soome // There are four basic types: Answer, Unique Answer, Additional, Unique Additional
7625ffb0c9bSToomas Soome // Bit 7 (the top bit) of kDNSRecordType is always set for Cache Resource Records; always clear for Authoritative Resource Records
7635ffb0c9bSToomas Soome // Bit 6 (value 0x40) is set for answer records; clear for authority/additional records
7645ffb0c9bSToomas Soome // Bit 5 (value 0x20) is set for records received with the kDNSClass_UniqueRRSet
7655ffb0c9bSToomas Soome 
766c65ebfc7SToomas Soome typedef enum
7675ffb0c9bSToomas Soome {
7685ffb0c9bSToomas Soome     kDNSRecordTypeUnregistered     = 0x00,  // Not currently in any list
7695ffb0c9bSToomas Soome     kDNSRecordTypeDeregistering    = 0x01,  // Shared record about to announce its departure and leave the list
7705ffb0c9bSToomas Soome 
7715ffb0c9bSToomas Soome     kDNSRecordTypeUnique           = 0x02,  // Will become a kDNSRecordTypeVerified when probing is complete
7725ffb0c9bSToomas Soome 
7735ffb0c9bSToomas Soome     kDNSRecordTypeAdvisory         = 0x04,  // Like Shared, but no goodbye packet
7745ffb0c9bSToomas Soome     kDNSRecordTypeShared           = 0x08,  // Shared means record name does not have to be unique -- use random delay on responses
7755ffb0c9bSToomas Soome 
7765ffb0c9bSToomas Soome     kDNSRecordTypeVerified         = 0x10,  // Unique means mDNS should check that name is unique (and then send immediate responses)
7775ffb0c9bSToomas Soome     kDNSRecordTypeKnownUnique      = 0x20,  // Known Unique means mDNS can assume name is unique without checking
7785ffb0c9bSToomas Soome                                             // For Dynamic Update records, Known Unique means the record must already exist on the server.
7795ffb0c9bSToomas Soome     kDNSRecordTypeUniqueMask       = (kDNSRecordTypeUnique | kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique),
7805ffb0c9bSToomas Soome     kDNSRecordTypeActiveSharedMask = (kDNSRecordTypeAdvisory         | kDNSRecordTypeShared),
7815ffb0c9bSToomas Soome     kDNSRecordTypeActiveUniqueMask = (kDNSRecordTypeVerified         | kDNSRecordTypeKnownUnique),
7825ffb0c9bSToomas Soome     kDNSRecordTypeActiveMask       = (kDNSRecordTypeActiveSharedMask | kDNSRecordTypeActiveUniqueMask),
7835ffb0c9bSToomas Soome 
7845ffb0c9bSToomas Soome     kDNSRecordTypePacketAdd        = 0x80,  // Received in the Additional  Section of a DNS Response
7855ffb0c9bSToomas Soome     kDNSRecordTypePacketAddUnique  = 0x90,  // Received in the Additional  Section of a DNS Response with kDNSClass_UniqueRRSet set
7865ffb0c9bSToomas Soome     kDNSRecordTypePacketAuth       = 0xA0,  // Received in the Authorities Section of a DNS Response
7875ffb0c9bSToomas Soome     kDNSRecordTypePacketAuthUnique = 0xB0,  // Received in the Authorities Section of a DNS Response with kDNSClass_UniqueRRSet set
7885ffb0c9bSToomas Soome     kDNSRecordTypePacketAns        = 0xC0,  // Received in the Answer      Section of a DNS Response
7895ffb0c9bSToomas Soome     kDNSRecordTypePacketAnsUnique  = 0xD0,  // Received in the Answer      Section of a DNS Response with kDNSClass_UniqueRRSet set
7905ffb0c9bSToomas Soome 
7915ffb0c9bSToomas Soome     kDNSRecordTypePacketNegative   = 0xF0,  // Pseudo-RR generated to cache non-existence results like NXDomain
7925ffb0c9bSToomas Soome 
7935ffb0c9bSToomas Soome     kDNSRecordTypePacketUniqueMask = 0x10   // True for PacketAddUnique, PacketAnsUnique, PacketAuthUnique, kDNSRecordTypePacketNegative
794c65ebfc7SToomas Soome } kDNSRecordTypes;
7955ffb0c9bSToomas Soome 
7965ffb0c9bSToomas Soome typedef packedstruct { mDNSu16 priority; mDNSu16 weight; mDNSIPPort port; domainname target;   } rdataSRV;
7975ffb0c9bSToomas Soome typedef packedstruct { mDNSu16 preference;                                domainname exchange; } rdataMX;
7985ffb0c9bSToomas Soome typedef packedstruct { domainname mbox; domainname txt;                                        } rdataRP;
7995ffb0c9bSToomas Soome typedef packedstruct { mDNSu16 preference; domainname map822; domainname mapx400;              } rdataPX;
8005ffb0c9bSToomas Soome 
8015ffb0c9bSToomas Soome typedef packedstruct
8025ffb0c9bSToomas Soome {
8035ffb0c9bSToomas Soome     domainname mname;
8045ffb0c9bSToomas Soome     domainname rname;
8055ffb0c9bSToomas Soome     mDNSs32 serial;     // Modular counter; increases when zone changes
8065ffb0c9bSToomas Soome     mDNSu32 refresh;    // Time in seconds that a slave waits after successful replication of the database before it attempts replication again
8075ffb0c9bSToomas Soome     mDNSu32 retry;      // Time in seconds that a slave waits after an unsuccessful replication attempt before it attempts replication again
8085ffb0c9bSToomas Soome     mDNSu32 expire;     // Time in seconds that a slave holds on to old data while replication attempts remain unsuccessful
8095ffb0c9bSToomas Soome     mDNSu32 min;        // Nominally the minimum record TTL for this zone, in seconds; also used for negative caching.
8105ffb0c9bSToomas Soome } rdataSOA;
8115ffb0c9bSToomas Soome 
8125ffb0c9bSToomas Soome typedef enum
8135ffb0c9bSToomas Soome {
814c65ebfc7SToomas Soome     platform_OSX = 1,   // OSX Platform
815c65ebfc7SToomas Soome     platform_iOS,       // iOS Platform
816c65ebfc7SToomas Soome     platform_Atv,       // Atv Platform
8175ffb0c9bSToomas Soome     platform_NonApple   // Non-Apple (Windows, POSIX) Platform
8185ffb0c9bSToomas Soome } Platform_t;
8195ffb0c9bSToomas Soome 
8205ffb0c9bSToomas Soome // EDNS Option Code registrations are recorded in the "DNS EDNS0 Options" section of
8215ffb0c9bSToomas Soome // <http://www.iana.org/assignments/dns-parameters>
8225ffb0c9bSToomas Soome 
8235ffb0c9bSToomas Soome #define kDNSOpt_LLQ   1
8245ffb0c9bSToomas Soome #define kDNSOpt_Lease 2
8255ffb0c9bSToomas Soome #define kDNSOpt_NSID  3
8265ffb0c9bSToomas Soome #define kDNSOpt_Owner 4
827c65ebfc7SToomas Soome #define kDNSOpt_Trace 65001  // 65001-65534 Reserved for Local/Experimental Use
8285ffb0c9bSToomas Soome 
8295ffb0c9bSToomas Soome typedef struct
8305ffb0c9bSToomas Soome {
8315ffb0c9bSToomas Soome     mDNSu16 vers;
8325ffb0c9bSToomas Soome     mDNSu16 llqOp;
8335ffb0c9bSToomas Soome     mDNSu16 err;        // Or UDP reply port, in setup request
8345ffb0c9bSToomas Soome     // Note: In the in-memory form, there's typically a two-byte space here, so that the following 64-bit id is word-aligned
8355ffb0c9bSToomas Soome     mDNSOpaque64 id;
8365ffb0c9bSToomas Soome     mDNSu32 llqlease;
8375ffb0c9bSToomas Soome } LLQOptData;
8385ffb0c9bSToomas Soome 
8395ffb0c9bSToomas Soome typedef struct
8405ffb0c9bSToomas Soome {
8415ffb0c9bSToomas Soome     mDNSu8 vers;            // Version number of this Owner OPT record
8425ffb0c9bSToomas Soome     mDNSs8 seq;             // Sleep/wake epoch
8435ffb0c9bSToomas Soome     mDNSEthAddr HMAC;       // Host's primary identifier (e.g. MAC of on-board Ethernet)
8445ffb0c9bSToomas Soome     mDNSEthAddr IMAC;       // Interface's MAC address (if different to primary MAC)
8455ffb0c9bSToomas Soome     mDNSOpaque48 password;  // Optional password
8465ffb0c9bSToomas Soome } OwnerOptData;
8475ffb0c9bSToomas Soome 
8485ffb0c9bSToomas Soome typedef struct
8495ffb0c9bSToomas Soome {
8505ffb0c9bSToomas Soome     mDNSu8    platf;      // Running platform (see enum Platform_t)
8515ffb0c9bSToomas Soome     mDNSu32   mDNSv;      // mDNSResponder Version (DNS_SD_H defined in dns_sd.h)
8525ffb0c9bSToomas Soome } TracerOptData;
8535ffb0c9bSToomas Soome 
8545ffb0c9bSToomas Soome // Note: rdataOPT format may be repeated an arbitrary number of times in a single resource record
855c65ebfc7SToomas Soome typedef struct
8565ffb0c9bSToomas Soome {
8575ffb0c9bSToomas Soome     mDNSu16 opt;
8585ffb0c9bSToomas Soome     mDNSu16 optlen;
8595ffb0c9bSToomas Soome     union { LLQOptData llq; mDNSu32 updatelease; OwnerOptData owner; TracerOptData tracer; } u;
8605ffb0c9bSToomas Soome } rdataOPT;
8615ffb0c9bSToomas Soome 
8625ffb0c9bSToomas Soome // Space needed to put OPT records into a packet:
8635ffb0c9bSToomas Soome // Header         11  bytes (name 1, type 2, class 2, TTL 4, length 2)
8645ffb0c9bSToomas Soome // LLQ   rdata    18  bytes (opt 2, len 2, vers 2, op 2, err 2, id 8, lease 4)
8655ffb0c9bSToomas Soome // Lease rdata     8  bytes (opt 2, len 2, lease 4)
8665ffb0c9bSToomas Soome // Owner rdata 12-24  bytes (opt 2, len 2, owner 8-20)
8675ffb0c9bSToomas Soome // Trace rdata     9  bytes (opt 2, len 2, platf 1, mDNSv 4)
8685ffb0c9bSToomas Soome 
8695ffb0c9bSToomas Soome 
8705ffb0c9bSToomas Soome #define DNSOpt_Header_Space                 11
8715ffb0c9bSToomas Soome #define DNSOpt_LLQData_Space               (4 + 2 + 2 + 2 + 8 + 4)
8725ffb0c9bSToomas Soome #define DNSOpt_LeaseData_Space             (4 + 4)
8735ffb0c9bSToomas Soome #define DNSOpt_OwnerData_ID_Space          (4 + 2 + 6)
8745ffb0c9bSToomas Soome #define DNSOpt_OwnerData_ID_Wake_Space     (4 + 2 + 6 + 6)
8755ffb0c9bSToomas Soome #define DNSOpt_OwnerData_ID_Wake_PW4_Space (4 + 2 + 6 + 6 + 4)
8765ffb0c9bSToomas Soome #define DNSOpt_OwnerData_ID_Wake_PW6_Space (4 + 2 + 6 + 6 + 6)
8775ffb0c9bSToomas Soome #define DNSOpt_TraceData_Space             (4 + 1 + 4)
8785ffb0c9bSToomas Soome 
8795ffb0c9bSToomas Soome #define ValidOwnerLength(X) (   (X) == DNSOpt_OwnerData_ID_Space          - 4 || \
8805ffb0c9bSToomas Soome                                 (X) == DNSOpt_OwnerData_ID_Wake_Space     - 4 || \
8815ffb0c9bSToomas Soome                                 (X) == DNSOpt_OwnerData_ID_Wake_PW4_Space - 4 || \
8825ffb0c9bSToomas Soome                                 (X) == DNSOpt_OwnerData_ID_Wake_PW6_Space - 4    )
8835ffb0c9bSToomas Soome 
8845ffb0c9bSToomas Soome #define DNSOpt_Owner_Space(A,B) (mDNSSameEthAddress((A),(B)) ? DNSOpt_OwnerData_ID_Space : DNSOpt_OwnerData_ID_Wake_Space)
8855ffb0c9bSToomas Soome 
8865ffb0c9bSToomas Soome #define DNSOpt_Data_Space(O) (                                  \
8875ffb0c9bSToomas Soome         (O)->opt == kDNSOpt_LLQ   ? DNSOpt_LLQData_Space   :        \
8885ffb0c9bSToomas Soome         (O)->opt == kDNSOpt_Lease ? DNSOpt_LeaseData_Space :        \
8895ffb0c9bSToomas Soome         (O)->opt == kDNSOpt_Trace ? DNSOpt_TraceData_Space :        \
8905ffb0c9bSToomas Soome         (O)->opt == kDNSOpt_Owner ? DNSOpt_Owner_Space(&(O)->u.owner.HMAC, &(O)->u.owner.IMAC) : 0x10000)
8915ffb0c9bSToomas Soome 
8925ffb0c9bSToomas Soome // NSEC record is defined in RFC 4034.
8935ffb0c9bSToomas Soome // 16 bit RRTYPE space is split into 256 windows and each window has 256 bits (32 bytes).
8945ffb0c9bSToomas Soome // If we create a structure for NSEC, it's size would be:
8955ffb0c9bSToomas Soome //
8965ffb0c9bSToomas Soome //   256 bytes domainname 'nextname'
8975ffb0c9bSToomas Soome // + 256 * 34 = 8704 bytes of bitmap data
8985ffb0c9bSToomas Soome // = 8960 bytes total
8995ffb0c9bSToomas Soome //
9005ffb0c9bSToomas Soome // This would be a waste, as types about 256 are not very common. But it would be odd, if we receive
9015ffb0c9bSToomas Soome // a type above 256 (.US zone had TYPE65534 when this code was written) and not able to handle it.
9025ffb0c9bSToomas Soome // Hence, we handle any size by not fixing a strucure in place. The following is just a placeholder
9035ffb0c9bSToomas Soome // and never used anywhere.
9045ffb0c9bSToomas Soome //
9055ffb0c9bSToomas Soome #define NSEC_MCAST_WINDOW_SIZE 32
9065ffb0c9bSToomas Soome typedef struct
9075ffb0c9bSToomas Soome {
9085ffb0c9bSToomas Soome     domainname *next; //placeholders are uncommented because C89 in Windows requires that a struct has at least a member.
9095ffb0c9bSToomas Soome     char bitmap[32];
9105ffb0c9bSToomas Soome } rdataNSEC;
9115ffb0c9bSToomas Soome 
9125ffb0c9bSToomas Soome // StandardAuthRDSize is 264 (256+8), which is large enough to hold a maximum-sized SRV record (6 + 256 bytes)
9135ffb0c9bSToomas Soome // MaximumRDSize is 8K the absolute maximum we support (at least for now)
9145ffb0c9bSToomas Soome #define StandardAuthRDSize 264
9155ffb0c9bSToomas Soome #ifndef MaximumRDSize
9165ffb0c9bSToomas Soome #define MaximumRDSize 8192
9175ffb0c9bSToomas Soome #endif
9185ffb0c9bSToomas Soome 
9195ffb0c9bSToomas Soome // InlineCacheRDSize is 68
9205ffb0c9bSToomas Soome // Records received from the network with rdata this size or less have their rdata stored right in the CacheRecord object
9215ffb0c9bSToomas Soome // Records received from the network with rdata larger than this have additional storage allocated for the rdata
9225ffb0c9bSToomas Soome // A quick unscientific sample from a busy network at Apple with lots of machines revealed this:
9235ffb0c9bSToomas Soome // 1461 records in cache
9245ffb0c9bSToomas Soome // 292 were one-byte TXT records
9255ffb0c9bSToomas Soome // 136 were four-byte A records
9265ffb0c9bSToomas Soome // 184 were sixteen-byte AAAA records
9275ffb0c9bSToomas Soome // 780 were various PTR, TXT and SRV records from 12-64 bytes
9285ffb0c9bSToomas Soome // Only 69 records had rdata bigger than 64 bytes
9295ffb0c9bSToomas Soome // Note that since CacheRecord object and a CacheGroup object are allocated out of the same pool, it's sensible to
9305ffb0c9bSToomas Soome // have them both be the same size. Making one smaller without making the other smaller won't actually save any memory.
9315ffb0c9bSToomas Soome #define InlineCacheRDSize 68
9325ffb0c9bSToomas Soome 
9335ffb0c9bSToomas Soome // The RDataBody union defines the common rdata types that fit into our 264-byte limit
9345ffb0c9bSToomas Soome typedef union
9355ffb0c9bSToomas Soome {
9365ffb0c9bSToomas Soome     mDNSu8 data[StandardAuthRDSize];
9375ffb0c9bSToomas Soome     mDNSv4Addr ipv4;        // For 'A' record
9385ffb0c9bSToomas Soome     domainname name;        // For PTR, NS, CNAME, DNAME
9395ffb0c9bSToomas Soome     UTF8str255 txt;
9405ffb0c9bSToomas Soome     rdataMX mx;
9415ffb0c9bSToomas Soome     mDNSv6Addr ipv6;        // For 'AAAA' record
9425ffb0c9bSToomas Soome     rdataSRV srv;
9435ffb0c9bSToomas Soome     rdataOPT opt[2];        // For EDNS0 OPT record; RDataBody may contain multiple variable-length rdataOPT objects packed together
9445ffb0c9bSToomas Soome } RDataBody;
9455ffb0c9bSToomas Soome 
9465ffb0c9bSToomas Soome // The RDataBody2 union is the same as above, except it includes fields for the larger types like soa, rp, px
9475ffb0c9bSToomas Soome typedef union
9485ffb0c9bSToomas Soome {
9495ffb0c9bSToomas Soome     mDNSu8 data[StandardAuthRDSize];
9505ffb0c9bSToomas Soome     mDNSv4Addr ipv4;        // For 'A' record
9515ffb0c9bSToomas Soome     domainname name;        // For PTR, NS, CNAME, DNAME
9525ffb0c9bSToomas Soome     rdataSOA soa;           // This is large; not included in the normal RDataBody definition
9535ffb0c9bSToomas Soome     UTF8str255 txt;
9545ffb0c9bSToomas Soome     rdataMX mx;
9555ffb0c9bSToomas Soome     rdataRP rp;             // This is large; not included in the normal RDataBody definition
9565ffb0c9bSToomas Soome     rdataPX px;             // This is large; not included in the normal RDataBody definition
9575ffb0c9bSToomas Soome     mDNSv6Addr ipv6;        // For 'AAAA' record
9585ffb0c9bSToomas Soome     rdataSRV srv;
9595ffb0c9bSToomas Soome     rdataOPT opt[2];        // For EDNS0 OPT record; RDataBody may contain multiple variable-length rdataOPT objects packed together
9605ffb0c9bSToomas Soome } RDataBody2;
9615ffb0c9bSToomas Soome 
9625ffb0c9bSToomas Soome typedef struct
9635ffb0c9bSToomas Soome {
9645ffb0c9bSToomas Soome     mDNSu16 MaxRDLength;    // Amount of storage allocated for rdata (usually sizeof(RDataBody))
9655ffb0c9bSToomas Soome     mDNSu16 padding;        // So that RDataBody is aligned on 32-bit boundary
9665ffb0c9bSToomas Soome     RDataBody u;
9675ffb0c9bSToomas Soome } RData;
9685ffb0c9bSToomas Soome 
9695ffb0c9bSToomas Soome // sizeofRDataHeader should be 4 bytes
9705ffb0c9bSToomas Soome #define sizeofRDataHeader (sizeof(RData) - sizeof(RDataBody))
9715ffb0c9bSToomas Soome 
9725ffb0c9bSToomas Soome // RData_small is a smaller version of the RData object, used for inline data storage embedded in a CacheRecord_struct
9735ffb0c9bSToomas Soome typedef struct
9745ffb0c9bSToomas Soome {
9755ffb0c9bSToomas Soome     mDNSu16 MaxRDLength;    // Storage allocated for data (may be greater than InlineCacheRDSize if additional storage follows this object)
9765ffb0c9bSToomas Soome     mDNSu16 padding;        // So that data is aligned on 32-bit boundary
9775ffb0c9bSToomas Soome     mDNSu8 data[InlineCacheRDSize];
9785ffb0c9bSToomas Soome } RData_small;
9795ffb0c9bSToomas Soome 
9805ffb0c9bSToomas Soome // Note: Within an mDNSRecordCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
9815ffb0c9bSToomas Soome typedef void mDNSRecordCallback (mDNS *const m, AuthRecord *const rr, mStatus result);
9825ffb0c9bSToomas Soome 
9835ffb0c9bSToomas Soome // Note:
9845ffb0c9bSToomas Soome // Restrictions: An mDNSRecordUpdateCallback may not make any mDNS API calls.
9855ffb0c9bSToomas Soome // The intent of this callback is to allow the client to free memory, if necessary.
9865ffb0c9bSToomas Soome // The internal data structures of the mDNS code may not be in a state where mDNS API calls may be made safely.
9875ffb0c9bSToomas Soome typedef void mDNSRecordUpdateCallback (mDNS *const m, AuthRecord *const rr, RData *OldRData, mDNSu16 OldRDLen);
9885ffb0c9bSToomas Soome 
9895ffb0c9bSToomas Soome // ***************************************************************************
9905ffb0c9bSToomas Soome #if 0
9915ffb0c9bSToomas Soome #pragma mark -
9925ffb0c9bSToomas Soome #pragma mark - NAT Traversal structures and constants
9935ffb0c9bSToomas Soome #endif
9945ffb0c9bSToomas Soome 
9955ffb0c9bSToomas Soome #define NATMAP_MAX_RETRY_INTERVAL    ((mDNSPlatformOneSecond * 60) * 15)    // Max retry interval is 15 minutes
9965ffb0c9bSToomas Soome #define NATMAP_MIN_RETRY_INTERVAL     (mDNSPlatformOneSecond * 2)           // Min retry interval is 2 seconds
9975ffb0c9bSToomas Soome #define NATMAP_INIT_RETRY             (mDNSPlatformOneSecond / 4)           // start at 250ms w/ exponential decay
9985ffb0c9bSToomas Soome #define NATMAP_DEFAULT_LEASE          (60 * 60 * 2)                         // 2 hour lease life in seconds
9995ffb0c9bSToomas Soome #define NATMAP_VERS 0
10005ffb0c9bSToomas Soome 
10015ffb0c9bSToomas Soome typedef enum
10025ffb0c9bSToomas Soome {
10035ffb0c9bSToomas Soome     NATOp_AddrRequest    = 0,
10045ffb0c9bSToomas Soome     NATOp_MapUDP         = 1,
10055ffb0c9bSToomas Soome     NATOp_MapTCP         = 2,
10065ffb0c9bSToomas Soome 
10075ffb0c9bSToomas Soome     NATOp_AddrResponse   = 0x80 | 0,
10085ffb0c9bSToomas Soome     NATOp_MapUDPResponse = 0x80 | 1,
10095ffb0c9bSToomas Soome     NATOp_MapTCPResponse = 0x80 | 2,
10105ffb0c9bSToomas Soome } NATOp_t;
10115ffb0c9bSToomas Soome 
10125ffb0c9bSToomas Soome enum
10135ffb0c9bSToomas Soome {
10145ffb0c9bSToomas Soome     NATErr_None    = 0,
10155ffb0c9bSToomas Soome     NATErr_Vers    = 1,
10165ffb0c9bSToomas Soome     NATErr_Refused = 2,
10175ffb0c9bSToomas Soome     NATErr_NetFail = 3,
10185ffb0c9bSToomas Soome     NATErr_Res     = 4,
10195ffb0c9bSToomas Soome     NATErr_Opcode  = 5
10205ffb0c9bSToomas Soome };
10215ffb0c9bSToomas Soome 
10225ffb0c9bSToomas Soome typedef mDNSu16 NATErr_t;
10235ffb0c9bSToomas Soome 
10245ffb0c9bSToomas Soome typedef packedstruct
10255ffb0c9bSToomas Soome {
10265ffb0c9bSToomas Soome     mDNSu8 vers;
10275ffb0c9bSToomas Soome     mDNSu8 opcode;
10285ffb0c9bSToomas Soome } NATAddrRequest;
10295ffb0c9bSToomas Soome 
10305ffb0c9bSToomas Soome typedef packedstruct
10315ffb0c9bSToomas Soome {
10325ffb0c9bSToomas Soome     mDNSu8 vers;
10335ffb0c9bSToomas Soome     mDNSu8 opcode;
10345ffb0c9bSToomas Soome     mDNSu16 err;
10355ffb0c9bSToomas Soome     mDNSu32 upseconds;          // Time since last NAT engine reboot, in seconds
10365ffb0c9bSToomas Soome     mDNSv4Addr ExtAddr;
10375ffb0c9bSToomas Soome } NATAddrReply;
10385ffb0c9bSToomas Soome 
10395ffb0c9bSToomas Soome typedef packedstruct
10405ffb0c9bSToomas Soome {
10415ffb0c9bSToomas Soome     mDNSu8 vers;
10425ffb0c9bSToomas Soome     mDNSu8 opcode;
10435ffb0c9bSToomas Soome     mDNSOpaque16 unused;
10445ffb0c9bSToomas Soome     mDNSIPPort intport;
10455ffb0c9bSToomas Soome     mDNSIPPort extport;
10465ffb0c9bSToomas Soome     mDNSu32 NATReq_lease;
10475ffb0c9bSToomas Soome } NATPortMapRequest;
10484b22b933Srs 
10495ffb0c9bSToomas Soome typedef packedstruct
10505ffb0c9bSToomas Soome {
10515ffb0c9bSToomas Soome     mDNSu8 vers;
10525ffb0c9bSToomas Soome     mDNSu8 opcode;
10535ffb0c9bSToomas Soome     mDNSu16 err;
10545ffb0c9bSToomas Soome     mDNSu32 upseconds;          // Time since last NAT engine reboot, in seconds
10555ffb0c9bSToomas Soome     mDNSIPPort intport;
10565ffb0c9bSToomas Soome     mDNSIPPort extport;
10575ffb0c9bSToomas Soome     mDNSu32 NATRep_lease;
10585ffb0c9bSToomas Soome } NATPortMapReply;
10594b22b933Srs 
10605ffb0c9bSToomas Soome // PCP Support for IPv4 mappings
10614b22b933Srs 
10625ffb0c9bSToomas Soome #define PCP_VERS 0x02
10635ffb0c9bSToomas Soome #define PCP_WAITSECS_AFTER_EPOCH_INVALID 5
10644b22b933Srs 
10655ffb0c9bSToomas Soome typedef enum
10665ffb0c9bSToomas Soome {
10675ffb0c9bSToomas Soome     PCPOp_Announce = 0,
10685ffb0c9bSToomas Soome     PCPOp_Map      = 1
10695ffb0c9bSToomas Soome } PCPOp_t;
10704b22b933Srs 
10715ffb0c9bSToomas Soome typedef enum
10725ffb0c9bSToomas Soome {
10735ffb0c9bSToomas Soome     PCPProto_All = 0,
10745ffb0c9bSToomas Soome     PCPProto_TCP = 6,
10755ffb0c9bSToomas Soome     PCPProto_UDP = 17
10765ffb0c9bSToomas Soome } PCPProto_t;
10774b22b933Srs 
10785ffb0c9bSToomas Soome typedef enum
10795ffb0c9bSToomas Soome {
10805ffb0c9bSToomas Soome     PCPResult_Success         = 0,
10815ffb0c9bSToomas Soome     PCPResult_UnsuppVersion   = 1,
10825ffb0c9bSToomas Soome     PCPResult_NotAuthorized   = 2,
10835ffb0c9bSToomas Soome     PCPResult_MalformedReq    = 3,
10845ffb0c9bSToomas Soome     PCPResult_UnsuppOpcode    = 4,
10855ffb0c9bSToomas Soome     PCPResult_UnsuppOption    = 5,
10865ffb0c9bSToomas Soome     PCPResult_MalformedOption = 6,
10875ffb0c9bSToomas Soome     PCPResult_NetworkFailure  = 7,
10885ffb0c9bSToomas Soome     PCPResult_NoResources     = 8,
10895ffb0c9bSToomas Soome     PCPResult_UnsuppProtocol  = 9,
10905ffb0c9bSToomas Soome     PCPResult_UserExQuota     = 10,
10915ffb0c9bSToomas Soome     PCPResult_CantProvideExt  = 11,
10925ffb0c9bSToomas Soome     PCPResult_AddrMismatch    = 12,
10935ffb0c9bSToomas Soome     PCPResult_ExcesRemotePeer = 13
10945ffb0c9bSToomas Soome } PCPResult_t;
10954b22b933Srs 
1096c65ebfc7SToomas Soome typedef struct
10975ffb0c9bSToomas Soome {
10985ffb0c9bSToomas Soome     mDNSu8       version;
10995ffb0c9bSToomas Soome     mDNSu8       opCode;
11005ffb0c9bSToomas Soome     mDNSOpaque16 reserved;
11015ffb0c9bSToomas Soome     mDNSu32      lifetime;
11025ffb0c9bSToomas Soome     mDNSv6Addr   clientAddr;
11035ffb0c9bSToomas Soome     mDNSu32      nonce[3];
11045ffb0c9bSToomas Soome     mDNSu8       protocol;
11055ffb0c9bSToomas Soome     mDNSu8       reservedMapOp[3];
11065ffb0c9bSToomas Soome     mDNSIPPort   intPort;
11075ffb0c9bSToomas Soome     mDNSIPPort   extPort;
11085ffb0c9bSToomas Soome     mDNSv6Addr   extAddress;
11095ffb0c9bSToomas Soome } PCPMapRequest;
11104b22b933Srs 
1111c65ebfc7SToomas Soome typedef struct
11125ffb0c9bSToomas Soome {
11135ffb0c9bSToomas Soome     mDNSu8     version;
11145ffb0c9bSToomas Soome     mDNSu8     opCode;
11155ffb0c9bSToomas Soome     mDNSu8     reserved;
11165ffb0c9bSToomas Soome     mDNSu8     result;
11175ffb0c9bSToomas Soome     mDNSu32    lifetime;
11185ffb0c9bSToomas Soome     mDNSu32    epoch;
11195ffb0c9bSToomas Soome     mDNSu32    clientAddrParts[3];
11205ffb0c9bSToomas Soome     mDNSu32    nonce[3];
11215ffb0c9bSToomas Soome     mDNSu8     protocol;
11225ffb0c9bSToomas Soome     mDNSu8     reservedMapOp[3];
11235ffb0c9bSToomas Soome     mDNSIPPort intPort;
11245ffb0c9bSToomas Soome     mDNSIPPort extPort;
11255ffb0c9bSToomas Soome     mDNSv6Addr extAddress;
11265ffb0c9bSToomas Soome } PCPMapReply;
11275ffb0c9bSToomas Soome 
11285ffb0c9bSToomas Soome // LNT Support
11294b22b933Srs 
11305ffb0c9bSToomas Soome typedef enum
11315ffb0c9bSToomas Soome {
11325ffb0c9bSToomas Soome     LNTDiscoveryOp      = 1,
11335ffb0c9bSToomas Soome     LNTExternalAddrOp   = 2,
11345ffb0c9bSToomas Soome     LNTPortMapOp        = 3,
11355ffb0c9bSToomas Soome     LNTPortMapDeleteOp  = 4
11365ffb0c9bSToomas Soome } LNTOp_t;
11375ffb0c9bSToomas Soome 
11385ffb0c9bSToomas Soome #define LNT_MAXBUFSIZE 8192
11395ffb0c9bSToomas Soome typedef struct tcpLNTInfo_struct tcpLNTInfo;
11405ffb0c9bSToomas Soome struct tcpLNTInfo_struct
11415ffb0c9bSToomas Soome {
11425ffb0c9bSToomas Soome     tcpLNTInfo       *next;
11435ffb0c9bSToomas Soome     mDNS             *m;
11445ffb0c9bSToomas Soome     NATTraversalInfo *parentNATInfo;    // pointer back to the parent NATTraversalInfo
11455ffb0c9bSToomas Soome     TCPSocket        *sock;
11465ffb0c9bSToomas Soome     LNTOp_t op;                         // operation performed using this connection
11475ffb0c9bSToomas Soome     mDNSAddr Address;                   // router address
11485ffb0c9bSToomas Soome     mDNSIPPort Port;                    // router port
11495ffb0c9bSToomas Soome     mDNSu8           *Request;          // xml request to router
11505ffb0c9bSToomas Soome     int requestLen;
11515ffb0c9bSToomas Soome     mDNSu8           *Reply;            // xml reply from router
11525ffb0c9bSToomas Soome     int replyLen;
11535ffb0c9bSToomas Soome     unsigned long nread;                // number of bytes read so far
11545ffb0c9bSToomas Soome     int retries;                        // number of times we've tried to do this port mapping
11555ffb0c9bSToomas Soome };
11565ffb0c9bSToomas Soome 
11575ffb0c9bSToomas Soome typedef void (*NATTraversalClientCallback)(mDNS *m, NATTraversalInfo *n);
11585ffb0c9bSToomas Soome 
11595ffb0c9bSToomas Soome // if m->timenow <  ExpiryTime then we have an active mapping, and we'll renew halfway to expiry
11605ffb0c9bSToomas Soome // if m->timenow >= ExpiryTime then our mapping has expired, and we're trying to create one
11614b22b933Srs 
11625ffb0c9bSToomas Soome typedef enum
11635ffb0c9bSToomas Soome {
11645ffb0c9bSToomas Soome     NATTProtocolNone    = 0,
11655ffb0c9bSToomas Soome     NATTProtocolNATPMP  = 1,
11665ffb0c9bSToomas Soome     NATTProtocolUPNPIGD = 2,
11675ffb0c9bSToomas Soome     NATTProtocolPCP     = 3,
11685ffb0c9bSToomas Soome } NATTProtocol;
11695ffb0c9bSToomas Soome 
11705ffb0c9bSToomas Soome struct NATTraversalInfo_struct
11715ffb0c9bSToomas Soome {
11725ffb0c9bSToomas Soome     // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
11735ffb0c9bSToomas Soome     NATTraversalInfo           *next;
11745ffb0c9bSToomas Soome 
11755ffb0c9bSToomas Soome     mDNSs32 ExpiryTime;                             // Time this mapping expires, or zero if no mapping
11765ffb0c9bSToomas Soome     mDNSs32 retryInterval;                          // Current interval, between last packet we sent and the next one
11775ffb0c9bSToomas Soome     mDNSs32 retryPortMap;                           // If Protocol is nonzero, time to send our next mapping packet
11785ffb0c9bSToomas Soome     mStatus NewResult;                              // New error code; will be copied to Result just prior to invoking callback
11795ffb0c9bSToomas Soome     NATTProtocol lastSuccessfulProtocol;            // To send correct deletion request & update non-PCP external address operations
11805ffb0c9bSToomas Soome     mDNSBool sentNATPMP;                            // Whether we just sent a NAT-PMP packet, so we won't send another if
11815ffb0c9bSToomas Soome                                                     //    we receive another NAT-PMP "Unsupported Version" packet
11824b22b933Srs 
11835ffb0c9bSToomas Soome #ifdef _LEGACY_NAT_TRAVERSAL_
11845ffb0c9bSToomas Soome     tcpLNTInfo tcpInfo;                             // Legacy NAT traversal (UPnP) TCP connection
11855ffb0c9bSToomas Soome #endif
11864b22b933Srs 
11875ffb0c9bSToomas Soome     // Result fields: When the callback is invoked these fields contain the answers the client is looking for
11885ffb0c9bSToomas Soome     // When the callback is invoked ExternalPort is *usually* set to be the same the same as RequestedPort, except:
11895ffb0c9bSToomas Soome     // (a) When we're behind a NAT gateway with port mapping disabled, ExternalPort is reported as zero to
11905ffb0c9bSToomas Soome     //     indicate that we don't currently have a working mapping (but RequestedPort retains the external port
11915ffb0c9bSToomas Soome     //     we'd like to get, the next time we meet an accomodating NAT gateway willing to give us one).
11925ffb0c9bSToomas Soome     // (b) When we have a routable non-RFC1918 address, we don't *need* a port mapping, so ExternalPort
11935ffb0c9bSToomas Soome     //     is reported as the same as our InternalPort, since that is effectively our externally-visible port too.
11945ffb0c9bSToomas Soome     //     Again, RequestedPort retains the external port we'd like to get the next time we find ourself behind a NAT gateway.
11955ffb0c9bSToomas Soome     // To improve stability of port mappings, RequestedPort is updated any time we get a successful
11965ffb0c9bSToomas Soome     // mapping response from the PCP, NAT-PMP or UPnP gateway. For example, if we ask for port 80, and
11975ffb0c9bSToomas Soome     // get assigned port 81, then thereafter we'll contine asking for port 81.
11985ffb0c9bSToomas Soome     mDNSInterfaceID InterfaceID;
11995ffb0c9bSToomas Soome     mDNSv4Addr ExternalAddress;                     // Initially set to onesIPv4Addr, until first callback
12005ffb0c9bSToomas Soome     mDNSv4Addr NewAddress;                          // May be updated with actual value assigned by gateway
12015ffb0c9bSToomas Soome     mDNSIPPort ExternalPort;
12025ffb0c9bSToomas Soome     mDNSu32 Lifetime;
12035ffb0c9bSToomas Soome     mStatus Result;
12045ffb0c9bSToomas Soome 
12055ffb0c9bSToomas Soome     // Client API fields: The client must set up these fields *before* making any NAT traversal API calls
12065ffb0c9bSToomas Soome     mDNSu8 Protocol;                                // NATOp_MapUDP or NATOp_MapTCP, or zero if just requesting the external IP address
12075ffb0c9bSToomas Soome     mDNSIPPort IntPort;                             // Client's internal port number (doesn't change)
12085ffb0c9bSToomas Soome     mDNSIPPort RequestedPort;                       // Requested external port; may be updated with actual value assigned by gateway
12095ffb0c9bSToomas Soome     mDNSu32 NATLease;                               // Requested lifetime in seconds (doesn't change)
12105ffb0c9bSToomas Soome     NATTraversalClientCallback clientCallback;
12115ffb0c9bSToomas Soome     void                       *clientContext;
12125ffb0c9bSToomas Soome };
12134b22b933Srs 
12145ffb0c9bSToomas Soome // ***************************************************************************
12155ffb0c9bSToomas Soome #if 0
12165ffb0c9bSToomas Soome #pragma mark -
12175ffb0c9bSToomas Soome #pragma mark - DNSServer & McastResolver structures and constants
12185ffb0c9bSToomas Soome #endif
12194b22b933Srs 
12205ffb0c9bSToomas Soome enum
12215ffb0c9bSToomas Soome {
12225ffb0c9bSToomas Soome     McastResolver_FlagDelete = 1,
12235ffb0c9bSToomas Soome     McastResolver_FlagNew    = 2
12245ffb0c9bSToomas Soome };
12255ffb0c9bSToomas Soome 
12265ffb0c9bSToomas Soome typedef struct McastResolver
12275ffb0c9bSToomas Soome {
12285ffb0c9bSToomas Soome     struct McastResolver *next;
12295ffb0c9bSToomas Soome     mDNSInterfaceID interface;
12305ffb0c9bSToomas Soome     mDNSu32 flags;              // Set when we're planning to delete this from the list
12315ffb0c9bSToomas Soome     domainname domain;
12325ffb0c9bSToomas Soome     mDNSu32 timeout;            // timeout value for questions
12335ffb0c9bSToomas Soome } McastResolver;
12345ffb0c9bSToomas Soome 
12353b436d06SToomas Soome enum {
12363b436d06SToomas Soome     Mortality_Mortal      = 0,          // This cache record can expire and get purged
12373b436d06SToomas Soome     Mortality_Immortal    = 1,          // Allow this record to remain in the cache indefinitely
12383b436d06SToomas Soome     Mortality_Ghost       = 2           // An immortal record that has expired and can linger in the cache
12393b436d06SToomas Soome };
12403b436d06SToomas Soome typedef mDNSu8 MortalityState;
12413b436d06SToomas Soome 
1242*472cd20dSToomas Soome // ScopeType values for DNSServer matching
1243*472cd20dSToomas Soome typedef enum
12445ffb0c9bSToomas Soome {
12455ffb0c9bSToomas Soome     kScopeNone         = 0,        // DNS server used by unscoped questions
12465ffb0c9bSToomas Soome     kScopeInterfaceID  = 1,        // Scoped DNS server used only by scoped questions
1247*472cd20dSToomas Soome     kScopeServiceID    = 2         // Service specific DNS server used only by questions
12485ffb0c9bSToomas Soome                                    // have a matching serviceID
1249*472cd20dSToomas Soome } ScopeType;
1250*472cd20dSToomas Soome 
1251*472cd20dSToomas Soome #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
1252*472cd20dSToomas Soome typedef mDNSu32 DNSServerFlags;
1253*472cd20dSToomas Soome #define DNSServerFlag_Delete        (1U << 0)
1254*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, SYMPTOMS)
1255*472cd20dSToomas Soome #define DNSServerFlag_Unreachable   (1U << 1)
1256*472cd20dSToomas Soome #endif
12575ffb0c9bSToomas Soome 
12585ffb0c9bSToomas Soome typedef struct DNSServer
12595ffb0c9bSToomas Soome {
12605ffb0c9bSToomas Soome     struct DNSServer *next;
12615ffb0c9bSToomas Soome     mDNSInterfaceID interface;  // DNS requests should be sent on this interface
1262*472cd20dSToomas Soome     mDNSs32 serviceID;          // ServiceID from DNS configuration.
1263*472cd20dSToomas Soome     mDNSAddr addr;              // DNS server's IP address.
1264*472cd20dSToomas Soome     DNSServerFlags flags;       // Set when we're planning to delete this from the list.
12655ffb0c9bSToomas Soome     mDNSs32 penaltyTime;        // amount of time this server is penalized
1266*472cd20dSToomas Soome     ScopeType scopeType;        // See the ScopeType enum above
12675ffb0c9bSToomas Soome     mDNSu32 timeout;            // timeout value for questions
1268*472cd20dSToomas Soome     mDNSu32 resGroupID;         // ID of the resolver group that contains this DNSServer
1269*472cd20dSToomas Soome     mDNSIPPort port;            // DNS server's port number.
1270*472cd20dSToomas Soome     mDNSBool usableA;           // True if A query results are usable over the interface, i.e., interface has IPv4.
1271*472cd20dSToomas Soome     mDNSBool usableAAAA;        // True if AAAA query results are usable over the interface, i.e., interface has IPv6.
1272*472cd20dSToomas Soome     mDNSBool isCell;            // True if the interface to this server is cellular.
1273c65ebfc7SToomas Soome     mDNSBool isExpensive;       // True if the interface to this server is expensive.
1274*472cd20dSToomas Soome     mDNSBool isConstrained;     // True if the interface to this server is constrained.
1275*472cd20dSToomas Soome     mDNSBool isCLAT46;          // True if the interface to this server supports CLAT46.
1276*472cd20dSToomas Soome     domainname domain;          // name->server matching for "split dns"
12775ffb0c9bSToomas Soome } DNSServer;
1278*472cd20dSToomas Soome #endif
12794b22b933Srs 
1280*472cd20dSToomas Soome #define kNegativeRecordType_Unspecified 0 // Initializer of ResourceRecord didn't specify why the record is negative.
1281*472cd20dSToomas Soome #define kNegativeRecordType_NoData      1 // The record's name exists, but there are no records of this type.
12825ffb0c9bSToomas Soome 
12835ffb0c9bSToomas Soome struct ResourceRecord_struct
12845ffb0c9bSToomas Soome {
1285c65ebfc7SToomas Soome     mDNSu8 RecordType;                  // See kDNSRecordTypes enum.
1286*472cd20dSToomas Soome     mDNSu8 negativeRecordType;          // If RecordType is kDNSRecordTypePacketNegative, specifies type of negative record.
12873b436d06SToomas Soome     MortalityState mortality;           // Mortality of this resource record (See MortalityState enum)
1288c65ebfc7SToomas Soome     mDNSu16 rrtype;                     // See DNS_TypeValues enum.
1289c65ebfc7SToomas Soome     mDNSu16 rrclass;                    // See DNS_ClassValues enum.
12905ffb0c9bSToomas Soome     mDNSu32 rroriginalttl;              // In seconds
12915ffb0c9bSToomas Soome     mDNSu16 rdlength;                   // Size of the raw rdata, in bytes, in the on-the-wire format
12925ffb0c9bSToomas Soome                                         // (In-memory storage may be larger, for structures containing 'holes', like SOA)
12935ffb0c9bSToomas Soome     mDNSu16 rdestimate;                 // Upper bound on on-the-wire size of rdata after name compression
12945ffb0c9bSToomas Soome     mDNSu32 namehash;                   // Name-based (i.e. case-insensitive) hash of name
12955ffb0c9bSToomas Soome     mDNSu32 rdatahash;                  // For rdata containing domain name (e.g. PTR, SRV, CNAME etc.), case-insensitive name hash
12965ffb0c9bSToomas Soome                                         // else, for all other rdata, 32-bit hash of the raw rdata
12975ffb0c9bSToomas Soome                                         // Note: This requirement is important. Various routines like AddAdditionalsToResponseList(),
12985ffb0c9bSToomas Soome                                         // ReconfirmAntecedents(), etc., use rdatahash as a pre-flight check to see
12995ffb0c9bSToomas Soome                                         // whether it's worth doing a full SameDomainName() call. If the rdatahash
13005ffb0c9bSToomas Soome                                         // is not a correct case-insensitive name hash, they'll get false negatives.
13015ffb0c9bSToomas Soome     // Grouping pointers together at the end of the structure improves the memory layout efficiency
13025ffb0c9bSToomas Soome     mDNSInterfaceID InterfaceID;        // Set if this RR is specific to one interface
13035ffb0c9bSToomas Soome                                         // For records received off the wire, InterfaceID is *always* set to the receiving interface
13045ffb0c9bSToomas Soome                                         // For our authoritative records, InterfaceID is usually zero, except for those few records
13055ffb0c9bSToomas Soome                                         // that are interface-specific (e.g. address records, especially linklocal addresses)
13065ffb0c9bSToomas Soome     const domainname *name;
13075ffb0c9bSToomas Soome     RData           *rdata;             // Pointer to storage for this rdata
1308*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
1309*472cd20dSToomas Soome 	mdns_dns_service_t dnsservice;
1310*472cd20dSToomas Soome 	mdns_resolver_type_t protocol;
1311*472cd20dSToomas Soome #else
1312cda73f64SToomas Soome     DNSServer       *rDNSServer;        // Unicast DNS server authoritative for this entry; null for multicast
1313*472cd20dSToomas Soome #endif
1314*472cd20dSToomas Soome 
1315*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
1316*472cd20dSToomas Soome     dnssec_result_t dnssec_result;      // DNSSEC validation result of the current resource record.
1317*472cd20dSToomas Soome                                         // For all DNSSEC-disabled queries, the result would always be dnssec_indeterminate.
1318*472cd20dSToomas Soome                                         // For DNSSEC-enabled queries, the result would be dnssec_indeterminate,
1319*472cd20dSToomas Soome                                         // dnssec_secure, dnssec_insecure, or dnssec_bogus, see
1320*472cd20dSToomas Soome                                         // <https://tools.ietf.org/html/rfc4033#section-5> for the detailed meaning of
1321*472cd20dSToomas Soome                                         // each state.
1322*472cd20dSToomas Soome #endif
13235ffb0c9bSToomas Soome };
13245ffb0c9bSToomas Soome 
13255ffb0c9bSToomas Soome 
13265ffb0c9bSToomas Soome // Unless otherwise noted, states may apply to either independent record registrations or service registrations
13274b22b933Srs typedef enum
13285ffb0c9bSToomas Soome {
13295ffb0c9bSToomas Soome     regState_Zero              = 0,
13305ffb0c9bSToomas Soome     regState_Pending           = 1,     // update sent, reply not received
13315ffb0c9bSToomas Soome     regState_Registered        = 2,     // update sent, reply received
13325ffb0c9bSToomas Soome     regState_DeregPending      = 3,     // dereg sent, reply not received
13335ffb0c9bSToomas Soome     regState_Unregistered      = 4,     // not in any list
13345ffb0c9bSToomas Soome     regState_Refresh           = 5,     // outstanding refresh (or target change) message
13355ffb0c9bSToomas Soome     regState_NATMap            = 6,     // establishing NAT port mapping
13365ffb0c9bSToomas Soome     regState_UpdatePending     = 7,     // update in flight as result of mDNS_Update call
13375ffb0c9bSToomas Soome     regState_NoTarget          = 8,     // SRV Record registration pending registration of hostname
13385ffb0c9bSToomas Soome     regState_NATError          = 9     // unable to complete NAT traversal
13395ffb0c9bSToomas Soome } regState_t;
13404b22b933Srs 
13415ffb0c9bSToomas Soome enum
13425ffb0c9bSToomas Soome {
13435ffb0c9bSToomas Soome     Target_Manual = 0,
13445ffb0c9bSToomas Soome     Target_AutoHost = 1,
13455ffb0c9bSToomas Soome     Target_AutoHostAndNATMAP = 2
13465ffb0c9bSToomas Soome };
13475ffb0c9bSToomas Soome 
13485ffb0c9bSToomas Soome typedef enum
13495ffb0c9bSToomas Soome {
13505ffb0c9bSToomas Soome     mergeState_Zero = 0,
13515ffb0c9bSToomas Soome     mergeState_DontMerge = 1  // Set on fatal error conditions to disable merging
13525ffb0c9bSToomas Soome } mergeState_t;
13535ffb0c9bSToomas Soome 
13545ffb0c9bSToomas Soome #define AUTH_GROUP_NAME_SIZE    128
13555ffb0c9bSToomas Soome struct AuthGroup_struct             // Header object for a list of AuthRecords with the same name
13565ffb0c9bSToomas Soome {
13575ffb0c9bSToomas Soome     AuthGroup      *next;               // Next AuthGroup object in this hash table bucket
13585ffb0c9bSToomas Soome     mDNSu32 namehash;                   // Name-based (i.e. case insensitive) hash of name
13595ffb0c9bSToomas Soome     AuthRecord     *members;            // List of CacheRecords with this same name
13605ffb0c9bSToomas Soome     AuthRecord    **rrauth_tail;        // Tail end of that list
13615ffb0c9bSToomas Soome     domainname     *name;               // Common name for all AuthRecords in this list
13625ffb0c9bSToomas Soome     AuthRecord     *NewLocalOnlyRecords;
13635ffb0c9bSToomas Soome     mDNSu8 namestorage[AUTH_GROUP_NAME_SIZE];
13645ffb0c9bSToomas Soome };
13655ffb0c9bSToomas Soome 
13665ffb0c9bSToomas Soome #ifndef AUTH_HASH_SLOTS
13675ffb0c9bSToomas Soome #define AUTH_HASH_SLOTS 499
13685ffb0c9bSToomas Soome #endif
13695ffb0c9bSToomas Soome #define FORALL_AUTHRECORDS(SLOT,AG,AR)                              \
13705ffb0c9bSToomas Soome     for ((SLOT) = 0; (SLOT) < AUTH_HASH_SLOTS; (SLOT)++)                                                                     \
13715ffb0c9bSToomas Soome         for ((AG)=m->rrauth.rrauth_hash[(SLOT)]; (AG); (AG)=(AG)->next)                                                                         \
13725ffb0c9bSToomas Soome             for ((AR) = (AG)->members; (AR); (AR)=(AR)->next)
13735ffb0c9bSToomas Soome 
13745ffb0c9bSToomas Soome typedef union AuthEntity_union AuthEntity;
13755ffb0c9bSToomas Soome union AuthEntity_union { AuthEntity *next; AuthGroup ag; };
13765ffb0c9bSToomas Soome typedef struct {
13775ffb0c9bSToomas Soome     mDNSu32 rrauth_size;                // Total number of available auth entries
13785ffb0c9bSToomas Soome     mDNSu32 rrauth_totalused;           // Number of auth entries currently occupied
13795ffb0c9bSToomas Soome     mDNSu32 rrauth_report;
13805ffb0c9bSToomas Soome     mDNSu8 rrauth_lock;                 // For debugging: Set at times when these lists may not be modified
13815ffb0c9bSToomas Soome     AuthEntity *rrauth_free;
13825ffb0c9bSToomas Soome     AuthGroup *rrauth_hash[AUTH_HASH_SLOTS];
13835ffb0c9bSToomas Soome }AuthHash;
13845ffb0c9bSToomas Soome 
13855ffb0c9bSToomas Soome // AuthRecordAny includes mDNSInterface_Any and interface specific auth records.
13865ffb0c9bSToomas Soome typedef enum
13875ffb0c9bSToomas Soome {
13885ffb0c9bSToomas Soome     AuthRecordAny,              // registered for *Any, NOT including P2P interfaces
13895ffb0c9bSToomas Soome     AuthRecordAnyIncludeP2P,    // registered for *Any, including P2P interfaces
13905ffb0c9bSToomas Soome     AuthRecordAnyIncludeAWDL,   // registered for *Any, including AWDL interface
13915ffb0c9bSToomas Soome     AuthRecordAnyIncludeAWDLandP2P, // registered for *Any, including AWDL and P2P interfaces
13925ffb0c9bSToomas Soome     AuthRecordLocalOnly,
1393*472cd20dSToomas Soome     AuthRecordP2P,              // discovered over D2D/P2P framework
13945ffb0c9bSToomas Soome } AuthRecType;
13955ffb0c9bSToomas Soome 
1396*472cd20dSToomas Soome #define AuthRecordIncludesAWDL(AR) \
1397*472cd20dSToomas Soome     (((AR)->ARType == AuthRecordAnyIncludeAWDL) || ((AR)->ARType == AuthRecordAnyIncludeAWDLandP2P))
1398*472cd20dSToomas Soome 
13995ffb0c9bSToomas Soome typedef enum
14005ffb0c9bSToomas Soome {
14015ffb0c9bSToomas Soome     AuthFlagsWakeOnly = 0x1     // WakeOnly service
14025ffb0c9bSToomas Soome } AuthRecordFlags;
14034b22b933Srs 
14044b22b933Srs struct AuthRecord_struct
14055ffb0c9bSToomas Soome {
14065ffb0c9bSToomas Soome     // For examples of how to set up this structure for use in mDNS_Register(),
14075ffb0c9bSToomas Soome     // see mDNS_AdvertiseInterface() or mDNS_RegisterService().
14085ffb0c9bSToomas Soome     // Basically, resrec and persistent metadata need to be set up before calling mDNS_Register().
14095ffb0c9bSToomas Soome     // mDNS_SetupResourceRecord() is avaliable as a helper routine to set up most fields to sensible default values for you
14105ffb0c9bSToomas Soome 
14115ffb0c9bSToomas Soome     AuthRecord     *next;               // Next in list; first element of structure for efficiency reasons
14125ffb0c9bSToomas Soome     // Field Group 1: Common ResourceRecord fields
1413cda73f64SToomas Soome     ResourceRecord resrec;              // 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit (now 44/64)
14145ffb0c9bSToomas Soome 
14155ffb0c9bSToomas Soome     // Field Group 2: Persistent metadata for Authoritative Records
14165ffb0c9bSToomas Soome     AuthRecord     *Additional1;        // Recommended additional record to include in response (e.g. SRV for PTR record)
14175ffb0c9bSToomas Soome     AuthRecord     *Additional2;        // Another additional (e.g. TXT for PTR record)
14185ffb0c9bSToomas Soome     AuthRecord     *DependentOn;        // This record depends on another for its uniqueness checking
14195ffb0c9bSToomas Soome     AuthRecord     *RRSet;              // This unique record is part of an RRSet
14205ffb0c9bSToomas Soome     mDNSRecordCallback *RecordCallback; // Callback function to call for state changes, and to free memory asynchronously on deregistration
14215ffb0c9bSToomas Soome     void           *RecordContext;      // Context parameter for the callback function
14225ffb0c9bSToomas Soome     mDNSu8 AutoTarget;                  // Set if the target of this record (PTR, CNAME, SRV, etc.) is our host name
14235ffb0c9bSToomas Soome     mDNSu8 AllowRemoteQuery;            // Set if we allow hosts not on the local link to query this record
14245ffb0c9bSToomas Soome     mDNSu8 ForceMCast;                  // Set by client to advertise solely via multicast, even for apparently unicast names
14255ffb0c9bSToomas Soome     mDNSu8 AuthFlags;
14265ffb0c9bSToomas Soome 
14275ffb0c9bSToomas Soome     OwnerOptData WakeUp;                // WakeUp.HMAC.l[0] nonzero indicates that this is a Sleep Proxy record
14285ffb0c9bSToomas Soome     mDNSAddr AddressProxy;              // For reverse-mapping Sleep Proxy PTR records, address in question
14295ffb0c9bSToomas Soome     mDNSs32 TimeRcvd;                   // In platform time units
14305ffb0c9bSToomas Soome     mDNSs32 TimeExpire;                 // In platform time units
14315ffb0c9bSToomas Soome     AuthRecType ARType;                 // LocalOnly, P2P or Normal ?
14325ffb0c9bSToomas Soome     mDNSs32 KATimeExpire;               // In platform time units: time to send keepalive packet for the proxy record
14335ffb0c9bSToomas Soome 
14345ffb0c9bSToomas Soome     // Field Group 3: Transient state for Authoritative Records
1435*472cd20dSToomas Soome     mDNSs32 ProbingConflictCount;       // Number of conflicting records observed during probing.
1436*472cd20dSToomas Soome     mDNSs32 LastConflictPktNum;         // Number of the last received packet that caused a probing conflict.
14375ffb0c9bSToomas Soome     mDNSu8 Acknowledged;                // Set if we've given the success callback to the client
14385ffb0c9bSToomas Soome     mDNSu8 ProbeRestartCount;           // Number of times we have restarted probing
14395ffb0c9bSToomas Soome     mDNSu8 ProbeCount;                  // Number of probes remaining before this record is valid (kDNSRecordTypeUnique)
14405ffb0c9bSToomas Soome     mDNSu8 AnnounceCount;               // Number of announcements remaining (kDNSRecordTypeShared)
14415ffb0c9bSToomas Soome     mDNSu8 RequireGoodbye;              // Set if this RR has been announced on the wire and will require a goodbye packet
14425ffb0c9bSToomas Soome     mDNSu8 AnsweredLocalQ;              // Set if this AuthRecord has been delivered to any local question (LocalOnly or mDNSInterface_Any)
14435ffb0c9bSToomas Soome     mDNSu8 IncludeInProbe;              // Set if this RR is being put into a probe right now
14445ffb0c9bSToomas Soome     mDNSu8 ImmedUnicast;                // Set if we may send our response directly via unicast to the requester
14455ffb0c9bSToomas Soome     mDNSInterfaceID SendNSECNow;        // Set if we need to generate associated NSEC data for this rrname
14465ffb0c9bSToomas Soome     mDNSInterfaceID ImmedAnswer;        // Someone on this interface issued a query we need to answer (all-ones for all interfaces)
14474b22b933Srs #if MDNS_LOG_ANSWER_SUPPRESSION_TIMES
14485ffb0c9bSToomas Soome     mDNSs32 ImmedAnswerMarkTime;
14494b22b933Srs #endif
14505ffb0c9bSToomas Soome     mDNSInterfaceID ImmedAdditional;    // Hint that we might want to also send this record, just to be helpful
14515ffb0c9bSToomas Soome     mDNSInterfaceID SendRNow;           // The interface this query is being sent on right now
14525ffb0c9bSToomas Soome     mDNSv4Addr v4Requester;             // Recent v4 query for this record, or all-ones if more than one recent query
14535ffb0c9bSToomas Soome     mDNSv6Addr v6Requester;             // Recent v6 query for this record, or all-ones if more than one recent query
14545ffb0c9bSToomas Soome     AuthRecord     *NextResponse;       // Link to the next element in the chain of responses to generate
14555ffb0c9bSToomas Soome     const mDNSu8   *NR_AnswerTo;        // Set if this record was selected by virtue of being a direct answer to a question
14565ffb0c9bSToomas Soome     AuthRecord     *NR_AdditionalTo;    // Set if this record was selected by virtue of being additional to another
14575ffb0c9bSToomas Soome     mDNSs32 ThisAPInterval;             // In platform time units: Current interval for announce/probe
14585ffb0c9bSToomas Soome     mDNSs32 LastAPTime;                 // In platform time units: Last time we sent announcement/probe
14595ffb0c9bSToomas Soome     mDNSs32 LastMCTime;                 // Last time we multicast this record (used to guard against packet-storm attacks)
14605ffb0c9bSToomas Soome     mDNSInterfaceID LastMCInterface;    // Interface this record was multicast on at the time LastMCTime was recorded
14615ffb0c9bSToomas Soome     RData          *NewRData;           // Set if we are updating this record with new rdata
14625ffb0c9bSToomas Soome     mDNSu16 newrdlength;                // ... and the length of the new RData
14635ffb0c9bSToomas Soome     mDNSRecordUpdateCallback *UpdateCallback;
14645ffb0c9bSToomas Soome     mDNSu32 UpdateCredits;              // Token-bucket rate limiting of excessive updates
14655ffb0c9bSToomas Soome     mDNSs32 NextUpdateCredit;           // Time next token is added to bucket
14665ffb0c9bSToomas Soome     mDNSs32 UpdateBlocked;              // Set if update delaying is in effect
14675ffb0c9bSToomas Soome 
14685ffb0c9bSToomas Soome     // Field Group 4: Transient uDNS state for Authoritative Records
14695ffb0c9bSToomas Soome     regState_t state;           // Maybe combine this with resrec.RecordType state? Right now it's ambiguous and confusing.
14705ffb0c9bSToomas Soome                                 // e.g. rr->resrec.RecordType can be kDNSRecordTypeUnregistered,
14715ffb0c9bSToomas Soome                                 // and rr->state can be regState_Unregistered
14725ffb0c9bSToomas Soome                                 // What if we find one of those statements is true and the other false? What does that mean?
14735ffb0c9bSToomas Soome     mDNSBool uselease;          // dynamic update contains (should contain) lease option
14745ffb0c9bSToomas Soome     mDNSs32 expire;             // In platform time units: expiration of lease (-1 for static)
14755ffb0c9bSToomas Soome     mDNSBool Private;           // If zone is private, DNS updates may have to be encrypted to prevent eavesdropping
14765ffb0c9bSToomas Soome     mDNSOpaque16 updateid;      // Identifier to match update request and response -- also used when transferring records to Sleep Proxy
14775ffb0c9bSToomas Soome     mDNSOpaque64 updateIntID;   // Interface IDs (one bit per interface index)to which updates have been sent
14785ffb0c9bSToomas Soome     const domainname *zone;     // the zone that is updated
14795ffb0c9bSToomas Soome     ZoneData  *nta;
14805ffb0c9bSToomas Soome     struct tcpInfo_t *tcp;
14815ffb0c9bSToomas Soome     NATTraversalInfo NATinfo;
14825ffb0c9bSToomas Soome     mDNSBool SRVChanged;       // temporarily deregistered service because its SRV target or port changed
14835ffb0c9bSToomas Soome     mergeState_t mState;       // Unicast Record Registrations merge state
14845ffb0c9bSToomas Soome     mDNSu8 refreshCount;        // Number of refreshes to the server
14855ffb0c9bSToomas Soome     mStatus updateError;        // Record update resulted in Error ?
14865ffb0c9bSToomas Soome 
14875ffb0c9bSToomas Soome     // uDNS_UpdateRecord support fields
14885ffb0c9bSToomas Soome     // Do we really need all these in *addition* to NewRData and newrdlength above?
14895ffb0c9bSToomas Soome     void *UpdateContext;    // Context parameter for the update callback function
14905ffb0c9bSToomas Soome     mDNSu16 OrigRDLen;      // previously registered, being deleted
14915ffb0c9bSToomas Soome     mDNSu16 InFlightRDLen;  // currently being registered
14925ffb0c9bSToomas Soome     mDNSu16 QueuedRDLen;    // pending operation (re-transmitting if necessary) THEN register the queued update
14935ffb0c9bSToomas Soome     RData *OrigRData;
14945ffb0c9bSToomas Soome     RData *InFlightRData;
14955ffb0c9bSToomas Soome     RData *QueuedRData;
14965ffb0c9bSToomas Soome 
14975ffb0c9bSToomas Soome     // Field Group 5: Large data objects go at the end
14985ffb0c9bSToomas Soome     domainname namestorage;
14995ffb0c9bSToomas Soome     RData rdatastorage;                 // Normally the storage is right here, except for oversized records
15005ffb0c9bSToomas Soome     // rdatastorage MUST be the last thing in the structure -- when using oversized AuthRecords, extra bytes
15015ffb0c9bSToomas Soome     // are appended after the end of the AuthRecord, logically augmenting the size of the rdatastorage
15025ffb0c9bSToomas Soome     // DO NOT ADD ANY MORE FIELDS HERE
15035ffb0c9bSToomas Soome };
15045ffb0c9bSToomas Soome 
15055ffb0c9bSToomas Soome // IsLocalDomain alone is not sufficient to determine that a record is mDNS or uDNS. By default domain names within
15065ffb0c9bSToomas Soome // the "local" pseudo-TLD (and within the IPv4 and IPv6 link-local reverse mapping domains) are automatically treated
15075ffb0c9bSToomas Soome // as mDNS records, but it is also possible to force any record (even those not within one of the inherently local
15085ffb0c9bSToomas Soome // domains) to be handled as an mDNS record by setting the ForceMCast flag, or by setting a non-zero InterfaceID.
15095ffb0c9bSToomas Soome // For example, the reverse-mapping PTR record created in AdvertiseInterface sets the ForceMCast flag, since it points to
15105ffb0c9bSToomas Soome // a dot-local hostname, and therefore it would make no sense to register this record with a wide-area Unicast DNS server.
15115ffb0c9bSToomas Soome // The same applies to Sleep Proxy records, which we will answer for when queried via mDNS, but we never want to try
15125ffb0c9bSToomas Soome // to register them with a wide-area Unicast DNS server -- and we probably don't have the required credentials anyway.
15135ffb0c9bSToomas Soome // Currently we have no concept of a wide-area uDNS record scoped to a particular interface, so if the InterfaceID is
15145ffb0c9bSToomas Soome // nonzero we treat this the same as ForceMCast.
15155ffb0c9bSToomas Soome // Note: Question_uDNS(Q) is used in *only* one place -- on entry to mDNS_StartQuery_internal, to decide whether to set TargetQID.
15165ffb0c9bSToomas Soome // Everywhere else in the code, the determination of whether a question is unicast is made by checking to see if TargetQID is nonzero.
15175ffb0c9bSToomas Soome #define AuthRecord_uDNS(R) ((R)->resrec.InterfaceID == mDNSInterface_Any && !(R)->ForceMCast && !IsLocalDomain((R)->resrec.name))
1518*472cd20dSToomas Soome #define Question_uDNS(Q)   ((Q)->IsUnicastDotLocal || (Q)->ProxyQuestion || \
1519c65ebfc7SToomas Soome                             ((Q)->InterfaceID != mDNSInterface_LocalOnly && (Q)->InterfaceID != mDNSInterface_P2P && (Q)->InterfaceID != mDNSInterface_BLE && !(Q)->ForceMCast && !IsLocalDomain(&(Q)->qname)))
15205ffb0c9bSToomas Soome 
1521c65ebfc7SToomas Soome // AuthRecordLocalOnly records are registered using mDNSInterface_LocalOnly and
1522c65ebfc7SToomas Soome // AuthRecordP2P records are created by D2DServiceFound events.  Both record types are kept on the same list.
15235ffb0c9bSToomas Soome #define RRLocalOnly(rr) ((rr)->ARType == AuthRecordLocalOnly || (rr)->ARType == AuthRecordP2P)
15245ffb0c9bSToomas Soome 
1525c65ebfc7SToomas Soome // All other auth records, not including those defined as RRLocalOnly().
15265ffb0c9bSToomas Soome #define RRAny(rr) ((rr)->ARType == AuthRecordAny || (rr)->ARType == AuthRecordAnyIncludeP2P || (rr)->ARType == AuthRecordAnyIncludeAWDL || (rr)->ARType == AuthRecordAnyIncludeAWDLandP2P)
15275ffb0c9bSToomas Soome 
15285ffb0c9bSToomas Soome // Normally we always lookup the cache and /etc/hosts before sending the query on the wire. For single label
15295ffb0c9bSToomas Soome // queries (A and AAAA) that are unqualified (indicated by AppendSearchDomains), we want to append search
15305ffb0c9bSToomas Soome // domains before we try them as such
15315ffb0c9bSToomas Soome #define ApplySearchDomainsFirst(q) ((q)->AppendSearchDomains && (CountLabels(&((q)->qname))) == 1)
15324b22b933Srs 
15334b22b933Srs // Wrapper struct for Auth Records for higher-level code that cannot use the AuthRecord's ->next pointer field
15344b22b933Srs typedef struct ARListElem
15355ffb0c9bSToomas Soome {
15365ffb0c9bSToomas Soome     struct ARListElem *next;
15375ffb0c9bSToomas Soome     AuthRecord ar;          // Note: Must be last element of structure, to accomodate oversized AuthRecords
15385ffb0c9bSToomas Soome } ARListElem;
15394b22b933Srs 
15404b22b933Srs struct CacheRecord_struct
15415ffb0c9bSToomas Soome {
15425ffb0c9bSToomas Soome     CacheRecord    *next;               // Next in list; first element of structure for efficiency reasons
1543cda73f64SToomas Soome     ResourceRecord resrec;              // 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit (now 44/64)
15445ffb0c9bSToomas Soome 
15455ffb0c9bSToomas Soome     // Transient state for Cache Records
15465ffb0c9bSToomas Soome     CacheRecord    *NextInKAList;       // Link to the next element in the chain of known answers to send
15475ffb0c9bSToomas Soome     mDNSs32 TimeRcvd;                   // In platform time units
15485ffb0c9bSToomas Soome     mDNSs32 DelayDelivery;              // Set if we want to defer delivery of this answer to local clients
15495ffb0c9bSToomas Soome     mDNSs32 NextRequiredQuery;          // In platform time units
1550*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, CACHE_ANALYTICS)
1551*472cd20dSToomas Soome     mDNSs32 LastCachedAnswerTime;       // Last time this record was used as an answer from the cache (before a query)
1552*472cd20dSToomas Soome                                         // In platform time units
1553*472cd20dSToomas Soome #else
15543b436d06SToomas Soome     // Extra four bytes here (on 64bit)
1555*472cd20dSToomas Soome #endif
15565ffb0c9bSToomas Soome     DNSQuestion    *CRActiveQuestion;   // Points to an active question referencing this answer. Can never point to a NewQuestion.
15575ffb0c9bSToomas Soome     mDNSs32 LastUnansweredTime;         // In platform time units; last time we incremented UnansweredQueries
15585ffb0c9bSToomas Soome     mDNSu8  UnansweredQueries;          // Number of times we've issued a query for this record without getting an answer
15595ffb0c9bSToomas Soome     mDNSOpaque16 responseFlags;         // Second 16 bit in the DNS response
15605ffb0c9bSToomas Soome     CacheRecord    *NextInCFList;       // Set if this is in the list of records we just received with the cache flush bit set
15615ffb0c9bSToomas Soome     CacheRecord    *soa;                // SOA record to return for proxy questions
1562*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
1563*472cd20dSToomas Soome     void *denial_of_existence_records;  // denial_of_existence_records_t
1564*472cd20dSToomas Soome #endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
15655ffb0c9bSToomas Soome 
15665ffb0c9bSToomas Soome     mDNSAddr sourceAddress;             // node from which we received this record
1567cda73f64SToomas Soome     // Size to here is 76 bytes when compiling 32-bit; 104 bytes when compiling 64-bit (now 160 bytes for 64-bit)
15685ffb0c9bSToomas Soome     RData_small smallrdatastorage;      // Storage for small records is right here (4 bytes header + 68 bytes data = 72 bytes)
15695ffb0c9bSToomas Soome };
15705ffb0c9bSToomas Soome 
15715ffb0c9bSToomas Soome // Should match the CacheGroup_struct members, except namestorage[].  Only used to calculate
1572cda73f64SToomas Soome // the size of the namestorage array in CacheGroup_struct so that sizeof(CacheGroup) == sizeof(CacheRecord)
15735ffb0c9bSToomas Soome struct CacheGroup_base
15745ffb0c9bSToomas Soome {
15755ffb0c9bSToomas Soome     CacheGroup     *next;
15765ffb0c9bSToomas Soome     mDNSu32         namehash;
15775ffb0c9bSToomas Soome     CacheRecord    *members;
15785ffb0c9bSToomas Soome     CacheRecord   **rrcache_tail;
15795ffb0c9bSToomas Soome     domainname     *name;
15805ffb0c9bSToomas Soome };
15815ffb0c9bSToomas Soome 
15825ffb0c9bSToomas Soome struct CacheGroup_struct                // Header object for a list of CacheRecords with the same name
15835ffb0c9bSToomas Soome {
15845ffb0c9bSToomas Soome     CacheGroup     *next;               // Next CacheGroup object in this hash table bucket
15855ffb0c9bSToomas Soome     mDNSu32         namehash;           // Name-based (i.e. case insensitive) hash of name
15865ffb0c9bSToomas Soome     CacheRecord    *members;            // List of CacheRecords with this same name
15875ffb0c9bSToomas Soome     CacheRecord   **rrcache_tail;       // Tail end of that list
15885ffb0c9bSToomas Soome     domainname     *name;               // Common name for all CacheRecords in this list
15895ffb0c9bSToomas Soome     mDNSu8 namestorage[sizeof(CacheRecord) - sizeof(struct CacheGroup_base)];  // match sizeof(CacheRecord)
15905ffb0c9bSToomas Soome };
15914b22b933Srs 
15924b22b933Srs // Storage sufficient to hold either a CacheGroup header or a CacheRecord
15935ffb0c9bSToomas Soome // -- for best efficiency (to avoid wasted unused storage) they should be the same size
15944b22b933Srs typedef union CacheEntity_union CacheEntity;
15954b22b933Srs union CacheEntity_union { CacheEntity *next; CacheGroup cg; CacheRecord cr; };
15964b22b933Srs 
15974b22b933Srs typedef struct
15985ffb0c9bSToomas Soome {
15995ffb0c9bSToomas Soome     CacheRecord r;
16005ffb0c9bSToomas Soome     mDNSu8 _extradata[MaximumRDSize-InlineCacheRDSize];     // Glue on the necessary number of extra bytes
16015ffb0c9bSToomas Soome     domainname namestorage;                                 // Needs to go *after* the extra rdata bytes
16025ffb0c9bSToomas Soome } LargeCacheRecord;
16035ffb0c9bSToomas Soome 
16045ffb0c9bSToomas Soome typedef struct HostnameInfo
16055ffb0c9bSToomas Soome {
16065ffb0c9bSToomas Soome     struct HostnameInfo *next;
16075ffb0c9bSToomas Soome     NATTraversalInfo natinfo;
16084b22b933Srs     domainname fqdn;
16095ffb0c9bSToomas Soome     AuthRecord arv4;                          // registered IPv4 address record
16105ffb0c9bSToomas Soome     AuthRecord arv6;                          // registered IPv6 address record
16115ffb0c9bSToomas Soome     mDNSRecordCallback *StatusCallback;       // callback to deliver success or error code to client layer
16125ffb0c9bSToomas Soome     const void *StatusContext;                // Client Context
16135ffb0c9bSToomas Soome } HostnameInfo;
16144b22b933Srs 
16154b22b933Srs typedef struct ExtraResourceRecord_struct ExtraResourceRecord;
16164b22b933Srs struct ExtraResourceRecord_struct
16175ffb0c9bSToomas Soome {
16185ffb0c9bSToomas Soome     ExtraResourceRecord *next;
16194b22b933Srs     mDNSu32 ClientID;  // Opaque ID field to be used by client to map an AddRecord call to a set of Extra records
16205ffb0c9bSToomas Soome     AuthRecord r;
16215ffb0c9bSToomas Soome     // Note: Add any additional fields *before* the AuthRecord in this structure, not at the end.
16225ffb0c9bSToomas Soome     // In some cases clients can allocate larger chunks of memory and set r->rdata->MaxRDLength to indicate
16235ffb0c9bSToomas Soome     // that this extra memory is available, which would result in any fields after the AuthRecord getting smashed
16245ffb0c9bSToomas Soome };
16255ffb0c9bSToomas Soome 
16265ffb0c9bSToomas Soome // Note: Within an mDNSServiceCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
16275ffb0c9bSToomas Soome typedef void mDNSServiceCallback (mDNS *const m, ServiceRecordSet *const sr, mStatus result);
16285ffb0c9bSToomas Soome 
16295ffb0c9bSToomas Soome // A ServiceRecordSet has no special meaning to the core code of the Multicast DNS protocol engine;
16305ffb0c9bSToomas Soome // it is just a convenience structure to group together the records that make up a standard service
16315ffb0c9bSToomas Soome // registration so that they can be allocted and deallocted together as a single memory object.
16325ffb0c9bSToomas Soome // It contains its own ServiceCallback+ServiceContext to report aggregate results up to the next layer of software above.
16335ffb0c9bSToomas Soome // It also contains:
16345ffb0c9bSToomas Soome //  * the basic PTR/SRV/TXT triplet used to represent any DNS-SD service
16355ffb0c9bSToomas Soome //  * the "_services" PTR record for service enumeration
16365ffb0c9bSToomas Soome //  * the optional list of SubType PTR records
16375ffb0c9bSToomas Soome //  * the optional list of additional records attached to the service set (e.g. iChat pictures)
16384b22b933Srs 
16394b22b933Srs struct ServiceRecordSet_struct
16405ffb0c9bSToomas Soome {
16415ffb0c9bSToomas Soome     // These internal state fields are used internally by mDNSCore; the client layer needn't be concerned with them.
16425ffb0c9bSToomas Soome     // No fields need to be set up by the client prior to calling mDNS_RegisterService();
16435ffb0c9bSToomas Soome     // all required data is passed as parameters to that function.
16445ffb0c9bSToomas Soome     mDNSServiceCallback *ServiceCallback;
16455ffb0c9bSToomas Soome     void                *ServiceContext;
16465ffb0c9bSToomas Soome     mDNSBool Conflict;              // Set if this record set was forcibly deregistered because of a conflict
16475ffb0c9bSToomas Soome 
16485ffb0c9bSToomas Soome     ExtraResourceRecord *Extras;    // Optional list of extra AuthRecords attached to this service registration
16495ffb0c9bSToomas Soome     mDNSu32 NumSubTypes;
16505ffb0c9bSToomas Soome     AuthRecord          *SubTypes;
1651*472cd20dSToomas Soome     mDNSu32             flags;      // saved for subsequent calls to mDNS_RegisterService() if records
16525ffb0c9bSToomas Soome                                     // need to be re-registered.
16535ffb0c9bSToomas Soome     AuthRecord RR_ADV;              // e.g. _services._dns-sd._udp.local. PTR _printer._tcp.local.
16545ffb0c9bSToomas Soome     AuthRecord RR_PTR;              // e.g. _printer._tcp.local.        PTR Name._printer._tcp.local.
16555ffb0c9bSToomas Soome     AuthRecord RR_SRV;              // e.g. Name._printer._tcp.local.   SRV 0 0 port target
16565ffb0c9bSToomas Soome     AuthRecord RR_TXT;              // e.g. Name._printer._tcp.local.   TXT PrintQueueName
16575ffb0c9bSToomas Soome     // Don't add any fields after AuthRecord RR_TXT.
16585ffb0c9bSToomas Soome     // This is where the implicit extra space goes if we allocate a ServiceRecordSet containing an oversized RR_TXT record
16595ffb0c9bSToomas Soome };
16604b22b933Srs 
16614b22b933Srs // ***************************************************************************
16624b22b933Srs #if 0
16635ffb0c9bSToomas Soome #pragma mark -
16644b22b933Srs #pragma mark - Question structures
16654b22b933Srs #endif
16664b22b933Srs 
16674b22b933Srs // We record the last eight instances of each duplicate query
16685ffb0c9bSToomas Soome // This gives us v4/v6 on each of Ethernet, AirPort and Firewire, and two free slots "for future expansion"
16694b22b933Srs // If the host has more active interfaces that this it is not fatal -- duplicate question suppression will degrade gracefully.
16704b22b933Srs // Since we will still remember the last eight, the busiest interfaces will still get the effective duplicate question suppression.
16714b22b933Srs #define DupSuppressInfoSize 8
16724b22b933Srs 
16734b22b933Srs typedef struct
16745ffb0c9bSToomas Soome {
16755ffb0c9bSToomas Soome     mDNSs32 Time;
16765ffb0c9bSToomas Soome     mDNSInterfaceID InterfaceID;
16775ffb0c9bSToomas Soome     mDNSs32 Type;                           // v4 or v6?
16785ffb0c9bSToomas Soome } DupSuppressInfo;
16794b22b933Srs 
16804b22b933Srs typedef enum
16815ffb0c9bSToomas Soome {
1682*472cd20dSToomas Soome     // This is the initial state.
1683*472cd20dSToomas Soome     LLQ_Init = 1,
1684*472cd20dSToomas Soome 
1685*472cd20dSToomas Soome     // All of these states indicate that we are doing DNS Push, and haven't given up yet.
1686*472cd20dSToomas Soome 	LLQ_DNSPush_ServerDiscovery = 100,
1687*472cd20dSToomas Soome 	LLQ_DNSPush_Connecting      = 101,
1688*472cd20dSToomas Soome 	LLQ_DNSPush_Established     = 102,
1689*472cd20dSToomas Soome 
1690*472cd20dSToomas Soome     // All of these states indicate that we are doing LLQ and haven't given up yet.
1691*472cd20dSToomas Soome     LLQ_InitialRequest   = 200,
1692*472cd20dSToomas Soome     LLQ_SecondaryRequest = 201,
1693*472cd20dSToomas Soome     LLQ_Established      = 202,
1694*472cd20dSToomas Soome 
1695*472cd20dSToomas Soome     // If we get here, it means DNS Push isn't available, so we're polling.
1696*472cd20dSToomas Soome     LLQ_Poll                    = 300
16975ffb0c9bSToomas Soome } LLQ_State;
16984b22b933Srs 
16994b22b933Srs // LLQ constants
17004b22b933Srs #define kLLQ_Vers      1
17014b22b933Srs #define kLLQ_DefLease  7200 // 2 hours
17024b22b933Srs #define kLLQ_MAX_TRIES 3    // retry an operation 3 times max
17034b22b933Srs #define kLLQ_INIT_RESEND 2 // resend an un-ack'd packet after 2 seconds, then double for each additional
17044b22b933Srs // LLQ Operation Codes
17054b22b933Srs #define kLLQOp_Setup     1
17064b22b933Srs #define kLLQOp_Refresh   2
17074b22b933Srs #define kLLQOp_Event     3
17084b22b933Srs 
17094b22b933Srs // LLQ Errror Codes
17104b22b933Srs enum
17115ffb0c9bSToomas Soome {
17125ffb0c9bSToomas Soome     LLQErr_NoError    = 0,
17135ffb0c9bSToomas Soome     LLQErr_ServFull   = 1,
17145ffb0c9bSToomas Soome     LLQErr_Static     = 2,
17155ffb0c9bSToomas Soome     LLQErr_FormErr    = 3,
17165ffb0c9bSToomas Soome     LLQErr_NoSuchLLQ  = 4,
17175ffb0c9bSToomas Soome     LLQErr_BadVers    = 5,
17185ffb0c9bSToomas Soome     LLQErr_UnknownErr = 6
17195ffb0c9bSToomas Soome };
17205ffb0c9bSToomas Soome 
17215ffb0c9bSToomas Soome enum { NoAnswer_Normal = 0, NoAnswer_Suspended = 1, NoAnswer_Fail = 2 };
17225ffb0c9bSToomas Soome 
1723c65ebfc7SToomas Soome typedef enum {
1724*472cd20dSToomas Soome     DNSPushServerDisconnected,
1725*472cd20dSToomas Soome 	DNSPushServerConnectFailed,
1726*472cd20dSToomas Soome 	DNSPushServerConnectionInProgress,
1727*472cd20dSToomas Soome 	DNSPushServerConnected,
1728*472cd20dSToomas Soome 	DNSPushServerSessionEstablished,
1729*472cd20dSToomas Soome 	DNSPushServerNoDNSPush
1730*472cd20dSToomas Soome } DNSPushServer_ConnectState;
1731*472cd20dSToomas Soome 
17323b436d06SToomas Soome enum {
17333b436d06SToomas Soome     AllowExpired_None = 0,                  // Don't allow expired answers or mark answers immortal (behave normally)
17343b436d06SToomas Soome     AllowExpired_MakeAnswersImmortal = 1,   // Any answers to this question get marked as immortal
17353b436d06SToomas Soome     AllowExpired_AllowExpiredAnswers = 2    // Allow already expired answers from the cache
17363b436d06SToomas Soome };
17373b436d06SToomas Soome typedef mDNSu8 AllowExpiredState;
1738c65ebfc7SToomas Soome 
17395ffb0c9bSToomas Soome #define HMAC_LEN    64
17405ffb0c9bSToomas Soome #define HMAC_IPAD   0x36
17415ffb0c9bSToomas Soome #define HMAC_OPAD   0x5c
17425ffb0c9bSToomas Soome #define MD5_LEN     16
17435ffb0c9bSToomas Soome 
17445ffb0c9bSToomas Soome // Internal data structure to maintain authentication information
17455ffb0c9bSToomas Soome typedef struct DomainAuthInfo
17465ffb0c9bSToomas Soome {
17475ffb0c9bSToomas Soome     struct DomainAuthInfo *next;
17485ffb0c9bSToomas Soome     mDNSs32 deltime;                        // If we're planning to delete this DomainAuthInfo, the time we want it deleted
17495ffb0c9bSToomas Soome     domainname domain;
17505ffb0c9bSToomas Soome     domainname keyname;
17515ffb0c9bSToomas Soome     domainname hostname;
17525ffb0c9bSToomas Soome     mDNSIPPort port;
17535ffb0c9bSToomas Soome     char b64keydata[32];
17545ffb0c9bSToomas Soome     mDNSu8 keydata_ipad[HMAC_LEN];              // padded key for inner hash rounds
17555ffb0c9bSToomas Soome     mDNSu8 keydata_opad[HMAC_LEN];              // padded key for outer hash rounds
17565ffb0c9bSToomas Soome } DomainAuthInfo;
17575ffb0c9bSToomas Soome 
17585ffb0c9bSToomas Soome // Note: Within an mDNSQuestionCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
17595ffb0c9bSToomas Soome // Note: Any value other than QC_rmv i.e., any non-zero value will result in kDNSServiceFlagsAdd to the application
17605ffb0c9bSToomas Soome // layer. These values are used within mDNSResponder and not sent across to the application. QC_addnocache is for
17615ffb0c9bSToomas Soome // delivering a response without adding to the cache. QC_forceresponse is superset of QC_addnocache where in
17625ffb0c9bSToomas Soome // addition to not entering in the cache, it also forces the negative response through.
1763*472cd20dSToomas Soome typedef enum { QC_rmv = 0, QC_add, QC_addnocache, QC_forceresponse, QC_suppressed } QC_result;
17645ffb0c9bSToomas Soome typedef void mDNSQuestionCallback (mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord);
1765*472cd20dSToomas Soome typedef void (*mDNSQuestionResetHandler)(DNSQuestion *question);
17665ffb0c9bSToomas Soome typedef void AsyncDispatchFunc(mDNS *const m, void *context);
17675ffb0c9bSToomas Soome extern void mDNSPlatformDispatchAsync(mDNS *const m, void *context, AsyncDispatchFunc func);
17685ffb0c9bSToomas Soome 
17695ffb0c9bSToomas Soome #define NextQSendTime(Q)  ((Q)->LastQTime + (Q)->ThisQInterval)
17705ffb0c9bSToomas Soome #define ActiveQuestion(Q) ((Q)->ThisQInterval > 0 && !(Q)->DuplicateOf)
17715ffb0c9bSToomas Soome #define TimeToSendThisQuestion(Q,time) (ActiveQuestion(Q) && (time) - NextQSendTime(Q) >= 0)
17725ffb0c9bSToomas Soome 
1773*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
1774*472cd20dSToomas Soome #define FollowCNAMEOptionDNSSEC(Q)      !(Q)->DNSSECStatus.enable_dnssec
1775*472cd20dSToomas Soome #else // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
1776*472cd20dSToomas Soome #define FollowCNAMEOptionDNSSEC(Q)      mDNStrue
1777*472cd20dSToomas Soome #endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
17785ffb0c9bSToomas Soome 
17795ffb0c9bSToomas Soome // Given the resource record and the question, should we follow the CNAME ?
17805ffb0c9bSToomas Soome #define FollowCNAME(q, rr, AddRecord)   (AddRecord && (q)->qtype != kDNSType_CNAME && \
17815ffb0c9bSToomas Soome                                          (rr)->RecordType != kDNSRecordTypePacketNegative && \
1782*472cd20dSToomas Soome                                          (rr)->rrtype == kDNSType_CNAME \
1783*472cd20dSToomas Soome                                          && FollowCNAMEOptionDNSSEC(q))
17845ffb0c9bSToomas Soome 
1785c65ebfc7SToomas Soome // RFC 4122 defines it to be 16 bytes
17865ffb0c9bSToomas Soome #define UUID_SIZE       16
17875ffb0c9bSToomas Soome 
1788*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, METRICS)
17893b436d06SToomas Soome enum
1790cda73f64SToomas Soome {
17913b436d06SToomas Soome     ExpiredAnswer_None = 0,                  // No expired answers used
17923b436d06SToomas Soome     ExpiredAnswer_Allowed = 1,               // An expired answer is allowed by this request
1793*472cd20dSToomas Soome     ExpiredAnswer_AnsweredWithCache = 2,     // Question was answered with a cached answer
1794*472cd20dSToomas Soome     ExpiredAnswer_AnsweredWithExpired = 3,   // Question was answered with an expired answer
1795*472cd20dSToomas Soome     ExpiredAnswer_ExpiredAnswerChanged = 4,  // Expired answer changed on refresh
17963b436d06SToomas Soome 
17973b436d06SToomas Soome     ExpiredAnswer_EnumCount
17983b436d06SToomas Soome };
17993b436d06SToomas Soome typedef mDNSu8 ExpiredAnswerMetric;
1800cda73f64SToomas Soome 
1801*472cd20dSToomas Soome enum
1802*472cd20dSToomas Soome {
1803*472cd20dSToomas Soome     DNSOverTCP_None = 0,                     // DNS Over TCP not used
1804*472cd20dSToomas Soome     DNSOverTCP_Truncated = 1,                // DNS Over TCP used because UDP reply was truncated
1805*472cd20dSToomas Soome     DNSOverTCP_Suspicious = 2,               // DNS Over TCP used because we received a suspicious reply
1806*472cd20dSToomas Soome     DNSOverTCP_SuspiciousDefense = 3,        // DNS Over TCP used because we were within the timeframe of a previous suspicious response
1807*472cd20dSToomas Soome 
1808*472cd20dSToomas Soome     DNSOverTCP_EnumCount
1809*472cd20dSToomas Soome };
1810*472cd20dSToomas Soome typedef mDNSu8 DNSOverTCPMetric;
1811*472cd20dSToomas Soome 
18123b436d06SToomas Soome typedef struct
18133b436d06SToomas Soome {
18143b436d06SToomas Soome     domainname *        originalQName;          // Name of original A/AAAA record if this question is for a CNAME record.
18153b436d06SToomas Soome     mDNSu32             querySendCount;         // Number of queries that have been sent to DNS servers so far.
18163b436d06SToomas Soome     mDNSs32             firstQueryTime;         // The time when the first query was sent to a DNS server.
18173b436d06SToomas Soome     mDNSBool            answered;               // Has this question been answered?
18183b436d06SToomas Soome     ExpiredAnswerMetric expiredAnswerState;     // Expired answer state (see ExpiredAnswerMetric above)
1819*472cd20dSToomas Soome     DNSOverTCPMetric    dnsOverTCPState;        // DNS Over TCP state (see DNSOverTCPMetric above)
1820*472cd20dSToomas Soome 
1821cda73f64SToomas Soome }   uDNSMetrics;
1822cda73f64SToomas Soome #endif
1823cda73f64SToomas Soome 
1824*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, METRICS)
1825*472cd20dSToomas Soome extern mDNSu32 curr_num_regservices; // tracks the current number of services registered
1826*472cd20dSToomas Soome extern mDNSu32 max_num_regservices;  // tracks the max number of simultaneous services registered by the device
1827*472cd20dSToomas Soome #endif
1828c65ebfc7SToomas Soome 
1829*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, DNS64)
1830c65ebfc7SToomas Soome #include "DNS64State.h"
1831c65ebfc7SToomas Soome #endif
1832c65ebfc7SToomas Soome 
1833*472cd20dSToomas Soome typedef struct mDNS_DNSPushNotificationServer DNSPushNotificationServer;
1834*472cd20dSToomas Soome typedef struct mDNS_DNSPushNotificationZone   DNSPushNotificationZone;
1835c65ebfc7SToomas Soome 
18364b22b933Srs struct DNSQuestion_struct
18375ffb0c9bSToomas Soome {
18385ffb0c9bSToomas Soome     // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
18395ffb0c9bSToomas Soome     DNSQuestion          *next;
18405ffb0c9bSToomas Soome     mDNSu32 qnamehash;
18415ffb0c9bSToomas Soome     mDNSs32 DelayAnswering;                 // Set if we want to defer answering this question until the cache settles
18425ffb0c9bSToomas Soome     mDNSs32 LastQTime;                      // Last scheduled transmission of this Q on *all* applicable interfaces
18435ffb0c9bSToomas Soome     mDNSs32 ThisQInterval;                  // LastQTime + ThisQInterval is the next scheduled transmission of this Q
18445ffb0c9bSToomas Soome                                             // ThisQInterval > 0 for an active question;
18455ffb0c9bSToomas Soome                                             // ThisQInterval = 0 for a suspended question that's still in the list
18465ffb0c9bSToomas Soome                                             // ThisQInterval = -1 for a cancelled question (should not still be in list)
18475ffb0c9bSToomas Soome     mDNSs32 ExpectUnicastResp;              // Set when we send a query with the kDNSQClass_UnicastResponse bit set
18485ffb0c9bSToomas Soome     mDNSs32 LastAnswerPktNum;               // The sequence number of the last response packet containing an answer to this Q
18495ffb0c9bSToomas Soome     mDNSu32 RecentAnswerPkts;               // Number of answers since the last time we sent this query
18505ffb0c9bSToomas Soome     mDNSu32 CurrentAnswers;                 // Number of records currently in the cache that answer this question
18515ffb0c9bSToomas Soome     mDNSu32 BrowseThreshold;                // If we have received at least this number of answers,
18525ffb0c9bSToomas Soome                                             // set the next question interval to MaxQuestionInterval
18535ffb0c9bSToomas Soome     mDNSu32 LargeAnswers;                   // Number of answers with rdata > 1024 bytes
18545ffb0c9bSToomas Soome     mDNSu32 UniqueAnswers;                  // Number of answers received with kDNSClass_UniqueRRSet bit set
18555ffb0c9bSToomas Soome     mDNSInterfaceID FlappingInterface1;     // Set when an interface goes away, to flag if remove events are delivered for this Q
18565ffb0c9bSToomas Soome     mDNSInterfaceID FlappingInterface2;     // Set when an interface goes away, to flag if remove events are delivered for this Q
18575ffb0c9bSToomas Soome     DomainAuthInfo       *AuthInfo;         // Non-NULL if query is currently being done using Private DNS
18585ffb0c9bSToomas Soome     DNSQuestion          *DuplicateOf;
18595ffb0c9bSToomas Soome     DNSQuestion          *NextInDQList;
18605ffb0c9bSToomas Soome     DupSuppressInfo DupSuppress[DupSuppressInfoSize];
18615ffb0c9bSToomas Soome     mDNSInterfaceID SendQNow;               // The interface this query is being sent on right now
18625ffb0c9bSToomas Soome     mDNSBool SendOnAll;                     // Set if we're sending this question on all active interfaces
1863c65ebfc7SToomas Soome     mDNSBool CachedAnswerNeedsUpdate;       // See SendQueries().  Set if we're sending this question
18645ffb0c9bSToomas Soome                                             // because a cached answer needs to be refreshed.
18655ffb0c9bSToomas Soome     mDNSu32 RequestUnicast;                 // Non-zero if we want to send query with kDNSQClass_UnicastResponse bit set
18665ffb0c9bSToomas Soome     mDNSs32 LastQTxTime;                    // Last time this Q was sent on one (but not necessarily all) interfaces
18675ffb0c9bSToomas Soome     mDNSu32 CNAMEReferrals;                 // Count of how many CNAME redirections we've done
1868*472cd20dSToomas Soome     mDNSBool Suppressed;                    // This query should be suppressed, i.e., not sent on the wire.
18695ffb0c9bSToomas Soome     mDNSu8 LOAddressAnswers;                // Number of answers from the local only auth records that are
18705ffb0c9bSToomas Soome                                             // answering A, AAAA, CNAME, or PTR (/etc/hosts)
18715ffb0c9bSToomas Soome     mDNSu8 WakeOnResolveCount;              // Number of wakes that should be sent on resolve
1872*472cd20dSToomas Soome     mDNSBool InitialCacheMiss;              // True after the question cannot be answered from the cache
18735ffb0c9bSToomas Soome     mDNSs32 StopTime;                       // Time this question should be stopped by giving them a negative answer
18745ffb0c9bSToomas Soome 
18755ffb0c9bSToomas Soome     // Wide Area fields. These are used internally by the uDNS core (Unicast)
18765ffb0c9bSToomas Soome     UDPSocket            *LocalSocket;
18775ffb0c9bSToomas Soome 
18785ffb0c9bSToomas Soome     // |-> DNS Configuration related fields used in uDNS (Subset of Wide Area/Unicast fields)
1879*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
1880*472cd20dSToomas Soome     mdns_dns_service_t    dnsservice;       // The current DNS service.
1881*472cd20dSToomas Soome     mdns_dns_service_id_t lastDNSServiceID; // The ID of the previous DNS service before a CNAME restart.
1882*472cd20dSToomas Soome     mdns_querier_t        querier;          // The current querier.
1883*472cd20dSToomas Soome #else
18845ffb0c9bSToomas Soome     DNSServer            *qDNSServer;       // Caching server for this query (in the absence of an SRV saying otherwise)
1885c65ebfc7SToomas Soome     mDNSOpaque128 validDNSServers;          // Valid DNSServers for this question
18865ffb0c9bSToomas Soome     mDNSu16 noServerResponse;               // At least one server did not respond.
1887*472cd20dSToomas Soome     mDNSBool triedAllServersOnce;           // True if all DNS servers have been tried once.
18885ffb0c9bSToomas Soome     mDNSu8 unansweredQueries;               // The number of unanswered queries to this server
1889*472cd20dSToomas Soome #endif
18903b436d06SToomas Soome     AllowExpiredState allowExpired;         // Allow expired answers state (see enum AllowExpired_None, etc. above)
18915ffb0c9bSToomas Soome 
18925ffb0c9bSToomas Soome     ZoneData             *nta;              // Used for getting zone data for private or LLQ query
18935ffb0c9bSToomas Soome     mDNSAddr servAddr;                      // Address and port learned from _dns-llq, _dns-llq-tls or _dns-query-tls SRV query
18945ffb0c9bSToomas Soome     mDNSIPPort servPort;
18955ffb0c9bSToomas Soome     struct tcpInfo_t *tcp;
18965ffb0c9bSToomas Soome     mDNSIPPort tcpSrcPort;                  // Local Port TCP packet received on;need this as tcp struct is disposed
18975ffb0c9bSToomas Soome                                             // by tcpCallback before calling into mDNSCoreReceive
18985ffb0c9bSToomas Soome     mDNSu8 NoAnswer;                        // Set if we want to suppress answers until tunnel setup has completed
1899*472cd20dSToomas Soome #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
1900*472cd20dSToomas Soome     mDNSBool Restart;                       // This question should be restarted soon.
1901*472cd20dSToomas Soome #endif
19025ffb0c9bSToomas Soome 
19035ffb0c9bSToomas Soome     // LLQ-specific fields. These fields are only meaningful when LongLived flag is set
19045ffb0c9bSToomas Soome     LLQ_State state;
19055ffb0c9bSToomas Soome     mDNSu32 ReqLease;                       // seconds (relative)
19065ffb0c9bSToomas Soome     mDNSs32 expire;                         // ticks (absolute)
19075ffb0c9bSToomas Soome     mDNSs16 ntries;                         // for UDP: the number of packets sent for this LLQ state
19085ffb0c9bSToomas Soome                                             // for TCP: there is some ambiguity in the use of this variable, but in general, it is
19095ffb0c9bSToomas Soome                                             //          the number of TCP/TLS connection attempts for this LLQ state, or
19105ffb0c9bSToomas Soome                                             //          the number of packets sent for this TCP/TLS connection
1911c65ebfc7SToomas Soome 
1912c65ebfc7SToomas Soome     // DNS Push Notification fields. These fields are only meaningful when LongLived flag is set
1913*472cd20dSToomas Soome     DNSPushNotificationServer *dnsPushServer;
1914*472cd20dSToomas Soome 
19155ffb0c9bSToomas Soome     mDNSOpaque64 id;
19165ffb0c9bSToomas Soome 
19175ffb0c9bSToomas Soome     // DNS Proxy fields
19185ffb0c9bSToomas Soome     mDNSOpaque16 responseFlags;             // Temporary place holder for the error we get back from the DNS server
19195ffb0c9bSToomas Soome                                             // till we populate in the cache
1920*472cd20dSToomas Soome     mDNSBool     BlockedByPolicy;           // True if the question is blocked by policy rule evaluation.
19215ffb0c9bSToomas Soome     mDNSs32      ServiceID;                 // Service identifier to match against the DNS server
1922*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
1923*472cd20dSToomas Soome     mDNSu8       ResolverUUID[UUID_SIZE];   // Resolver UUID to match against the DNS server
1924*472cd20dSToomas Soome     mdns_dns_service_id_t CustomID;
1925*472cd20dSToomas Soome #endif
1926c65ebfc7SToomas Soome 
19275ffb0c9bSToomas Soome     // Client API fields: The client must set up these fields *before* calling mDNS_StartQuery()
19285ffb0c9bSToomas Soome     mDNSInterfaceID InterfaceID;            // Non-zero if you want to issue queries only on a single specific IP interface
19295ffb0c9bSToomas Soome     mDNSu32  flags;                         // flags from original DNSService*() API request.
1930*472cd20dSToomas Soome     mDNSOpaque16 TargetQID;                 // DNS or mDNS message ID.
19315ffb0c9bSToomas Soome     domainname qname;
19323b436d06SToomas Soome     domainname firstExpiredQname;           // first expired qname in request chain
19335ffb0c9bSToomas Soome     mDNSu16 qtype;
19345ffb0c9bSToomas Soome     mDNSu16 qclass;
19355ffb0c9bSToomas Soome     mDNSBool LongLived;                     // Set by client for calls to mDNS_StartQuery to indicate LLQs to unicast layer.
19365ffb0c9bSToomas Soome     mDNSBool ExpectUnique;                  // Set by client if it's expecting unique RR(s) for this question, not shared RRs
19375ffb0c9bSToomas Soome     mDNSBool ForceMCast;                    // Set by client to force mDNS query, even for apparently uDNS names
19385ffb0c9bSToomas Soome     mDNSBool ReturnIntermed;                // Set by client to request callbacks for intermediate CNAME/NXDOMAIN results
19395ffb0c9bSToomas Soome     mDNSBool SuppressUnusable;              // Set by client to suppress unusable queries to be sent on the wire
1940*472cd20dSToomas Soome     mDNSBool TimeoutQuestion;               // Timeout this question if there is no reply in configured time
1941*472cd20dSToomas Soome     mDNSBool IsUnicastDotLocal;             // True if this is a dot-local query that should be answered via unicast DNS.
1942*472cd20dSToomas Soome     mDNSBool WakeOnResolve;                 // Send wakeup on resolve
1943*472cd20dSToomas Soome     mDNSBool UseBackgroundTraffic;          // Set by client to use background traffic class for request
1944*472cd20dSToomas Soome     mDNSBool AppendSearchDomains;           // Search domains can be appended for this query
1945*472cd20dSToomas Soome     mDNSBool ForcePathEval;                 // Perform a path evaluation even if kDNSServiceFlagsPathEvaluationDone is set.
1946*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
1947*472cd20dSToomas Soome     mDNSBool RequireEncryption;             // Set by client to require encrypted queries
1948*472cd20dSToomas Soome #endif
1949*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, AUDIT_TOKEN)
1950*472cd20dSToomas Soome     mDNSBool inAppBrowserRequest;           // Is request associated with an in-app-browser
1951*472cd20dSToomas Soome     audit_token_t  peerAuditToken;          // audit token of the peer requesting the question
1952*472cd20dSToomas Soome     audit_token_t  delegateAuditToken;      // audit token of the delegated client the question is for
1953*472cd20dSToomas Soome #endif
19545ffb0c9bSToomas Soome     mDNSu8 ProxyQuestion;                   // Proxy Question
19555ffb0c9bSToomas Soome     mDNSs32 pid;                            // Process ID of the client that is requesting the question
19565ffb0c9bSToomas Soome     mDNSu8  uuid[UUID_SIZE];                // Unique ID of the client that is requesting the question (valid only if pid is zero)
1957cda73f64SToomas Soome     mDNSu32 euid;                           // Effective User Id of the client that is requesting the question
1958*472cd20dSToomas Soome     mDNSu32 request_id;                     // The ID of request that generates the current question
19595ffb0c9bSToomas Soome     mDNSQuestionCallback *QuestionCallback;
1960*472cd20dSToomas Soome     mDNSQuestionResetHandler ResetHandler;
19615ffb0c9bSToomas Soome     void                 *QuestionContext;
1962*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, METRICS)
1963cda73f64SToomas Soome     uDNSMetrics metrics;                    // Data used for collecting unicast DNS query metrics.
1964cda73f64SToomas Soome #endif
1965*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, DNS64)
1966c65ebfc7SToomas Soome     DNS64 dns64;                            // DNS64 state for performing IPv6 address synthesis on networks with NAT64.
1967c65ebfc7SToomas Soome #endif
1968*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
1969*472cd20dSToomas Soome     dnssec_status_t DNSSECStatus;           // DNSSEC state for fectching DNSSEC records and doing validation
1970*472cd20dSToomas Soome #endif // MDNSRESPONDER_SUPPORTS(APPLE, DNSSECv2)
19715ffb0c9bSToomas Soome };
19724b22b933Srs 
1973c65ebfc7SToomas Soome typedef enum { ZoneServiceUpdate, ZoneServiceQuery, ZoneServiceLLQ, ZoneServiceDNSPush } ZoneService;
19745ffb0c9bSToomas Soome 
19755ffb0c9bSToomas Soome typedef void ZoneDataCallback (mDNS *const m, mStatus err, const ZoneData *result);
19765ffb0c9bSToomas Soome 
19775ffb0c9bSToomas Soome struct ZoneData_struct
19785ffb0c9bSToomas Soome {
19795ffb0c9bSToomas Soome     domainname ChildName;               // Name for which we're trying to find the responsible server
19805ffb0c9bSToomas Soome     ZoneService ZoneService;            // Which service we're seeking for this zone (update, query, or LLQ)
19815ffb0c9bSToomas Soome     domainname       *CurrentSOA;       // Points to somewhere within ChildName
19825ffb0c9bSToomas Soome     domainname ZoneName;                // Discovered result: Left-hand-side of SOA record
19835ffb0c9bSToomas Soome     mDNSu16 ZoneClass;                  // Discovered result: DNS Class from SOA record
19845ffb0c9bSToomas Soome     domainname Host;                    // Discovered result: Target host from SRV record
19855ffb0c9bSToomas Soome     mDNSIPPort Port;                    // Discovered result: Update port, query port, or LLQ port from SRV record
19865ffb0c9bSToomas Soome     mDNSAddr Addr;                      // Discovered result: Address of Target host from SRV record
19875ffb0c9bSToomas Soome     mDNSBool ZonePrivate;               // Discovered result: Does zone require encrypted queries?
19885ffb0c9bSToomas Soome     ZoneDataCallback *ZoneDataCallback; // Caller-specified function to be called upon completion
19895ffb0c9bSToomas Soome     void             *ZoneDataContext;
19905ffb0c9bSToomas Soome     DNSQuestion question;               // Storage for any active question
19915ffb0c9bSToomas Soome };
19925ffb0c9bSToomas Soome 
19935ffb0c9bSToomas Soome extern ZoneData *StartGetZoneData(mDNS *const m, const domainname *const name, const ZoneService target, ZoneDataCallback callback, void *callbackInfo);
19945ffb0c9bSToomas Soome extern void CancelGetZoneData(mDNS *const m, ZoneData *nta);
19955ffb0c9bSToomas Soome extern mDNSBool IsGetZoneDataQuestion(DNSQuestion *q);
19965ffb0c9bSToomas Soome 
19975ffb0c9bSToomas Soome typedef struct DNameListElem
19985ffb0c9bSToomas Soome {
19995ffb0c9bSToomas Soome     struct DNameListElem *next;
20005ffb0c9bSToomas Soome     mDNSu32 uid;
20015ffb0c9bSToomas Soome     domainname name;
20025ffb0c9bSToomas Soome } DNameListElem;
20035ffb0c9bSToomas Soome 
20045ffb0c9bSToomas Soome #if APPLE_OSX_mDNSResponder
20055ffb0c9bSToomas Soome // Different states that we go through locating the peer
20065ffb0c9bSToomas Soome #define TC_STATE_AAAA_PEER          0x000000001     /* Peer's BTMM IPv6 address */
20075ffb0c9bSToomas Soome #define TC_STATE_AAAA_PEER_RELAY    0x000000002     /* Peer's IPv6 Relay address */
20085ffb0c9bSToomas Soome #define TC_STATE_SRV_PEER           0x000000003     /* Peer's SRV Record corresponding to IPv4 address */
20095ffb0c9bSToomas Soome #define TC_STATE_ADDR_PEER          0x000000004     /* Peer's IPv4 address */
20105ffb0c9bSToomas Soome 
20115ffb0c9bSToomas Soome typedef struct ClientTunnel
20125ffb0c9bSToomas Soome {
20135ffb0c9bSToomas Soome     struct ClientTunnel *next;
20145ffb0c9bSToomas Soome     domainname dstname;
20155ffb0c9bSToomas Soome     mDNSBool MarkedForDeletion;
20165ffb0c9bSToomas Soome     mDNSv6Addr loc_inner;
20175ffb0c9bSToomas Soome     mDNSv4Addr loc_outer;
20185ffb0c9bSToomas Soome     mDNSv6Addr loc_outer6;
20195ffb0c9bSToomas Soome     mDNSv6Addr rmt_inner;
20205ffb0c9bSToomas Soome     mDNSv4Addr rmt_outer;
20215ffb0c9bSToomas Soome     mDNSv6Addr rmt_outer6;
20225ffb0c9bSToomas Soome     mDNSIPPort rmt_outer_port;
20235ffb0c9bSToomas Soome     mDNSu16 tc_state;
20245ffb0c9bSToomas Soome     DNSQuestion q;
20255ffb0c9bSToomas Soome } ClientTunnel;
20265ffb0c9bSToomas Soome #endif
20274b22b933Srs 
20284b22b933Srs // ***************************************************************************
20294b22b933Srs #if 0
20305ffb0c9bSToomas Soome #pragma mark -
20315ffb0c9bSToomas Soome #pragma mark - NetworkInterfaceInfo_struct
20324b22b933Srs #endif
20334b22b933Srs 
20345ffb0c9bSToomas Soome typedef struct NetworkInterfaceInfo_struct NetworkInterfaceInfo;
20354b22b933Srs 
20365ffb0c9bSToomas Soome // A NetworkInterfaceInfo_struct serves two purposes:
20375ffb0c9bSToomas Soome // 1. It holds the address, PTR and HINFO records to advertise a given IP address on a given physical interface
20385ffb0c9bSToomas Soome // 2. It tells mDNSCore which physical interfaces are available; each physical interface has its own unique InterfaceID.
20395ffb0c9bSToomas Soome //    Since there may be multiple IP addresses on a single physical interface,
20405ffb0c9bSToomas Soome //    there may be multiple NetworkInterfaceInfo_structs with the same InterfaceID.
20415ffb0c9bSToomas Soome //    In this case, to avoid sending the same packet n times, when there's more than one
20425ffb0c9bSToomas Soome //    struct with the same InterfaceID, mDNSCore picks one member of the set to be the
20435ffb0c9bSToomas Soome //    active representative of the set; all others have the 'InterfaceActive' flag unset.
20444b22b933Srs 
20455ffb0c9bSToomas Soome struct NetworkInterfaceInfo_struct
20465ffb0c9bSToomas Soome {
20475ffb0c9bSToomas Soome     // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
20485ffb0c9bSToomas Soome     NetworkInterfaceInfo *next;
20495ffb0c9bSToomas Soome 
20505ffb0c9bSToomas Soome     mDNSu8 InterfaceActive;             // Set if interface is sending & receiving packets (see comment above)
20515ffb0c9bSToomas Soome     mDNSu8 IPv4Available;               // If InterfaceActive, set if v4 available on this InterfaceID
20525ffb0c9bSToomas Soome     mDNSu8 IPv6Available;               // If InterfaceActive, set if v6 available on this InterfaceID
20535ffb0c9bSToomas Soome 
20545ffb0c9bSToomas Soome     DNSQuestion NetWakeBrowse;
20555ffb0c9bSToomas Soome     DNSQuestion NetWakeResolve[3];      // For fault-tolerance, we try up to three Sleep Proxies
20565ffb0c9bSToomas Soome     mDNSAddr SPSAddr[3];
20575ffb0c9bSToomas Soome     mDNSIPPort SPSPort[3];
20585ffb0c9bSToomas Soome     mDNSs32 NextSPSAttempt;             // -1 if we're not currently attempting to register with any Sleep Proxy
20595ffb0c9bSToomas Soome     mDNSs32 NextSPSAttemptTime;
20605ffb0c9bSToomas Soome 
20615ffb0c9bSToomas Soome     // Standard AuthRecords that every Responder host should have (one per active IP address)
20625ffb0c9bSToomas Soome     AuthRecord RR_A;                    // 'A' or 'AAAA' (address) record for our ".local" name
20635ffb0c9bSToomas Soome     AuthRecord RR_PTR;                  // PTR (reverse lookup) record
2064*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
2065*472cd20dSToomas Soome     AuthRecord RR_AddrRand;             // For non-AWDL interfaces, this is the A or AAAA record of the randomized hostname.
2066*472cd20dSToomas Soome #endif
20675ffb0c9bSToomas Soome 
20685ffb0c9bSToomas Soome     // Client API fields: The client must set up these fields *before* calling mDNS_RegisterInterface()
20695ffb0c9bSToomas Soome     mDNSInterfaceID InterfaceID;        // Identifies physical interface; MUST NOT be 0, -1, or -2
20705ffb0c9bSToomas Soome     mDNSAddr ip;                        // The IPv4 or IPv6 address to advertise
20715ffb0c9bSToomas Soome     mDNSAddr mask;
20725ffb0c9bSToomas Soome     mDNSEthAddr MAC;
20735ffb0c9bSToomas Soome     char ifname[64];                    // Windows uses a GUID string for the interface name, which doesn't fit in 16 bytes
20745ffb0c9bSToomas Soome     mDNSu8 Advertise;                   // False if you are only searching on this interface
20755ffb0c9bSToomas Soome     mDNSu8 McastTxRx;                   // Send/Receive multicast on this { InterfaceID, address family } ?
20765ffb0c9bSToomas Soome     mDNSu8 NetWake;                     // Set if Wake-On-Magic-Packet is enabled on this interface
20775ffb0c9bSToomas Soome     mDNSu8 Loopback;                    // Set if this is the loopback interface
20785ffb0c9bSToomas Soome     mDNSu8 IgnoreIPv4LL;                // Set if IPv4 Link-Local addresses have to be ignored.
20795ffb0c9bSToomas Soome     mDNSu8 SendGoodbyes;                // Send goodbyes on this interface while sleeping
20805ffb0c9bSToomas Soome     mDNSBool DirectLink;                // a direct link, indicating we can skip the probe for
20815ffb0c9bSToomas Soome                                         // address records
2082cda73f64SToomas Soome     mDNSBool SupportsUnicastMDNSResponse;  // Indicates that the interface supports unicast responses
20833b436d06SToomas Soome                                         // to Bonjour queries.  Generally true for an interface.
20845ffb0c9bSToomas Soome };
20855ffb0c9bSToomas Soome 
20865ffb0c9bSToomas Soome #define SLE_DELETE                      0x00000001
20875ffb0c9bSToomas Soome #define SLE_WAB_BROWSE_QUERY_STARTED    0x00000002
20885ffb0c9bSToomas Soome #define SLE_WAB_LBROWSE_QUERY_STARTED   0x00000004
20895ffb0c9bSToomas Soome #define SLE_WAB_REG_QUERY_STARTED       0x00000008
20905ffb0c9bSToomas Soome 
20915ffb0c9bSToomas Soome typedef struct SearchListElem
20925ffb0c9bSToomas Soome {
20935ffb0c9bSToomas Soome     struct SearchListElem *next;
20945ffb0c9bSToomas Soome     domainname domain;
20955ffb0c9bSToomas Soome     int flag;
20965ffb0c9bSToomas Soome     mDNSInterfaceID InterfaceID;
20975ffb0c9bSToomas Soome     DNSQuestion BrowseQ;
20985ffb0c9bSToomas Soome     DNSQuestion DefBrowseQ;
20995ffb0c9bSToomas Soome     DNSQuestion AutomaticBrowseQ;
21005ffb0c9bSToomas Soome     DNSQuestion RegisterQ;
21015ffb0c9bSToomas Soome     DNSQuestion DefRegisterQ;
21025ffb0c9bSToomas Soome     int numCfAnswers;
21035ffb0c9bSToomas Soome     ARListElem *AuthRecs;
21045ffb0c9bSToomas Soome } SearchListElem;
21055ffb0c9bSToomas Soome 
21065ffb0c9bSToomas Soome // For domain enumeration and automatic browsing
21075ffb0c9bSToomas Soome // This is the user's DNS search list.
21085ffb0c9bSToomas Soome // In each of these domains we search for our special pointer records (lb._dns-sd._udp.<domain>, etc.)
21095ffb0c9bSToomas Soome // to discover recommended domains for domain enumeration (browse, default browse, registration,
21105ffb0c9bSToomas Soome // default registration) and possibly one or more recommended automatic browsing domains.
21115ffb0c9bSToomas Soome extern SearchListElem *SearchList;      // This really ought to be part of mDNS_struct -- SC
21124b22b933Srs 
21134b22b933Srs // ***************************************************************************
21144b22b933Srs #if 0
21155ffb0c9bSToomas Soome #pragma mark -
21164b22b933Srs #pragma mark - Main mDNS object, used to hold all the mDNS state
21174b22b933Srs #endif
21184b22b933Srs 
21195ffb0c9bSToomas Soome typedef void mDNSCallback (mDNS *const m, mStatus result);
21204b22b933Srs 
21215ffb0c9bSToomas Soome #ifndef CACHE_HASH_SLOTS
21224b22b933Srs #define CACHE_HASH_SLOTS 499
21235ffb0c9bSToomas Soome #endif
21244b22b933Srs 
21254b22b933Srs enum
21265ffb0c9bSToomas Soome {
21275ffb0c9bSToomas Soome     SleepState_Awake = 0,
21285ffb0c9bSToomas Soome     SleepState_Transferring = 1,
21295ffb0c9bSToomas Soome     SleepState_Sleeping = 2
21305ffb0c9bSToomas Soome };
21315ffb0c9bSToomas Soome 
21324b22b933Srs typedef struct
21335ffb0c9bSToomas Soome {
21345ffb0c9bSToomas Soome     mDNSu32 NameConflicts;                  // Normal Name conflicts
21355ffb0c9bSToomas Soome     mDNSu32 KnownUniqueNameConflicts;       // Name Conflicts for KnownUnique Records
21365ffb0c9bSToomas Soome     mDNSu32 DupQuerySuppressions;           // Duplicate query suppressions
21375ffb0c9bSToomas Soome     mDNSu32 KnownAnswerSuppressions;        // Known Answer suppressions
21385ffb0c9bSToomas Soome     mDNSu32 KnownAnswerMultiplePkts;        // Known Answer in queries spannign multiple packets
21395ffb0c9bSToomas Soome     mDNSu32 PoofCacheDeletions;             // Number of times the cache was deleted due to POOF
21405ffb0c9bSToomas Soome     mDNSu32 UnicastBitInQueries;            // Queries with QU bit set
21415ffb0c9bSToomas Soome     mDNSu32 NormalQueries;                  // Queries with QU bit not set
21425ffb0c9bSToomas Soome     mDNSu32 MatchingAnswersForQueries;      // Queries for which we had a response
21435ffb0c9bSToomas Soome     mDNSu32 UnicastResponses;               // Unicast responses to queries
21445ffb0c9bSToomas Soome     mDNSu32 MulticastResponses;             // Multicast responses to queries
21455ffb0c9bSToomas Soome     mDNSu32 UnicastDemotedToMulticast;      // Number of times unicast demoted to multicast
21465ffb0c9bSToomas Soome     mDNSu32 Sleeps;                         // Total sleeps
21475ffb0c9bSToomas Soome     mDNSu32 Wakes;                          // Total wakes
21485ffb0c9bSToomas Soome     mDNSu32 InterfaceUp;                    // Total Interface UP events
21495ffb0c9bSToomas Soome     mDNSu32 InterfaceUpFlap;                // Total Interface UP events with flaps
21505ffb0c9bSToomas Soome     mDNSu32 InterfaceDown;                  // Total Interface Down events
21515ffb0c9bSToomas Soome     mDNSu32 InterfaceDownFlap;              // Total Interface Down events with flaps
21525ffb0c9bSToomas Soome     mDNSu32 CacheRefreshQueries;            // Number of queries that we sent for refreshing cache
21535ffb0c9bSToomas Soome     mDNSu32 CacheRefreshed;                 // Number of times the cache was refreshed due to a response
21545ffb0c9bSToomas Soome     mDNSu32 WakeOnResolves;                 // Number of times we did a wake on resolve
21555ffb0c9bSToomas Soome } mDNSStatistics;
2156cda73f64SToomas Soome 
2157*472cd20dSToomas Soome extern void LogMDNSStatisticsToFD(int fd, mDNS *const m);
2158c65ebfc7SToomas Soome 
2159c65ebfc7SToomas Soome // Time constant (~= 260 hours ~= 10 days and 21 hours) used to set
2160c65ebfc7SToomas Soome // various time values to a point well into the future.
2161c65ebfc7SToomas Soome #define FutureTime   0x38000000
2162c65ebfc7SToomas Soome 
21634b22b933Srs struct mDNS_struct
21645ffb0c9bSToomas Soome {
21655ffb0c9bSToomas Soome     // Internal state fields. These hold the main internal state of mDNSCore;
21665ffb0c9bSToomas Soome     // the client layer needn't be concerned with them.
21675ffb0c9bSToomas Soome     // No fields need to be set up by the client prior to calling mDNS_Init();
21685ffb0c9bSToomas Soome     // all required data is passed as parameters to that function.
21695ffb0c9bSToomas Soome 
21705ffb0c9bSToomas Soome     mDNS_PlatformSupport *p;            // Pointer to platform-specific data of indeterminite size
2171cda73f64SToomas Soome     mDNSs32 NetworkChanged;
21725ffb0c9bSToomas Soome     mDNSBool CanReceiveUnicastOn5353;
21735ffb0c9bSToomas Soome     mDNSBool AdvertiseLocalAddresses;
21745ffb0c9bSToomas Soome     mDNSBool DivertMulticastAdvertisements; // from interfaces that do not advertise local addresses to local-only
21755ffb0c9bSToomas Soome     mStatus mDNSPlatformStatus;
21765ffb0c9bSToomas Soome     mDNSIPPort UnicastPort4;
21775ffb0c9bSToomas Soome     mDNSIPPort UnicastPort6;
21785ffb0c9bSToomas Soome     mDNSEthAddr PrimaryMAC;             // Used as unique host ID
21795ffb0c9bSToomas Soome     mDNSCallback *MainCallback;
21805ffb0c9bSToomas Soome     void         *MainContext;
21815ffb0c9bSToomas Soome 
21825ffb0c9bSToomas Soome     // For debugging: To catch and report locking failures
21835ffb0c9bSToomas Soome     mDNSu32 mDNS_busy;                  // Incremented between mDNS_Lock/mDNS_Unlock section
21845ffb0c9bSToomas Soome     mDNSu32 mDNS_reentrancy;            // Incremented when calling a client callback
21855ffb0c9bSToomas Soome     mDNSu8 lock_rrcache;                // For debugging: Set at times when these lists may not be modified
21865ffb0c9bSToomas Soome     mDNSu8 lock_Questions;
21875ffb0c9bSToomas Soome     mDNSu8 lock_Records;
21885ffb0c9bSToomas Soome 
21895ffb0c9bSToomas Soome     // Task Scheduling variables
21905ffb0c9bSToomas Soome     mDNSs32 timenow_adjust;             // Correction applied if we ever discover time went backwards
21915ffb0c9bSToomas Soome     mDNSs32 timenow;                    // The time that this particular activation of the mDNS code started
21925ffb0c9bSToomas Soome     mDNSs32 timenow_last;               // The time the last time we ran
21935ffb0c9bSToomas Soome     mDNSs32 NextScheduledEvent;         // Derived from values below
21945ffb0c9bSToomas Soome     mDNSs32 ShutdownTime;               // Set when we're shutting down; allows us to skip some unnecessary steps
21955ffb0c9bSToomas Soome     mDNSs32 SuppressSending;            // Don't send local-link mDNS packets during this time
21965ffb0c9bSToomas Soome     mDNSs32 NextCacheCheck;             // Next time to refresh cache record before it expires
21975ffb0c9bSToomas Soome     mDNSs32 NextScheduledQuery;         // Next time to send query in its exponential backoff sequence
21985ffb0c9bSToomas Soome     mDNSs32 NextScheduledProbe;         // Next time to probe for new authoritative record
21995ffb0c9bSToomas Soome     mDNSs32 NextScheduledResponse;      // Next time to send authoritative record(s) in responses
22005ffb0c9bSToomas Soome     mDNSs32 NextScheduledNATOp;         // Next time to send NAT-traversal packets
22015ffb0c9bSToomas Soome     mDNSs32 NextScheduledSPS;           // Next time to purge expiring Sleep Proxy records
22025ffb0c9bSToomas Soome     mDNSs32 NextScheduledKA;            // Next time to send Keepalive packets (SPS)
2203*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
2204c65ebfc7SToomas Soome     mDNSs32 NextBonjourDisableTime;     // Next time to leave multicast group if Bonjour on Demand is enabled
2205c65ebfc7SToomas Soome     mDNSu8 BonjourEnabled;              // Non zero if Bonjour is currently enabled by the Bonjour on Demand logic
2206*472cd20dSToomas Soome #endif
22075ffb0c9bSToomas Soome     mDNSs32 RandomQueryDelay;           // For de-synchronization of query packets on the wire
22085ffb0c9bSToomas Soome     mDNSu32 RandomReconfirmDelay;       // For de-synchronization of reconfirmation queries on the wire
22095ffb0c9bSToomas Soome     mDNSs32 PktNum;                     // Unique sequence number assigned to each received packet
22105ffb0c9bSToomas Soome     mDNSs32 MPktNum;                    // Unique sequence number assigned to each received Multicast packet
22115ffb0c9bSToomas Soome     mDNSu8 LocalRemoveEvents;           // Set if we may need to deliver remove events for local-only questions and/or local-only records
22125ffb0c9bSToomas Soome     mDNSu8 SleepState;                  // Set if we're sleeping
22135ffb0c9bSToomas Soome     mDNSu8 SleepSeqNum;                 // "Epoch number" of our current period of wakefulness
22145ffb0c9bSToomas Soome     mDNSu8 SystemWakeOnLANEnabled;      // Set if we want to register with a Sleep Proxy before going to sleep
22155ffb0c9bSToomas Soome     mDNSu8 SentSleepProxyRegistration;  // Set if we registered (or tried to register) with a Sleep Proxy
22165ffb0c9bSToomas Soome     mDNSu8 SystemSleepOnlyIfWakeOnLAN;  // Set if we may only sleep if we managed to register with a Sleep Proxy
22175ffb0c9bSToomas Soome     mDNSs32 AnnounceOwner;              // After waking from sleep, include OWNER option in packets until this time
22185ffb0c9bSToomas Soome     mDNSs32 DelaySleep;                 // To inhibit re-sleeping too quickly right after wake
22195ffb0c9bSToomas Soome     mDNSs32 SleepLimit;                 // Time window to allow deregistrations, etc.,
22205ffb0c9bSToomas Soome                                         // during which underying platform layer should inhibit system sleep
22215ffb0c9bSToomas Soome     mDNSs32 TimeSlept;                  // Time we went to sleep.
22225ffb0c9bSToomas Soome 
22235ffb0c9bSToomas Soome     mDNSs32 UnicastPacketsSent;         // Number of unicast packets sent.
22245ffb0c9bSToomas Soome     mDNSs32 MulticastPacketsSent;       // Number of multicast packets sent.
22255ffb0c9bSToomas Soome     mDNSs32 RemoteSubnet;               // Multicast packets received from outside our subnet.
22265ffb0c9bSToomas Soome 
22275ffb0c9bSToomas Soome     mDNSs32 NextScheduledSPRetry;       // Time next sleep proxy registration action is required.
22285ffb0c9bSToomas Soome                                         // Only valid if SleepLimit is nonzero and DelaySleep is zero.
22295ffb0c9bSToomas Soome 
22305ffb0c9bSToomas Soome     mDNSs32 NextScheduledStopTime;      // Next time to stop a question
22315ffb0c9bSToomas Soome 
2232c65ebfc7SToomas Soome     mDNSs32 NextBLEServiceTime;         // Next time to call the BLE discovery management layer.  Non zero when active.
22335ffb0c9bSToomas Soome 
22345ffb0c9bSToomas Soome     // These fields only required for mDNS Searcher...
22355ffb0c9bSToomas Soome     DNSQuestion *Questions;             // List of all registered questions, active and inactive
22365ffb0c9bSToomas Soome     DNSQuestion *NewQuestions;          // Fresh questions not yet answered from cache
22375ffb0c9bSToomas Soome     DNSQuestion *CurrentQuestion;       // Next question about to be examined in AnswerLocalQuestions()
22385ffb0c9bSToomas Soome     DNSQuestion *LocalOnlyQuestions;    // Questions with InterfaceID set to mDNSInterface_LocalOnly or mDNSInterface_P2P
22395ffb0c9bSToomas Soome     DNSQuestion *NewLocalOnlyQuestions; // Fresh local-only or P2P questions not yet answered
22405ffb0c9bSToomas Soome     DNSQuestion *RestartQuestion;       // Questions that are being restarted (stop followed by start)
22415ffb0c9bSToomas Soome     mDNSu32 rrcache_size;               // Total number of available cache entries
22425ffb0c9bSToomas Soome     mDNSu32 rrcache_totalused;          // Number of cache entries currently occupied
22435ffb0c9bSToomas Soome     mDNSu32 rrcache_totalused_unicast;  // Number of cache entries currently occupied by unicast
22445ffb0c9bSToomas Soome     mDNSu32 rrcache_active;             // Number of cache entries currently occupied by records that answer active questions
22455ffb0c9bSToomas Soome     mDNSu32 rrcache_report;
22465ffb0c9bSToomas Soome     CacheEntity *rrcache_free;
22475ffb0c9bSToomas Soome     CacheGroup *rrcache_hash[CACHE_HASH_SLOTS];
22485ffb0c9bSToomas Soome     mDNSs32 rrcache_nextcheck[CACHE_HASH_SLOTS];
22495ffb0c9bSToomas Soome 
22505ffb0c9bSToomas Soome     AuthHash rrauth;
22515ffb0c9bSToomas Soome 
22525ffb0c9bSToomas Soome     // Fields below only required for mDNS Responder...
22535ffb0c9bSToomas Soome     domainlabel nicelabel;              // Rich text label encoded using canonically precomposed UTF-8
22545ffb0c9bSToomas Soome     domainlabel hostlabel;              // Conforms to RFC 1034 "letter-digit-hyphen" ARPANET host name rules
22555ffb0c9bSToomas Soome     domainname MulticastHostname;       // Fully Qualified "dot-local" Host Name, e.g. "Foo.local."
2256*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
2257*472cd20dSToomas Soome     domainname RandomizedHostname;      // Randomized hostname to use for services involving AWDL interfaces. This is to
2258*472cd20dSToomas Soome                                         // avoid using a hostname derived from the device's name, which may contain the
2259*472cd20dSToomas Soome                                         // owner's real name, (e.g., "Steve's iPhone" -> "Steves-iPhone.local"), which is a
2260*472cd20dSToomas Soome                                         // privacy concern.
2261*472cd20dSToomas Soome     mDNSu32 AutoTargetAWDLIncludedCount;// Number of registered AWDL-included auto-target records.
2262*472cd20dSToomas Soome     mDNSu32 AutoTargetAWDLOnlyCount;    // Number of registered AWDL-only auto-target records.
2263*472cd20dSToomas Soome #endif
22645ffb0c9bSToomas Soome     UTF8str255 HIHardware;
22655ffb0c9bSToomas Soome     UTF8str255 HISoftware;
22665ffb0c9bSToomas Soome     AuthRecord DeviceInfo;
22675ffb0c9bSToomas Soome     AuthRecord *ResourceRecords;
22685ffb0c9bSToomas Soome     AuthRecord *DuplicateRecords;       // Records currently 'on hold' because they are duplicates of existing records
22695ffb0c9bSToomas Soome     AuthRecord *NewLocalRecords;        // Fresh AuthRecords (public) not yet delivered to our local-only questions
22705ffb0c9bSToomas Soome     AuthRecord *CurrentRecord;          // Next AuthRecord about to be examined
22715ffb0c9bSToomas Soome     mDNSBool NewLocalOnlyRecords;       // Fresh AuthRecords (local only) not yet delivered to our local questions
22725ffb0c9bSToomas Soome     NetworkInterfaceInfo *HostInterfaces;
22735ffb0c9bSToomas Soome     mDNSs32 ProbeFailTime;
22745ffb0c9bSToomas Soome     mDNSu32 NumFailedProbes;
22755ffb0c9bSToomas Soome     mDNSs32 SuppressProbes;
2276c65ebfc7SToomas Soome     Platform_t mDNS_plat;               // Why is this here in the “only required for mDNS Responder” section? -- SC
22775ffb0c9bSToomas Soome 
22785ffb0c9bSToomas Soome     // Unicast-specific data
22795ffb0c9bSToomas Soome     mDNSs32 NextuDNSEvent;                  // uDNS next event
22805ffb0c9bSToomas Soome     mDNSs32 NextSRVUpdate;                  // Time to perform delayed update
22815ffb0c9bSToomas Soome 
2282*472cd20dSToomas Soome #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
22835ffb0c9bSToomas Soome     DNSServer        *DNSServers;           // list of DNS servers
2284*472cd20dSToomas Soome #endif
22855ffb0c9bSToomas Soome     McastResolver    *McastResolvers;       // list of Mcast Resolvers
22865ffb0c9bSToomas Soome 
22875ffb0c9bSToomas Soome     mDNSAddr Router;
22885ffb0c9bSToomas Soome     mDNSAddr AdvertisedV4;                  // IPv4 address pointed to by hostname
22895ffb0c9bSToomas Soome     mDNSAddr AdvertisedV6;                  // IPv6 address pointed to by hostname
22905ffb0c9bSToomas Soome 
22915ffb0c9bSToomas Soome     DomainAuthInfo   *AuthInfoList;         // list of domains requiring authentication for updates
22925ffb0c9bSToomas Soome 
22935ffb0c9bSToomas Soome     DNSQuestion ReverseMap;                 // Reverse-map query to find static hostname for service target
22945ffb0c9bSToomas Soome     DNSQuestion AutomaticBrowseDomainQ;
22955ffb0c9bSToomas Soome     domainname StaticHostname;              // Current answer to reverse-map query
22965ffb0c9bSToomas Soome     domainname FQDN;
22975ffb0c9bSToomas Soome     HostnameInfo     *Hostnames;            // List of registered hostnames + hostname metadata
22985ffb0c9bSToomas Soome 
22995ffb0c9bSToomas Soome     mDNSu32 WABBrowseQueriesCount;          // Number of WAB Browse domain enumeration queries (b, db) callers
23005ffb0c9bSToomas Soome     mDNSu32 WABLBrowseQueriesCount;         // Number of legacy WAB Browse domain enumeration queries (lb) callers
23015ffb0c9bSToomas Soome     mDNSu32 WABRegQueriesCount;             // Number of WAB Registration domain enumeration queries (r, dr) callers
23025ffb0c9bSToomas Soome     mDNSu8 SearchDomainsHash[MD5_LEN];
23035ffb0c9bSToomas Soome 
23045ffb0c9bSToomas Soome     // NAT-Traversal fields
23055ffb0c9bSToomas Soome     NATTraversalInfo LLQNAT;                    // Single shared NAT Traversal to receive inbound LLQ notifications
23065ffb0c9bSToomas Soome     NATTraversalInfo *NATTraversals;
23075ffb0c9bSToomas Soome     NATTraversalInfo *CurrentNATTraversal;
23085ffb0c9bSToomas Soome     mDNSs32 retryIntervalGetAddr;               // delta between time sent and retry for NAT-PMP & UPnP/IGD external address request
23095ffb0c9bSToomas Soome     mDNSs32 retryGetAddr;                       // absolute time when we retry for NAT-PMP & UPnP/IGD external address request
23105ffb0c9bSToomas Soome     mDNSv4Addr ExtAddress;                      // the external address discovered via NAT-PMP or UPnP/IGD
23115ffb0c9bSToomas Soome     mDNSu32 PCPNonce[3];                        // the nonce if using PCP
23125ffb0c9bSToomas Soome 
23135ffb0c9bSToomas Soome     UDPSocket        *NATMcastRecvskt;          // For receiving PCP & NAT-PMP announcement multicasts from router on port 5350
23145ffb0c9bSToomas Soome     mDNSu32 LastNATupseconds;                   // NAT engine uptime in seconds, from most recent NAT packet
23155ffb0c9bSToomas Soome     mDNSs32 LastNATReplyLocalTime;              // Local time in ticks when most recent NAT packet was received
23165ffb0c9bSToomas Soome     mDNSu16 LastNATMapResultCode;               // Most recent error code for mappings
23175ffb0c9bSToomas Soome 
23185ffb0c9bSToomas Soome     tcpLNTInfo tcpAddrInfo;                     // legacy NAT traversal TCP connection info for external address
23195ffb0c9bSToomas Soome     tcpLNTInfo tcpDeviceInfo;                   // legacy NAT traversal TCP connection info for device info
23205ffb0c9bSToomas Soome     tcpLNTInfo       *tcpInfoUnmapList;         // list of pending unmap requests
23215ffb0c9bSToomas Soome     mDNSInterfaceID UPnPInterfaceID;
23225ffb0c9bSToomas Soome     UDPSocket        *SSDPSocket;               // For SSDP request/response
23235ffb0c9bSToomas Soome     mDNSBool SSDPWANPPPConnection;              // whether we should send the SSDP query for WANIPConnection or WANPPPConnection
23245ffb0c9bSToomas Soome     mDNSIPPort UPnPRouterPort;                  // port we send discovery messages to
23255ffb0c9bSToomas Soome     mDNSIPPort UPnPSOAPPort;                    // port we send SOAP messages to
2326c65ebfc7SToomas Soome     char             *UPnPRouterURL;            // router's URL string
23275ffb0c9bSToomas Soome     mDNSBool UPnPWANPPPConnection;              // whether we're using WANIPConnection or WANPPPConnection
2328c65ebfc7SToomas Soome     char             *UPnPSOAPURL;              // router's SOAP control URL string
2329c65ebfc7SToomas Soome     char             *UPnPRouterAddressString;  // holds both the router's address and port
2330c65ebfc7SToomas Soome     char             *UPnPSOAPAddressString;    // holds both address and port for SOAP messages
2331c65ebfc7SToomas Soome 
2332c65ebfc7SToomas Soome     // DNS Push Notification fields
2333c65ebfc7SToomas Soome     DNSPushNotificationServer *DNSPushServers;  // DNS Push Notification Servers
2334c65ebfc7SToomas Soome     DNSPushNotificationZone   *DNSPushZones;
23355ffb0c9bSToomas Soome 
23365ffb0c9bSToomas Soome     // Sleep Proxy client fields
23375ffb0c9bSToomas Soome     AuthRecord *SPSRRSet;                       // To help the client keep track of the records registered with the sleep proxy
23385ffb0c9bSToomas Soome 
23395ffb0c9bSToomas Soome     // Sleep Proxy Server fields
23405ffb0c9bSToomas Soome     mDNSu8 SPSType;                             // 0 = off, 10-99 encodes desirability metric
23415ffb0c9bSToomas Soome     mDNSu8 SPSPortability;                      // 10-99
23425ffb0c9bSToomas Soome     mDNSu8 SPSMarginalPower;                    // 10-99
23435ffb0c9bSToomas Soome     mDNSu8 SPSTotalPower;                       // 10-99
23445ffb0c9bSToomas Soome     mDNSu8 SPSFeatureFlags;                     // Features supported. Currently 1 = TCP KeepAlive supported.
23455ffb0c9bSToomas Soome     mDNSu8 SPSState;                            // 0 = off, 1 = running, 2 = shutting down, 3 = suspended during sleep
23465ffb0c9bSToomas Soome     mDNSInterfaceID SPSProxyListChanged;
23475ffb0c9bSToomas Soome     UDPSocket        *SPSSocket;
23485ffb0c9bSToomas Soome #ifndef SPC_DISABLED
23495ffb0c9bSToomas Soome     ServiceRecordSet SPSRecords;
23505ffb0c9bSToomas Soome #endif
23515ffb0c9bSToomas Soome     mDNSQuestionCallback *SPSBrowseCallback;    // So the platform layer can do something useful with SPS browse results
23525ffb0c9bSToomas Soome     int ProxyRecords;                           // Total number of records we're holding as proxy
23535ffb0c9bSToomas Soome     #define           MAX_PROXY_RECORDS 10000   /* DOS protection: 400 machines at 25 records each */
23545ffb0c9bSToomas Soome 
2355*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, WEB_CONTENT_FILTER)
2356*472cd20dSToomas Soome     WCFConnection    *WCF;
23575ffb0c9bSToomas Soome #endif
23585ffb0c9bSToomas Soome     // DNS Proxy fields
23595ffb0c9bSToomas Soome     mDNSu32 dp_ipintf[MaxIp];                   // input interface index list from the DNS Proxy Client
23605ffb0c9bSToomas Soome     mDNSu32 dp_opintf;                          // output interface index from the DNS Proxy Client
23615ffb0c9bSToomas Soome 
23625ffb0c9bSToomas Soome     int             notifyToken;
2363cda73f64SToomas Soome     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
23645ffb0c9bSToomas Soome     mDNSu32         AutoTargetServices;         // # of services that have AutoTarget set
2365c65ebfc7SToomas Soome 
2366*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, BONJOUR_ON_DEMAND)
2367c65ebfc7SToomas Soome     // Counters used in Bonjour on Demand logic.
2368c65ebfc7SToomas Soome     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.)
2369c65ebfc7SToomas Soome     mDNSu32         NumAllInterfaceQuestions;   // Right now we count *all* multicast questions here. Later we may want to change to count interface-specific questions separately.
2370*472cd20dSToomas Soome #endif
2371c65ebfc7SToomas Soome 
23725ffb0c9bSToomas Soome     mDNSStatistics   mDNSStats;
23735ffb0c9bSToomas Soome 
23745ffb0c9bSToomas Soome     // Fixed storage, to avoid creating large objects on the stack
23755ffb0c9bSToomas Soome     // The imsg is declared as a union with a pointer type to enforce CPU-appropriate alignment
23765ffb0c9bSToomas Soome     union { DNSMessage m; void *p; } imsg;  // Incoming message received from wire
23775ffb0c9bSToomas Soome     DNSMessage omsg;                        // Outgoing message we're building
23785ffb0c9bSToomas Soome     LargeCacheRecord rec;                   // Resource Record extracted from received message
2379*472cd20dSToomas Soome 
2380*472cd20dSToomas Soome #ifndef MaxMsg
2381*472cd20dSToomas Soome     #define MaxMsg 512
2382*472cd20dSToomas Soome #endif
2383*472cd20dSToomas Soome     char MsgBuffer[MaxMsg];                 // Temp storage used while building error log messages (keep at end of struct)
23845ffb0c9bSToomas Soome };
23855ffb0c9bSToomas Soome 
23865ffb0c9bSToomas Soome #define FORALL_CACHERECORDS(SLOT,CG,CR)                           \
2387cda73f64SToomas Soome     for ((SLOT) = 0; (SLOT) < CACHE_HASH_SLOTS; (SLOT)++)         \
2388cda73f64SToomas Soome         for ((CG)=m->rrcache_hash[(SLOT)]; (CG); (CG)=(CG)->next) \
23895ffb0c9bSToomas Soome             for ((CR) = (CG)->members; (CR); (CR)=(CR)->next)
23904b22b933Srs 
23914b22b933Srs // ***************************************************************************
23924b22b933Srs #if 0
23935ffb0c9bSToomas Soome #pragma mark -
23944b22b933Srs #pragma mark - Useful Static Constants
23954b22b933Srs #endif
23964b22b933Srs 
23975ffb0c9bSToomas Soome extern const mDNSInterfaceID mDNSInterface_Any;             // Zero
23985ffb0c9bSToomas Soome extern const mDNSInterfaceID mDNSInterface_LocalOnly;       // Special value
23995ffb0c9bSToomas Soome extern const mDNSInterfaceID mDNSInterfaceMark;             // Special value
24005ffb0c9bSToomas Soome extern const mDNSInterfaceID mDNSInterface_P2P;             // Special value
24015ffb0c9bSToomas Soome extern const mDNSInterfaceID uDNSInterfaceMark;             // Special value
2402c65ebfc7SToomas Soome extern const mDNSInterfaceID mDNSInterface_BLE;             // Special value
2403c65ebfc7SToomas Soome 
2404*472cd20dSToomas Soome #define LocalOnlyOrP2PInterface(INTERFACE)  (((INTERFACE) == mDNSInterface_LocalOnly) || ((INTERFACE) == mDNSInterface_P2P) || ((INTERFACE) == mDNSInterface_BLE))
24055ffb0c9bSToomas Soome 
24065ffb0c9bSToomas Soome extern const mDNSIPPort DiscardPort;
24075ffb0c9bSToomas Soome extern const mDNSIPPort SSHPort;
24085ffb0c9bSToomas Soome extern const mDNSIPPort UnicastDNSPort;
24095ffb0c9bSToomas Soome extern const mDNSIPPort SSDPPort;
24105ffb0c9bSToomas Soome extern const mDNSIPPort IPSECPort;
24115ffb0c9bSToomas Soome extern const mDNSIPPort NSIPCPort;
24125ffb0c9bSToomas Soome extern const mDNSIPPort NATPMPAnnouncementPort;
24135ffb0c9bSToomas Soome extern const mDNSIPPort NATPMPPort;
24145ffb0c9bSToomas Soome extern const mDNSIPPort DNSEXTPort;
24155ffb0c9bSToomas Soome extern const mDNSIPPort MulticastDNSPort;
24165ffb0c9bSToomas Soome extern const mDNSIPPort LoopbackIPCPort;
24175ffb0c9bSToomas Soome extern const mDNSIPPort PrivateDNSPort;
24185ffb0c9bSToomas Soome 
24195ffb0c9bSToomas Soome extern const OwnerOptData zeroOwner;
24205ffb0c9bSToomas Soome 
24215ffb0c9bSToomas Soome extern const mDNSIPPort zeroIPPort;
24225ffb0c9bSToomas Soome extern const mDNSv4Addr zerov4Addr;
24235ffb0c9bSToomas Soome extern const mDNSv6Addr zerov6Addr;
24245ffb0c9bSToomas Soome extern const mDNSEthAddr zeroEthAddr;
24255ffb0c9bSToomas Soome extern const mDNSv4Addr onesIPv4Addr;
24265ffb0c9bSToomas Soome extern const mDNSv6Addr onesIPv6Addr;
24275ffb0c9bSToomas Soome extern const mDNSEthAddr onesEthAddr;
24285ffb0c9bSToomas Soome extern const mDNSAddr zeroAddr;
24295ffb0c9bSToomas Soome 
24305ffb0c9bSToomas Soome extern const mDNSv4Addr AllDNSAdminGroup;
24315ffb0c9bSToomas Soome extern const mDNSv4Addr AllHosts_v4;
24325ffb0c9bSToomas Soome extern const mDNSv6Addr AllHosts_v6;
24335ffb0c9bSToomas Soome extern const mDNSv6Addr NDP_prefix;
24345ffb0c9bSToomas Soome extern const mDNSEthAddr AllHosts_v6_Eth;
24355ffb0c9bSToomas Soome extern const mDNSAddr AllDNSLinkGroup_v4;
24365ffb0c9bSToomas Soome extern const mDNSAddr AllDNSLinkGroup_v6;
24374b22b933Srs 
24384b22b933Srs extern const mDNSOpaque16 zeroID;
24395ffb0c9bSToomas Soome extern const mDNSOpaque16 onesID;
24404b22b933Srs extern const mDNSOpaque16 QueryFlags;
24414b22b933Srs extern const mDNSOpaque16 uQueryFlags;
24424b22b933Srs extern const mDNSOpaque16 ResponseFlags;
24434b22b933Srs extern const mDNSOpaque16 UpdateReqFlags;
24444b22b933Srs extern const mDNSOpaque16 UpdateRespFlags;
2445c65ebfc7SToomas Soome extern const mDNSOpaque16 SubscribeFlags;
2446c65ebfc7SToomas Soome extern const mDNSOpaque16 UnSubscribeFlags;
2447*472cd20dSToomas Soome extern const mDNSOpaque16 uDNSSecQueryFlags;
24484b22b933Srs 
24495ffb0c9bSToomas Soome extern const mDNSOpaque64 zeroOpaque64;
2450c65ebfc7SToomas Soome extern const mDNSOpaque128 zeroOpaque128;
24515ffb0c9bSToomas Soome 
24525ffb0c9bSToomas Soome extern mDNSBool StrictUnicastOrdering;
24535ffb0c9bSToomas Soome 
24545ffb0c9bSToomas Soome #define localdomain           (*(const domainname *)"\x5" "local")
24555ffb0c9bSToomas Soome #define DeviceInfoName        (*(const domainname *)"\xC" "_device-info" "\x4" "_tcp")
24565ffb0c9bSToomas Soome #define LocalDeviceInfoName   (*(const domainname *)"\xC" "_device-info" "\x4" "_tcp" "\x5" "local")
24575ffb0c9bSToomas Soome #define SleepProxyServiceType (*(const domainname *)"\xC" "_sleep-proxy" "\x4" "_udp")
24585ffb0c9bSToomas Soome 
24594b22b933Srs // ***************************************************************************
24604b22b933Srs #if 0
24615ffb0c9bSToomas Soome #pragma mark -
24624b22b933Srs #pragma mark - Inline functions
24634b22b933Srs #endif
24644b22b933Srs 
24654b22b933Srs #if (defined(_MSC_VER))
24665ffb0c9bSToomas Soome     #define mDNSinline static __inline
24674b22b933Srs #elif ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9)))
24685ffb0c9bSToomas Soome     #define mDNSinline static inline
24693b436d06SToomas Soome #else
24703b436d06SToomas Soome     #define mDNSinline static inline
24714b22b933Srs #endif
24724b22b933Srs 
24734b22b933Srs // If we're not doing inline functions, then this header needs to have the extern declarations
24744b22b933Srs #if !defined(mDNSinline)
2475*472cd20dSToomas Soome #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
2476*472cd20dSToomas Soome extern int          CountOfUnicastDNSServers(mDNS *const m);
2477*472cd20dSToomas Soome #endif
24784b22b933Srs extern mDNSs32      NonZeroTime(mDNSs32 t);
24794b22b933Srs extern mDNSu16      mDNSVal16(mDNSOpaque16 x);
24804b22b933Srs extern mDNSOpaque16 mDNSOpaque16fromIntVal(mDNSu16 v);
24814b22b933Srs #endif
24824b22b933Srs 
24834b22b933Srs // If we're compiling the particular C file that instantiates our inlines, then we
24844b22b933Srs // define "mDNSinline" (to empty string) so that we generate code in the following section
24854b22b933Srs #if (!defined(mDNSinline) && mDNS_InstantiateInlines)
24864b22b933Srs #define mDNSinline
24874b22b933Srs #endif
24884b22b933Srs 
24894b22b933Srs #ifdef mDNSinline
24904b22b933Srs 
2491*472cd20dSToomas Soome #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
CountOfUnicastDNSServers(mDNS * const m)2492*472cd20dSToomas Soome mDNSinline int CountOfUnicastDNSServers(mDNS *const m)
2493*472cd20dSToomas Soome {
2494*472cd20dSToomas Soome     int count = 0;
2495*472cd20dSToomas Soome     DNSServer *ptr = m->DNSServers;
2496*472cd20dSToomas Soome     while(ptr) { if(!(ptr->flags & DNSServerFlag_Delete)) count++; ptr = ptr->next; }
2497*472cd20dSToomas Soome     return (count);
2498*472cd20dSToomas Soome }
2499*472cd20dSToomas Soome #endif
2500*472cd20dSToomas Soome 
NonZeroTime(mDNSs32 t)25015ffb0c9bSToomas Soome mDNSinline mDNSs32 NonZeroTime(mDNSs32 t) { if (t) return(t);else return(1);}
25024b22b933Srs 
mDNSVal16(mDNSOpaque16 x)25034b22b933Srs mDNSinline mDNSu16 mDNSVal16(mDNSOpaque16 x) { return((mDNSu16)((mDNSu16)x.b[0] <<  8 | (mDNSu16)x.b[1])); }
25044b22b933Srs 
mDNSOpaque16fromIntVal(mDNSu16 v)25054b22b933Srs mDNSinline mDNSOpaque16 mDNSOpaque16fromIntVal(mDNSu16 v)
25065ffb0c9bSToomas Soome {
25075ffb0c9bSToomas Soome     mDNSOpaque16 x;
25085ffb0c9bSToomas Soome     x.b[0] = (mDNSu8)(v >> 8);
25095ffb0c9bSToomas Soome     x.b[1] = (mDNSu8)(v & 0xFF);
25105ffb0c9bSToomas Soome     return(x);
25115ffb0c9bSToomas Soome }
25124b22b933Srs 
25134b22b933Srs #endif
2514*472cd20dSToomas Soome 
25154b22b933Srs // ***************************************************************************
25164b22b933Srs #if 0
25175ffb0c9bSToomas Soome #pragma mark -
25184b22b933Srs #pragma mark - Main Client Functions
25194b22b933Srs #endif
25204b22b933Srs 
25214b22b933Srs // Every client should call mDNS_Init, passing in storage for the mDNS object and the mDNS_PlatformSupport object.
25224b22b933Srs //
25234b22b933Srs // Clients that are only advertising services should use mDNS_Init_NoCache and mDNS_Init_ZeroCacheSize.
2524c65ebfc7SToomas Soome // Clients that plan to perform queries (mDNS_StartQuery, mDNS_StartBrowse, etc.)
25254b22b933Srs // need to provide storage for the resource record cache, or the query calls will return 'mStatus_NoCache'.
25264b22b933Srs // The rrcachestorage parameter is the address of memory for the resource record cache, and
25274b22b933Srs // the rrcachesize parameter is the number of entries in the CacheRecord array passed in.
25284b22b933Srs // (i.e. the size of the cache memory needs to be sizeof(CacheRecord) * rrcachesize).
25294b22b933Srs // OS X 10.3 Panther uses an initial cache size of 64 entries, and then mDNSCore sends an
25304b22b933Srs // mStatus_GrowCache message if it needs more.
25314b22b933Srs //
25324b22b933Srs // Most clients should use mDNS_Init_AdvertiseLocalAddresses. This causes mDNSCore to automatically
25334b22b933Srs // create the correct address records for all the hosts interfaces. If you plan to advertise
25344b22b933Srs // services being offered by the local machine, this is almost always what you want.
25354b22b933Srs // There are two cases where you might use mDNS_Init_DontAdvertiseLocalAddresses:
25364b22b933Srs // 1. A client-only device, that browses for services but doesn't advertise any of its own.
25374b22b933Srs // 2. A proxy-registration service, that advertises services being offered by other machines, and takes
25384b22b933Srs //    the appropriate steps to manually create the correct address records for those other machines.
25394b22b933Srs // In principle, a proxy-like registration service could manually create address records for its own machine too,
25404b22b933Srs // but this would be pointless extra effort when using mDNS_Init_AdvertiseLocalAddresses does that for you.
25414b22b933Srs //
25425ffb0c9bSToomas Soome // Note that a client-only device that wishes to prohibit multicast advertisements (e.g. from
25435ffb0c9bSToomas Soome // higher-layer API calls) must also set DivertMulticastAdvertisements in the mDNS structure and
25445ffb0c9bSToomas Soome // advertise local address(es) on a loopback interface.
25455ffb0c9bSToomas Soome //
25464b22b933Srs // When mDNS has finished setting up the client's callback is called
25474b22b933Srs // A client can also spin and poll the mDNSPlatformStatus field to see when it changes from mStatus_Waiting to mStatus_NoError
25484b22b933Srs //
25495ffb0c9bSToomas Soome // Call mDNS_StartExit to tidy up before exiting
25505ffb0c9bSToomas Soome // Because exiting may be an asynchronous process (e.g. if unicast records need to be deregistered)
25515ffb0c9bSToomas Soome // client layer may choose to wait until mDNS_ExitNow() returns true before calling mDNS_FinalExit().
25524b22b933Srs //
25534b22b933Srs // Call mDNS_Register with a completed AuthRecord object to register a resource record
25544b22b933Srs // If the resource record type is kDNSRecordTypeUnique (or kDNSknownunique) then if a conflicting resource record is discovered,
25554b22b933Srs // the resource record's mDNSRecordCallback will be called with error code mStatus_NameConflict. The callback should deregister
25564b22b933Srs // the record, and may then try registering the record again after picking a new name (e.g. by automatically appending a number).
25574b22b933Srs // Following deregistration, the RecordCallback will be called with result mStatus_MemFree to signal that it is safe to deallocate
25584b22b933Srs // the record's storage (memory must be freed asynchronously to allow for goodbye packets and dynamic update deregistration).
25594b22b933Srs //
25604b22b933Srs // Call mDNS_StartQuery to initiate a query. mDNS will proceed to issue Multicast DNS query packets, and any time a response
25614b22b933Srs // is received containing a record which matches the question, the DNSQuestion's mDNSAnswerCallback function will be called
25624b22b933Srs // Call mDNS_StopQuery when no more answers are required
25634b22b933Srs //
25644b22b933Srs // Care should be taken on multi-threaded or interrupt-driven environments.
25654b22b933Srs // The main mDNS routines call mDNSPlatformLock() on entry and mDNSPlatformUnlock() on exit;
25664b22b933Srs // each platform layer needs to implement these appropriately for its respective platform.
25674b22b933Srs // For example, if the support code on a particular platform implements timer callbacks at interrupt time, then
25684b22b933Srs // mDNSPlatformLock/Unlock need to disable interrupts or do similar concurrency control to ensure that the mDNS
25694b22b933Srs // code is not entered by an interrupt-time timer callback while in the middle of processing a client call.
25704b22b933Srs 
25714b22b933Srs extern mStatus mDNS_Init      (mDNS *const m, mDNS_PlatformSupport *const p,
25725ffb0c9bSToomas Soome                                CacheEntity *rrcachestorage, mDNSu32 rrcachesize,
25735ffb0c9bSToomas Soome                                mDNSBool AdvertiseLocalAddresses,
25745ffb0c9bSToomas Soome                                mDNSCallback *Callback, void *Context);
25754b22b933Srs // See notes above on use of NoCache/ZeroCacheSize
25764b22b933Srs #define mDNS_Init_NoCache                     mDNSNULL
25774b22b933Srs #define mDNS_Init_ZeroCacheSize               0
25784b22b933Srs // See notes above on use of Advertise/DontAdvertiseLocalAddresses
25794b22b933Srs #define mDNS_Init_AdvertiseLocalAddresses     mDNStrue
25804b22b933Srs #define mDNS_Init_DontAdvertiseLocalAddresses mDNSfalse
25814b22b933Srs #define mDNS_Init_NoInitCallback              mDNSNULL
25824b22b933Srs #define mDNS_Init_NoInitCallbackContext       mDNSNULL
25834b22b933Srs 
25845ffb0c9bSToomas Soome extern void    mDNS_ConfigChanged(mDNS *const m);
25854b22b933Srs extern void    mDNS_GrowCache (mDNS *const m, CacheEntity *storage, mDNSu32 numrecords);
25865ffb0c9bSToomas Soome extern void    mDNS_StartExit (mDNS *const m);
25875ffb0c9bSToomas Soome extern void    mDNS_FinalExit (mDNS *const m);
25885ffb0c9bSToomas Soome #define mDNS_Close(m) do { mDNS_StartExit(m); mDNS_FinalExit(m); } while(0)
25895ffb0c9bSToomas Soome #define mDNS_ExitNow(m, now) ((now) - (m)->ShutdownTime >= 0 || (!(m)->ResourceRecords))
25905ffb0c9bSToomas Soome 
25914b22b933Srs extern mDNSs32 mDNS_Execute   (mDNS *const m);
25924b22b933Srs 
25934b22b933Srs extern mStatus mDNS_Register  (mDNS *const m, AuthRecord *const rr);
25944b22b933Srs extern mStatus mDNS_Update    (mDNS *const m, AuthRecord *const rr, mDNSu32 newttl,
25955ffb0c9bSToomas Soome                                const mDNSu16 newrdlength, RData *const newrdata, mDNSRecordUpdateCallback *Callback);
25964b22b933Srs extern mStatus mDNS_Deregister(mDNS *const m, AuthRecord *const rr);
25974b22b933Srs 
25984b22b933Srs extern mStatus mDNS_StartQuery(mDNS *const m, DNSQuestion *const question);
25994b22b933Srs extern mStatus mDNS_StopQuery (mDNS *const m, DNSQuestion *const question);
26005ffb0c9bSToomas Soome extern mStatus mDNS_StopQueryWithRemoves(mDNS *const m, DNSQuestion *const question);
26014b22b933Srs extern mStatus mDNS_Reconfirm (mDNS *const m, CacheRecord *const cacherr);
26025ffb0c9bSToomas Soome extern mStatus mDNS_Reconfirm_internal(mDNS *const m, CacheRecord *const rr, mDNSu32 interval);
26034b22b933Srs extern mStatus mDNS_ReconfirmByValue(mDNS *const m, ResourceRecord *const rr);
26045ffb0c9bSToomas Soome extern void    mDNS_PurgeCacheResourceRecord(mDNS *const m, CacheRecord *rr);
26054b22b933Srs extern mDNSs32 mDNS_TimeNow(const mDNS *const m);
26064b22b933Srs 
26075ffb0c9bSToomas Soome extern mStatus mDNS_StartNATOperation(mDNS *const m, NATTraversalInfo *traversal);
26085ffb0c9bSToomas Soome extern mStatus mDNS_StopNATOperation(mDNS *const m, NATTraversalInfo *traversal);
26095ffb0c9bSToomas Soome extern mStatus mDNS_StopNATOperation_internal(mDNS *m, NATTraversalInfo *traversal);
26105ffb0c9bSToomas Soome 
26115ffb0c9bSToomas Soome extern DomainAuthInfo *GetAuthInfoForName(mDNS *m, const domainname *const name);
26125ffb0c9bSToomas Soome 
26135ffb0c9bSToomas Soome extern void    mDNS_UpdateAllowSleep(mDNS *const m);
26145ffb0c9bSToomas Soome 
26154b22b933Srs // ***************************************************************************
26164b22b933Srs #if 0
26175ffb0c9bSToomas Soome #pragma mark -
26184b22b933Srs #pragma mark - Platform support functions that are accessible to the client layer too
26194b22b933Srs #endif
26204b22b933Srs 
26215ffb0c9bSToomas Soome extern mDNSs32 mDNSPlatformOneSecond;
26224b22b933Srs 
26234b22b933Srs // ***************************************************************************
26244b22b933Srs #if 0
26255ffb0c9bSToomas Soome #pragma mark -
26264b22b933Srs #pragma mark - General utility and helper functions
26274b22b933Srs #endif
26284b22b933Srs 
26295ffb0c9bSToomas Soome // mDNS_Dereg_normal is used for most calls to mDNS_Deregister_internal
26305ffb0c9bSToomas Soome // mDNS_Dereg_rapid is used to send one goodbye instead of three, when we want the memory available for reuse sooner
26315ffb0c9bSToomas Soome // mDNS_Dereg_conflict is used to indicate that this record is being forcibly deregistered because of a conflict
26325ffb0c9bSToomas Soome // mDNS_Dereg_repeat is used when cleaning up, for records that may have already been forcibly deregistered
26335ffb0c9bSToomas Soome typedef enum { mDNS_Dereg_normal, mDNS_Dereg_rapid, mDNS_Dereg_conflict, mDNS_Dereg_repeat } mDNS_Dereg_type;
26345ffb0c9bSToomas Soome 
26354b22b933Srs // mDNS_RegisterService is a single call to register the set of resource records associated with a given named service.
26364b22b933Srs //
26374b22b933Srs //
26384b22b933Srs // mDNS_AddRecordToService adds an additional record to a Service Record Set.  This record may be deregistered
26394b22b933Srs // via mDNS_RemoveRecordFromService, or by deregistering the service.  mDNS_RemoveRecordFromService is passed a
26404b22b933Srs // callback to free the memory associated with the extra RR when it is safe to do so.  The ExtraResourceRecord
26414b22b933Srs // object can be found in the record's context pointer.
26425ffb0c9bSToomas Soome 
26434b22b933Srs // mDNS_GetBrowseDomains is a special case of the mDNS_StartQuery call, where the resulting answers
26444b22b933Srs // are a list of PTR records indicating (in the rdata) domains that are recommended for browsing.
26454b22b933Srs // After getting the list of domains to browse, call mDNS_StopQuery to end the search.
26464b22b933Srs // mDNS_GetDefaultBrowseDomain returns the name of the domain that should be highlighted by default.
26474b22b933Srs //
26484b22b933Srs // mDNS_GetRegistrationDomains and mDNS_GetDefaultRegistrationDomain are the equivalent calls to get the list
26494b22b933Srs // of one or more domains that should be offered to the user as choices for where they may register their service,
26504b22b933Srs // and the default domain in which to register in the case where the user has made no selection.
26514b22b933Srs 
26524b22b933Srs extern void    mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mDNSInterfaceID InterfaceID,
26535ffb0c9bSToomas Soome                                         mDNSu16 rrtype, mDNSu32 ttl, mDNSu8 RecordType, AuthRecType artype, mDNSRecordCallback Callback, void *Context);
26545ffb0c9bSToomas Soome 
26554b22b933Srs extern mStatus mDNS_RegisterService  (mDNS *const m, ServiceRecordSet *sr,
26565ffb0c9bSToomas Soome                                       const domainlabel *const name, const domainname *const type, const domainname *const domain,
26573b436d06SToomas Soome                                       const domainname *const host, mDNSIPPort port, RData *txtrdata, const mDNSu8 txtinfo[], mDNSu16 txtlen,
26585ffb0c9bSToomas Soome                                       AuthRecord *SubTypes, mDNSu32 NumSubTypes,
26595ffb0c9bSToomas Soome                                       mDNSInterfaceID InterfaceID, mDNSServiceCallback Callback, void *Context, mDNSu32 flags);
26605ffb0c9bSToomas Soome extern mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra, RData *rdata, mDNSu32 ttl,  mDNSu32 flags);
26614b22b933Srs extern mStatus mDNS_RemoveRecordFromService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra, mDNSRecordCallback MemFreeCallback, void *Context);
26624b22b933Srs extern mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordSet *const sr, const domainlabel *newname);
26635ffb0c9bSToomas Soome extern mStatus mDNS_DeregisterService_drt(mDNS *const m, ServiceRecordSet *sr, mDNS_Dereg_type drt);
26645ffb0c9bSToomas Soome #define mDNS_DeregisterService(M,S) mDNS_DeregisterService_drt((M), (S), mDNS_Dereg_normal)
26654b22b933Srs 
26664b22b933Srs extern mStatus mDNS_RegisterNoSuchService(mDNS *const m, AuthRecord *const rr,
26675ffb0c9bSToomas Soome                                           const domainlabel *const name, const domainname *const type, const domainname *const domain,
26685ffb0c9bSToomas Soome                                           const domainname *const host,
26695ffb0c9bSToomas Soome                                           const mDNSInterfaceID InterfaceID, mDNSRecordCallback Callback, void *Context, mDNSu32 flags);
26704b22b933Srs #define        mDNS_DeregisterNoSuchService mDNS_Deregister
26714b22b933Srs 
26725ffb0c9bSToomas Soome extern void mDNS_SetupQuestion(DNSQuestion *const q, const mDNSInterfaceID InterfaceID, const domainname *const name,
26735ffb0c9bSToomas Soome                                const mDNSu16 qtype, mDNSQuestionCallback *const callback, void *const context);
26745ffb0c9bSToomas Soome 
26754b22b933Srs extern mStatus mDNS_StartBrowse(mDNS *const m, DNSQuestion *const question,
2676*472cd20dSToomas Soome                                 const domainname *const srv, const domainname *const domain,
26775ffb0c9bSToomas Soome                                 const mDNSInterfaceID InterfaceID, mDNSu32 flags,
26785ffb0c9bSToomas Soome                                 mDNSBool ForceMCast, mDNSBool useBackgroundTrafficClass,
26795ffb0c9bSToomas Soome                                 mDNSQuestionCallback *Callback, void *Context);
26804b22b933Srs #define        mDNS_StopBrowse mDNS_StopQuery
26814b22b933Srs 
26824b22b933Srs 
26834b22b933Srs typedef enum
26845ffb0c9bSToomas Soome {
26855ffb0c9bSToomas Soome     mDNS_DomainTypeBrowse              = 0,
26865ffb0c9bSToomas Soome     mDNS_DomainTypeBrowseDefault       = 1,
26875ffb0c9bSToomas Soome     mDNS_DomainTypeBrowseAutomatic     = 2,
26885ffb0c9bSToomas Soome     mDNS_DomainTypeRegistration        = 3,
26895ffb0c9bSToomas Soome     mDNS_DomainTypeRegistrationDefault = 4,
26905ffb0c9bSToomas Soome 
26915ffb0c9bSToomas Soome     mDNS_DomainTypeMax = 4
26925ffb0c9bSToomas Soome } mDNS_DomainType;
26934b22b933Srs 
26944b22b933Srs extern const char *const mDNS_DomainTypeNames[];
26954b22b933Srs 
26964b22b933Srs extern mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, mDNS_DomainType DomainType, const domainname *dom,
26975ffb0c9bSToomas Soome                                const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *Callback, void *Context);
26984b22b933Srs #define        mDNS_StopGetDomains mDNS_StopQuery
26994b22b933Srs extern mStatus mDNS_AdvertiseDomains(mDNS *const m, AuthRecord *rr, mDNS_DomainType DomainType, const mDNSInterfaceID InterfaceID, char *domname);
27004b22b933Srs #define        mDNS_StopAdvertiseDomains mDNS_Deregister
27014b22b933Srs 
27025ffb0c9bSToomas Soome extern mDNSOpaque16 mDNS_NewMessageID(mDNS *const m);
2703cda73f64SToomas Soome extern mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr);
27045ffb0c9bSToomas Soome 
2705*472cd20dSToomas Soome #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
27065ffb0c9bSToomas Soome extern DNSServer *GetServerForQuestion(mDNS *m, DNSQuestion *question);
2707*472cd20dSToomas Soome #endif
27085ffb0c9bSToomas Soome extern mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question);
2709*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
2710*472cd20dSToomas Soome extern mDNSBool ShouldSuppressUnicastQuery(const DNSQuestion *q, mdns_dns_service_t dnsservice);
2711*472cd20dSToomas Soome extern mDNSBool LocalRecordRmvEventsForQuestion(mDNS *m, DNSQuestion *q);
2712*472cd20dSToomas Soome #endif
27135ffb0c9bSToomas Soome 
27144b22b933Srs // ***************************************************************************
27154b22b933Srs #if 0
27165ffb0c9bSToomas Soome #pragma mark -
27174b22b933Srs #pragma mark - DNS name utility functions
27184b22b933Srs #endif
27194b22b933Srs 
27204b22b933Srs // In order to expose the full capabilities of the DNS protocol (which allows any arbitrary eight-bit values
27214b22b933Srs // in domain name labels, including unlikely characters like ascii nulls and even dots) all the mDNS APIs
27224b22b933Srs // work with DNS's native length-prefixed strings. For convenience in C, the following utility functions
27234b22b933Srs // are provided for converting between C's null-terminated strings and DNS's length-prefixed strings.
27244b22b933Srs 
27254b22b933Srs // Assignment
27264b22b933Srs // A simple C structure assignment of a domainname can cause a protection fault by accessing unmapped memory,
27274b22b933Srs // because that object is defined to be 256 bytes long, but not all domainname objects are truly the full size.
27284b22b933Srs // This macro uses mDNSPlatformMemCopy() to make sure it only touches the actual bytes that are valid.
27295ffb0c9bSToomas Soome #define AssignDomainName(DST, SRC) do { mDNSu16 len__ = DomainNameLength((SRC)); \
2730c65ebfc7SToomas Soome     if (len__ <= MAX_DOMAIN_NAME) mDNSPlatformMemCopy((DST)->c, (SRC)->c, len__); else (DST)->c[0] = 0; } while(0)
2731*472cd20dSToomas Soome #define AssignConstStringDomainName(DST, SRC) do { \
2732*472cd20dSToomas Soome     mDNSu16 len__ = DomainNameLengthLimit((domainname *)(SRC), (mDNSu8 *)(SRC) + sizeof (SRC)); \
2733*472cd20dSToomas Soome     if (len__ <= MAX_DOMAIN_NAME) \
2734*472cd20dSToomas Soome         mDNSPlatformMemCopy((DST)->c, (SRC), len__); else (DST)->c[0] = 0; } while(0)
27354b22b933Srs 
27364b22b933Srs // Comparison functions
27375ffb0c9bSToomas Soome #define SameDomainLabelCS(A,B) ((A)[0] == (B)[0] && mDNSPlatformMemSame((A)+1, (B)+1, (A)[0]))
27384b22b933Srs extern mDNSBool SameDomainLabel(const mDNSu8 *a, const mDNSu8 *b);
27394b22b933Srs extern mDNSBool SameDomainName(const domainname *const d1, const domainname *const d2);
27405ffb0c9bSToomas Soome extern mDNSBool SameDomainNameCS(const domainname *const d1, const domainname *const d2);
27415ffb0c9bSToomas Soome typedef mDNSBool DomainNameComparisonFn (const domainname *const d1, const domainname *const d2);
27424b22b933Srs extern mDNSBool IsLocalDomain(const domainname *d);     // returns true for domains that by default should be looked up using link-local multicast
27434b22b933Srs 
27445ffb0c9bSToomas Soome #define StripFirstLabel(X) ((const domainname *)& (X)->c[(X)->c[0] ? 1 + (X)->c[0] : 0])
27455ffb0c9bSToomas Soome 
27465ffb0c9bSToomas Soome #define FirstLabel(X)  ((const domainlabel *)(X))
27475ffb0c9bSToomas Soome #define SecondLabel(X) ((const domainlabel *)StripFirstLabel(X))
27485ffb0c9bSToomas Soome #define ThirdLabel(X)  ((const domainlabel *)StripFirstLabel(StripFirstLabel(X)))
27495ffb0c9bSToomas Soome 
27505ffb0c9bSToomas Soome extern const mDNSu8 *LastLabel(const domainname *d);
27515ffb0c9bSToomas Soome 
27524b22b933Srs // Get total length of domain name, in native DNS format, including terminal root label
27534b22b933Srs //   (e.g. length of "com." is 5 (length byte, three data bytes, final zero)
27545ffb0c9bSToomas Soome extern mDNSu16  DomainNameLengthLimit(const domainname *const name, const mDNSu8 *limit);
27555ffb0c9bSToomas Soome #define DomainNameLength(name) DomainNameLengthLimit((name), (name)->c + MAX_DOMAIN_NAME)
27564b22b933Srs 
27574b22b933Srs // Append functions to append one or more labels to an existing native format domain name:
27584b22b933Srs //   AppendLiteralLabelString adds a single label from a literal C string, with no escape character interpretation.
27594b22b933Srs //   AppendDNSNameString      adds zero or more labels from a C string using conventional DNS dots-and-escaping interpretation
27604b22b933Srs //   AppendDomainLabel        adds a single label from a native format domainlabel
27614b22b933Srs //   AppendDomainName         adds zero or more labels from a native format domainname
27624b22b933Srs extern mDNSu8  *AppendLiteralLabelString(domainname *const name, const char *cstr);
27634b22b933Srs extern mDNSu8  *AppendDNSNameString     (domainname *const name, const char *cstr);
27644b22b933Srs extern mDNSu8  *AppendDomainLabel       (domainname *const name, const domainlabel *const label);
27654b22b933Srs extern mDNSu8  *AppendDomainName        (domainname *const name, const domainname *const append);
27664b22b933Srs 
27674b22b933Srs // Convert from null-terminated string to native DNS format:
27684b22b933Srs //   The DomainLabel form makes a single label from a literal C string, with no escape character interpretation.
27694b22b933Srs //   The DomainName form makes native format domain name from a C string using conventional DNS interpretation:
27704b22b933Srs //     dots separate labels, and within each label, '\.' represents a literal dot, '\\' represents a literal
27714b22b933Srs //     backslash and backslash with three decimal digits (e.g. \000) represents an arbitrary byte value.
27724b22b933Srs extern mDNSBool MakeDomainLabelFromLiteralString(domainlabel *const label, const char *cstr);
27734b22b933Srs extern mDNSu8  *MakeDomainNameFromDNSNameString (domainname  *const name,  const char *cstr);
27744b22b933Srs 
27754b22b933Srs // Convert native format domainlabel or domainname back to C string format
27764b22b933Srs // IMPORTANT:
27774b22b933Srs // When using ConvertDomainLabelToCString, the target buffer must be MAX_ESCAPED_DOMAIN_LABEL (254) bytes long
27784b22b933Srs // to guarantee there will be no buffer overrun. It is only safe to use a buffer shorter than this in rare cases
27794b22b933Srs // where the label is known to be constrained somehow (for example, if the label is known to be either "_tcp" or "_udp").
27805ffb0c9bSToomas Soome // Similarly, when using ConvertDomainNameToCString, the target buffer must be MAX_ESCAPED_DOMAIN_NAME (1009) bytes long.
27814b22b933Srs // See definitions of MAX_ESCAPED_DOMAIN_LABEL and MAX_ESCAPED_DOMAIN_NAME for more detailed explanation.
27824b22b933Srs extern char    *ConvertDomainLabelToCString_withescape(const domainlabel *const name, char *cstr, char esc);
27834b22b933Srs #define         ConvertDomainLabelToCString_unescaped(D,C) ConvertDomainLabelToCString_withescape((D), (C), 0)
27844b22b933Srs #define         ConvertDomainLabelToCString(D,C)           ConvertDomainLabelToCString_withescape((D), (C), '\\')
27854b22b933Srs extern char    *ConvertDomainNameToCString_withescape(const domainname *const name, char *cstr, char esc);
27864b22b933Srs #define         ConvertDomainNameToCString_unescaped(D,C) ConvertDomainNameToCString_withescape((D), (C), 0)
27874b22b933Srs #define         ConvertDomainNameToCString(D,C)           ConvertDomainNameToCString_withescape((D), (C), '\\')
27884b22b933Srs 
27894b22b933Srs extern void     ConvertUTF8PstringToRFC1034HostLabel(const mDNSu8 UTF8Name[], domainlabel *const hostlabel);
27904b22b933Srs 
2791c65ebfc7SToomas Soome #define ValidTransportProtocol(X) ( (X)[0] == 4 && (X)[1] == '_' && \
2792c65ebfc7SToomas Soome                                     ((((X)[2] | 0x20) == 'u' && ((X)[3] | 0x20) == 'd') || (((X)[2] | 0x20) == 't' && ((X)[3] | 0x20) == 'c')) && \
2793c65ebfc7SToomas Soome                                     ((X)[4] | 0x20) == 'p')
2794c65ebfc7SToomas Soome 
27954b22b933Srs extern mDNSu8  *ConstructServiceName(domainname *const fqdn, const domainlabel *name, const domainname *type, const domainname *const domain);
27964b22b933Srs extern mDNSBool DeconstructServiceName(const domainname *const fqdn, domainlabel *const name, domainname *const type, domainname *const domain);
27974b22b933Srs 
27984b22b933Srs // Note: Some old functions have been replaced by more sensibly-named versions.
27994b22b933Srs // You can uncomment the hash-defines below if you don't want to have to change your source code right away.
28004b22b933Srs // When updating your code, note that (unlike the old versions) *all* the new routines take the target object
28014b22b933Srs // as their first parameter.
28024b22b933Srs //#define ConvertCStringToDomainName(SRC,DST)  MakeDomainNameFromDNSNameString((DST),(SRC))
28034b22b933Srs //#define ConvertCStringToDomainLabel(SRC,DST) MakeDomainLabelFromLiteralString((DST),(SRC))
28044b22b933Srs //#define AppendStringLabelToName(DST,SRC)     AppendLiteralLabelString((DST),(SRC))
28054b22b933Srs //#define AppendStringNameToName(DST,SRC)      AppendDNSNameString((DST),(SRC))
28064b22b933Srs //#define AppendDomainLabelToName(DST,SRC)     AppendDomainLabel((DST),(SRC))
28074b22b933Srs //#define AppendDomainNameToName(DST,SRC)      AppendDomainName((DST),(SRC))
28084b22b933Srs 
28094b22b933Srs // ***************************************************************************
28104b22b933Srs #if 0
28115ffb0c9bSToomas Soome #pragma mark -
28124b22b933Srs #pragma mark - Other utility functions and macros
28134b22b933Srs #endif
28144b22b933Srs 
28154b22b933Srs // mDNS_vsnprintf/snprintf return the number of characters written, excluding the final terminating null.
28164b22b933Srs // The output is always null-terminated: for example, if the output turns out to be exactly buflen long,
28174b22b933Srs // then the output will be truncated by one character to allow space for the terminating null.
28184b22b933Srs // Unlike standard C vsnprintf/snprintf, they return the number of characters *actually* written,
28194b22b933Srs // not the number of characters that *would* have been printed were buflen unlimited.
2820c65ebfc7SToomas Soome extern mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, va_list arg) IS_A_PRINTF_STYLE_FUNCTION(3,0);
28214b22b933Srs extern mDNSu32 mDNS_snprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, ...) IS_A_PRINTF_STYLE_FUNCTION(3,4);
2822*472cd20dSToomas Soome extern void mDNS_snprintf_add(char **dst, const char *lim, const char *fmt, ...) IS_A_PRINTF_STYLE_FUNCTION(3,4);
28234b22b933Srs extern mDNSu32 NumCacheRecordsForInterfaceID(const mDNS *const m, mDNSInterfaceID id);
28244b22b933Srs extern char *DNSTypeName(mDNSu16 rrtype);
2825*472cd20dSToomas Soome extern const char *mStatusDescription(mStatus error);
28265ffb0c9bSToomas Soome extern char *GetRRDisplayString_rdb(const ResourceRecord *const rr, const RDataBody *const rd1, char *const buffer);
28274b22b933Srs #define RRDisplayString(m, rr) GetRRDisplayString_rdb(rr, &(rr)->rdata->u, (m)->MsgBuffer)
28284b22b933Srs #define ARDisplayString(m, rr) GetRRDisplayString_rdb(&(rr)->resrec, &(rr)->resrec.rdata->u, (m)->MsgBuffer)
28294b22b933Srs #define CRDisplayString(m, rr) GetRRDisplayString_rdb(&(rr)->resrec, &(rr)->resrec.rdata->u, (m)->MsgBuffer)
28303b436d06SToomas Soome #define MortalityDisplayString(M) (M == Mortality_Mortal ? "mortal" : (M == Mortality_Immortal ? "immortal" : "ghost"))
28314b22b933Srs extern mDNSBool mDNSSameAddress(const mDNSAddr *ip1, const mDNSAddr *ip2);
28324b22b933Srs extern void IncrementLabelSuffix(domainlabel *name, mDNSBool RichText);
28335ffb0c9bSToomas Soome extern mDNSBool mDNSv4AddrIsRFC1918(const mDNSv4Addr * const addr);  // returns true for RFC1918 private addresses
28345ffb0c9bSToomas Soome #define mDNSAddrIsRFC1918(X) ((X)->type == mDNSAddrType_IPv4 && mDNSv4AddrIsRFC1918(&(X)->ip.v4))
2835*472cd20dSToomas Soome extern const char *DNSScopeToString(mDNSu32 scope);
28365ffb0c9bSToomas Soome 
28375ffb0c9bSToomas Soome // For PCP
28385ffb0c9bSToomas Soome extern void mDNSAddrMapIPv4toIPv6(mDNSv4Addr* in, mDNSv6Addr* out);
28395ffb0c9bSToomas Soome extern mDNSBool mDNSAddrIPv4FromMappedIPv6(mDNSv6Addr *in, mDNSv4Addr *out);
28405ffb0c9bSToomas Soome 
28415ffb0c9bSToomas Soome #define mDNSSameIPPort(A,B)      ((A).NotAnInteger == (B).NotAnInteger)
28425ffb0c9bSToomas Soome #define mDNSSameOpaque16(A,B)    ((A).NotAnInteger == (B).NotAnInteger)
28435ffb0c9bSToomas Soome #define mDNSSameOpaque32(A,B)    ((A).NotAnInteger == (B).NotAnInteger)
28445ffb0c9bSToomas Soome #define mDNSSameOpaque64(A,B)    ((A)->l[0] == (B)->l[0] && (A)->l[1] == (B)->l[1])
28454b22b933Srs 
28464b22b933Srs #define mDNSSameIPv4Address(A,B) ((A).NotAnInteger == (B).NotAnInteger)
28474b22b933Srs #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])
28485ffb0c9bSToomas Soome #define mDNSSameIPv6NetworkPart(A,B) ((A).l[0] == (B).l[0] && (A).l[1] == (B).l[1])
28494b22b933Srs #define mDNSSameEthAddress(A,B)  ((A)->w[0] == (B)->w[0] && (A)->w[1] == (B)->w[1] && (A)->w[2] == (B)->w[2])
28504b22b933Srs 
28515ffb0c9bSToomas Soome #define mDNSIPPortIsZero(A)      ((A).NotAnInteger                            == 0)
28525ffb0c9bSToomas Soome #define mDNSOpaque16IsZero(A)    ((A).NotAnInteger                            == 0)
28535ffb0c9bSToomas Soome #define mDNSOpaque64IsZero(A)    (((A)->l[0] | (A)->l[1]                    ) == 0)
2854c65ebfc7SToomas Soome #define mDNSOpaque128IsZero(A)   (((A)->l[0] | (A)->l[1] | (A)->l[2] | (A)->l[3]) == 0)
28555ffb0c9bSToomas Soome #define mDNSIPv4AddressIsZero(A) ((A).NotAnInteger                            == 0)
28565ffb0c9bSToomas Soome #define mDNSIPv6AddressIsZero(A) (((A).l[0] | (A).l[1] | (A).l[2] | (A).l[3]) == 0)
28575ffb0c9bSToomas Soome #define mDNSEthAddressIsZero(A)  (((A).w[0] | (A).w[1] | (A).w[2]           ) == 0)
28584b22b933Srs 
28595ffb0c9bSToomas Soome #define mDNSIPv4AddressIsOnes(A) ((A).NotAnInteger == 0xFFFFFFFF)
28605ffb0c9bSToomas Soome #define mDNSIPv6AddressIsOnes(A) (((A).l[0] & (A).l[1] & (A).l[2] & (A).l[3]) == 0xFFFFFFFF)
28614b22b933Srs 
28625ffb0c9bSToomas Soome #define mDNSAddressIsAllDNSLinkGroup(X) (                                                            \
28635ffb0c9bSToomas Soome         ((X)->type == mDNSAddrType_IPv4 && mDNSSameIPv4Address((X)->ip.v4, AllDNSLinkGroup_v4.ip.v4)) || \
28645ffb0c9bSToomas Soome         ((X)->type == mDNSAddrType_IPv6 && mDNSSameIPv6Address((X)->ip.v6, AllDNSLinkGroup_v6.ip.v6))    )
28654b22b933Srs 
28664b22b933Srs #define mDNSAddressIsZero(X) (                                                \
28675ffb0c9bSToomas Soome         ((X)->type == mDNSAddrType_IPv4 && mDNSIPv4AddressIsZero((X)->ip.v4))  || \
28685ffb0c9bSToomas Soome         ((X)->type == mDNSAddrType_IPv6 && mDNSIPv6AddressIsZero((X)->ip.v6))     )
28694b22b933Srs 
28704b22b933Srs #define mDNSAddressIsValidNonZero(X) (                                        \
28715ffb0c9bSToomas Soome         ((X)->type == mDNSAddrType_IPv4 && !mDNSIPv4AddressIsZero((X)->ip.v4)) || \
28725ffb0c9bSToomas Soome         ((X)->type == mDNSAddrType_IPv6 && !mDNSIPv6AddressIsZero((X)->ip.v6))    )
28734b22b933Srs 
28744b22b933Srs #define mDNSAddressIsOnes(X) (                                                \
28755ffb0c9bSToomas Soome         ((X)->type == mDNSAddrType_IPv4 && mDNSIPv4AddressIsOnes((X)->ip.v4))  || \
28765ffb0c9bSToomas Soome         ((X)->type == mDNSAddrType_IPv6 && mDNSIPv6AddressIsOnes((X)->ip.v6))     )
28774b22b933Srs 
28784b22b933Srs #define mDNSAddressIsValid(X) (                                                                                             \
28795ffb0c9bSToomas Soome         ((X)->type == mDNSAddrType_IPv4) ? !(mDNSIPv4AddressIsZero((X)->ip.v4) || mDNSIPv4AddressIsOnes((X)->ip.v4)) :          \
28805ffb0c9bSToomas Soome         ((X)->type == mDNSAddrType_IPv6) ? !(mDNSIPv6AddressIsZero((X)->ip.v6) || mDNSIPv6AddressIsOnes((X)->ip.v6)) : mDNSfalse)
28815ffb0c9bSToomas Soome 
28825ffb0c9bSToomas Soome #define mDNSv4AddressIsLinkLocal(X) ((X)->b[0] ==  169 &&  (X)->b[1]         ==  254)
28835ffb0c9bSToomas Soome #define mDNSv6AddressIsLinkLocal(X) ((X)->b[0] == 0xFE && ((X)->b[1] & 0xC0) == 0x80)
28845ffb0c9bSToomas Soome 
28855ffb0c9bSToomas Soome #define mDNSAddressIsLinkLocal(X)  (                                                    \
28865ffb0c9bSToomas Soome         ((X)->type == mDNSAddrType_IPv4) ? mDNSv4AddressIsLinkLocal(&(X)->ip.v4) :          \
28875ffb0c9bSToomas Soome         ((X)->type == mDNSAddrType_IPv6) ? mDNSv6AddressIsLinkLocal(&(X)->ip.v6) : mDNSfalse)
28884b22b933Srs 
28894b22b933Srs 
28904b22b933Srs // ***************************************************************************
28914b22b933Srs #if 0
28925ffb0c9bSToomas Soome #pragma mark -
28934b22b933Srs #pragma mark - Authentication Support
28944b22b933Srs #endif
28954b22b933Srs 
28964b22b933Srs // Unicast DNS and Dynamic Update specific Client Calls
28974b22b933Srs //
28985ffb0c9bSToomas Soome // mDNS_SetSecretForDomain tells the core to authenticate (via TSIG with an HMAC_MD5 hash of the shared secret)
28994b22b933Srs // when dynamically updating a given zone (and its subdomains).  The key used in authentication must be in
29004b22b933Srs // domain name format.  The shared secret must be a null-terminated base64 encoded string.  A minimum size of
29014b22b933Srs // 16 bytes (128 bits) is recommended for an MD5 hash as per RFC 2485.
29024b22b933Srs // Calling this routine multiple times for a zone replaces previously entered values.  Call with a NULL key
29035ffb0c9bSToomas Soome // to disable authentication for the zone.  A non-NULL autoTunnelPrefix means this is an AutoTunnel domain,
29045ffb0c9bSToomas Soome // and the value is prepended to the IPSec identifier (used for key lookup)
29054b22b933Srs 
29065ffb0c9bSToomas Soome extern mStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info,
2907*472cd20dSToomas Soome                                        const domainname *domain, const domainname *keyname, const char *b64keydata, const domainname *hostname, mDNSIPPort *port);
29085ffb0c9bSToomas Soome 
29095ffb0c9bSToomas Soome extern void RecreateNATMappings(mDNS *const m, const mDNSu32 waitTicks);
29104b22b933Srs 
29114b22b933Srs // Hostname/Unicast Interface Configuration
29124b22b933Srs 
29134b22b933Srs // All hostnames advertised point to one IPv4 address and/or one IPv6 address, set via SetPrimaryInterfaceInfo.  Invoking this routine
29144b22b933Srs // updates all existing hostnames to point to the new address.
29155ffb0c9bSToomas Soome 
29164b22b933Srs // A hostname is added via AddDynDNSHostName, which points to the primary interface's v4 and/or v6 addresss
29174b22b933Srs 
29184b22b933Srs // The status callback is invoked to convey success or failure codes - the callback should not modify the AuthRecord or free memory.
29194b22b933Srs // Added hostnames may be removed (deregistered) via mDNS_RemoveDynDNSHostName.
29204b22b933Srs 
29214b22b933Srs // Host domains added prior to specification of the primary interface address and computer name will be deferred until
29224b22b933Srs // these values are initialized.
29234b22b933Srs 
29245ffb0c9bSToomas Soome // DNS servers used to resolve unicast queries are specified by mDNS_AddDNSServer.
29254b22b933Srs // For "split" DNS configurations, in which queries for different domains are sent to different servers (e.g. VPN and external),
29264b22b933Srs // a domain may be associated with a DNS server.  For standard configurations, specify the root label (".") or NULL.
29275ffb0c9bSToomas Soome 
29284b22b933Srs extern void mDNS_AddDynDNSHostName(mDNS *m, const domainname *fqdn, mDNSRecordCallback *StatusCallback, const void *StatusContext);
29294b22b933Srs extern void mDNS_RemoveDynDNSHostName(mDNS *m, const domainname *fqdn);
29304b22b933Srs extern void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr,  const mDNSAddr *v6addr, const mDNSAddr *router);
2931*472cd20dSToomas Soome #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
29325ffb0c9bSToomas Soome extern DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, mDNSs32 serviceID, const mDNSAddr *addr,
2933*472cd20dSToomas Soome                                     const mDNSIPPort port, ScopeType scopeType, mDNSu32 timeout, mDNSBool cellIntf, mDNSBool isExpensive, mDNSBool isConstrained, mDNSBool isCLAT46,
2934*472cd20dSToomas Soome                                     mDNSu32 resGroupID, mDNSBool reqA, mDNSBool reqAAAA, mDNSBool reqDO);
29355ffb0c9bSToomas Soome extern void PenalizeDNSServer(mDNS *const m, DNSQuestion *q, mDNSOpaque16 responseFlags);
2936*472cd20dSToomas Soome #endif
29375ffb0c9bSToomas Soome extern void mDNS_AddSearchDomain(const domainname *const domain, mDNSInterfaceID InterfaceID);
29384b22b933Srs 
29395ffb0c9bSToomas Soome extern McastResolver *mDNS_AddMcastResolver(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, mDNSu32 timeout);
29405ffb0c9bSToomas Soome 
29415ffb0c9bSToomas Soome // We use ((void *)0) here instead of mDNSNULL to avoid compile warnings on gcc 4.2
29425ffb0c9bSToomas Soome #define mDNS_AddSearchDomain_CString(X, I) \
29435ffb0c9bSToomas Soome     do { domainname d__; if (((X) != (void*)0) && MakeDomainNameFromDNSNameString(&d__, (X)) && d__.c[0]) mDNS_AddSearchDomain(&d__, I);} while(0)
29444b22b933Srs 
29455ffb0c9bSToomas Soome // Routines called by the core, exported by DNSDigest.c
29464b22b933Srs 
29475ffb0c9bSToomas Soome // Convert an arbitrary base64 encoded key key into an HMAC key (stored in AuthInfo struct)
29485ffb0c9bSToomas Soome extern mDNSs32 DNSDigest_ConstructHMACKeyfromBase64(DomainAuthInfo *info, const char *b64key);
29494b22b933Srs 
29505ffb0c9bSToomas Soome // sign a DNS message.  The message must be complete, with all values in network byte order.  end points to the end
29514b22b933Srs // of the message, and is modified by this routine.  numAdditionals is a pointer to the number of additional
29524b22b933Srs // records in HOST byte order, which is incremented upon successful completion of this routine.  The function returns
29534b22b933Srs // the new end pointer on success, and NULL on failure.
29545ffb0c9bSToomas Soome extern void DNSDigest_SignMessage(DNSMessage *msg, mDNSu8 **end, DomainAuthInfo *info, mDNSu16 tcode);
29555ffb0c9bSToomas Soome 
29565ffb0c9bSToomas Soome #define SwapDNSHeaderBytes(M) do { \
29575ffb0c9bSToomas Soome     (M)->h.numQuestions   = (mDNSu16)((mDNSu8 *)&(M)->h.numQuestions  )[0] << 8 | ((mDNSu8 *)&(M)->h.numQuestions  )[1]; \
29585ffb0c9bSToomas Soome     (M)->h.numAnswers     = (mDNSu16)((mDNSu8 *)&(M)->h.numAnswers    )[0] << 8 | ((mDNSu8 *)&(M)->h.numAnswers    )[1]; \
29595ffb0c9bSToomas Soome     (M)->h.numAuthorities = (mDNSu16)((mDNSu8 *)&(M)->h.numAuthorities)[0] << 8 | ((mDNSu8 *)&(M)->h.numAuthorities)[1]; \
29605ffb0c9bSToomas Soome     (M)->h.numAdditionals = (mDNSu16)((mDNSu8 *)&(M)->h.numAdditionals)[0] << 8 | ((mDNSu8 *)&(M)->h.numAdditionals)[1]; \
29615ffb0c9bSToomas Soome } while (0)
29625ffb0c9bSToomas Soome 
29635ffb0c9bSToomas Soome // verify a DNS message.  The message must be complete, with all values in network byte order.  end points to the
29645ffb0c9bSToomas Soome // end of the record.  tsig is a pointer to the resource record that contains the TSIG OPT record.  info is
29655ffb0c9bSToomas Soome // the matching key to use for verifying the message.  This function expects that the additionals member
29665ffb0c9bSToomas Soome // of the DNS message header has already had one subtracted from it.
29675ffb0c9bSToomas Soome extern mDNSBool DNSDigest_VerifyMessage(DNSMessage *msg, mDNSu8 *end, LargeCacheRecord *tsig, DomainAuthInfo *info, mDNSu16 *rcode, mDNSu16 *tcode);
29684b22b933Srs 
29694b22b933Srs // ***************************************************************************
29704b22b933Srs #if 0
29715ffb0c9bSToomas Soome #pragma mark -
29724b22b933Srs #pragma mark - PlatformSupport interface
29734b22b933Srs #endif
29744b22b933Srs 
29754b22b933Srs // This section defines the interface to the Platform Support layer.
29764b22b933Srs // Normal client code should not use any of types defined here, or directly call any of the functions defined here.
29774b22b933Srs // The definitions are placed here because sometimes clients do use these calls indirectly, via other supported client operations.
29784b22b933Srs // For example, AssignDomainName is a macro defined using mDNSPlatformMemCopy()
29794b22b933Srs 
29804b22b933Srs // Every platform support module must provide the following functions.
29814b22b933Srs // mDNSPlatformInit() typically opens a communication endpoint, and starts listening for mDNS packets.
29824b22b933Srs // When Setup is complete, the platform support layer calls mDNSCoreInitComplete().
29834b22b933Srs // mDNSPlatformSendUDP() sends one UDP packet
29844b22b933Srs // When a packet is received, the PlatformSupport code calls mDNSCoreReceive()
29854b22b933Srs // mDNSPlatformClose() tidies up on exit
29864b22b933Srs //
29874b22b933Srs // Note: mDNSPlatformMemAllocate/mDNSPlatformMemFree are only required for handling oversized resource records and unicast DNS.
29884b22b933Srs // If your target platform has a well-defined specialized application, and you know that all the records it uses
29894b22b933Srs // are InlineCacheRDSize or less, then you can just make a simple mDNSPlatformMemAllocate() stub that always returns
29905ffb0c9bSToomas Soome // NULL. InlineCacheRDSize is a compile-time constant, which is set by default to 68. If you need to handle records
29914b22b933Srs // a little larger than this and you don't want to have to implement run-time allocation and freeing, then you
29924b22b933Srs // can raise the value of this constant to a suitable value (at the expense of increased memory usage).
29934b22b933Srs //
29944b22b933Srs // USE CAUTION WHEN CALLING mDNSPlatformRawTime: The m->timenow_adjust correction factor needs to be added
29954b22b933Srs // Generally speaking:
29964b22b933Srs // Code that's protected by the main mDNS lock should just use the m->timenow value
29974b22b933Srs // Code outside the main mDNS lock should use mDNS_TimeNow(m) to get properly adjusted time
29984b22b933Srs // In certain cases there may be reasons why it's necessary to get the time without taking the lock first
29994b22b933Srs // (e.g. inside the routines that are doing the locking and unlocking, where a call to get the lock would result in a
30004b22b933Srs // recursive loop); in these cases use mDNS_TimeNow_NoLock(m) to get mDNSPlatformRawTime with the proper correction factor added.
30014b22b933Srs //
30024b22b933Srs // mDNSPlatformUTC returns the time, in seconds, since Jan 1st 1970 UTC and is required for generating TSIG records
30034b22b933Srs 
3004*472cd20dSToomas Soome #ifdef MDNS_MALLOC_DEBUGGING
3005*472cd20dSToomas Soome typedef void mDNSListValidationFunction(void *);
3006*472cd20dSToomas Soome typedef struct listValidator mDNSListValidator;
3007*472cd20dSToomas Soome struct listValidator {
3008*472cd20dSToomas Soome     struct listValidator *next;
3009*472cd20dSToomas Soome     const char *validationFunctionName;
3010*472cd20dSToomas Soome     mDNSListValidationFunction *validator;
3011*472cd20dSToomas Soome     void *context;
3012*472cd20dSToomas Soome };
3013*472cd20dSToomas Soome #endif // MDNS_MALLOC_DEBUGGING
3014*472cd20dSToomas Soome 
30154b22b933Srs extern mStatus  mDNSPlatformInit        (mDNS *const m);
30164b22b933Srs extern void     mDNSPlatformClose       (mDNS *const m);
30174b22b933Srs extern mStatus  mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end,
3018c65ebfc7SToomas Soome                                     mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst,
30195ffb0c9bSToomas Soome                                     mDNSIPPort dstport, mDNSBool useBackgroundTrafficClass);
30204b22b933Srs 
30214b22b933Srs extern void     mDNSPlatformLock        (const mDNS *const m);
30224b22b933Srs extern void     mDNSPlatformUnlock      (const mDNS *const m);
30234b22b933Srs 
3024c65ebfc7SToomas Soome extern mDNSu32  mDNSPlatformStrLCopy    (      void *dst, const void *src, mDNSu32 len);
30255ffb0c9bSToomas Soome extern mDNSu32  mDNSPlatformStrLen      (                 const void *src);
30265ffb0c9bSToomas Soome extern void     mDNSPlatformMemCopy     (      void *dst, const void *src, mDNSu32 len);
30275ffb0c9bSToomas Soome extern mDNSBool mDNSPlatformMemSame     (const void *dst, const void *src, mDNSu32 len);
30285ffb0c9bSToomas Soome extern int      mDNSPlatformMemCmp      (const void *dst, const void *src, mDNSu32 len);
30295ffb0c9bSToomas Soome extern void     mDNSPlatformMemZero     (      void *dst,                  mDNSu32 len);
30305ffb0c9bSToomas Soome extern void mDNSPlatformQsort       (void *base, int nel, int width, int (*compar)(const void *, const void *));
3031*472cd20dSToomas Soome #if MDNS_MALLOC_DEBUGGING
3032*472cd20dSToomas Soome #define         mDNSPlatformMemAllocate(X)      mallocL(# X, X)
3033*472cd20dSToomas Soome #define         mDNSPlatformMemAllocateClear(X)	callocL(# X, X)
3034*472cd20dSToomas Soome #define         mDNSPlatformMemFree(X)          freeL(# X, X)
3035*472cd20dSToomas Soome extern void     mDNSPlatformValidateLists (void);
3036*472cd20dSToomas Soome extern void     mDNSPlatformAddListValidator(mDNSListValidator *validator,
3037*472cd20dSToomas Soome                                              mDNSListValidationFunction *vf, const char *vfName, void *context);
30385ffb0c9bSToomas Soome #else
3039*472cd20dSToomas Soome extern void *   mDNSPlatformMemAllocate(mDNSu32 len);
3040*472cd20dSToomas Soome extern void *   mDNSPlatformMemAllocateClear(mDNSu32 len);
3041*472cd20dSToomas Soome extern void     mDNSPlatformMemFree(void *mem);
3042*472cd20dSToomas Soome #endif // MDNS_MALLOC_DEBUGGING
30435ffb0c9bSToomas Soome 
30445ffb0c9bSToomas Soome // If the platform doesn't have a strong PRNG, we define a naive multiply-and-add based on a seed
30455ffb0c9bSToomas Soome // from the platform layer.  Long-term, we should embed an arc4 implementation, but the strength
30465ffb0c9bSToomas Soome // will still depend on the randomness of the seed.
30475ffb0c9bSToomas Soome #if !defined(_PLATFORM_HAS_STRONG_PRNG_) && (_BUILDING_XCODE_PROJECT_ || defined(_WIN32))
30485ffb0c9bSToomas Soome #define _PLATFORM_HAS_STRONG_PRNG_ 1
30495ffb0c9bSToomas Soome #endif
30505ffb0c9bSToomas Soome #if _PLATFORM_HAS_STRONG_PRNG_
30515ffb0c9bSToomas Soome extern mDNSu32  mDNSPlatformRandomNumber(void);
30525ffb0c9bSToomas Soome #else
30534b22b933Srs extern mDNSu32  mDNSPlatformRandomSeed  (void);
30545ffb0c9bSToomas Soome #endif // _PLATFORM_HAS_STRONG_PRNG_
30555ffb0c9bSToomas Soome 
30564b22b933Srs extern mStatus  mDNSPlatformTimeInit    (void);
30574b22b933Srs extern mDNSs32  mDNSPlatformRawTime     (void);
30584b22b933Srs extern mDNSs32  mDNSPlatformUTC         (void);
30595ffb0c9bSToomas Soome #define mDNS_TimeNow_NoLock(m) (mDNSPlatformRawTime() + (m)->timenow_adjust)
30605ffb0c9bSToomas Soome 
30615ffb0c9bSToomas Soome #if MDNS_DEBUGMSGS
30625ffb0c9bSToomas Soome extern void mDNSPlatformWriteDebugMsg(const char *msg);
30635ffb0c9bSToomas Soome #endif
30645ffb0c9bSToomas Soome extern void mDNSPlatformWriteLogMsg(const char *ident, const char *msg, mDNSLogLevel_t loglevel);
30655ffb0c9bSToomas Soome 
30664b22b933Srs // Platform support modules should provide the following functions to map between opaque interface IDs
30674b22b933Srs // and interface indexes in order to support the DNS-SD API. If your target platform does not support
30684b22b933Srs // multiple interfaces and/or does not support the DNS-SD API, these functions can be empty.
30695ffb0c9bSToomas Soome extern mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 ifindex);
30705ffb0c9bSToomas Soome extern mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id, mDNSBool suppressNetworkChange);
30714b22b933Srs 
30724b22b933Srs // Every platform support module must provide the following functions if it is to support unicast DNS
30734b22b933Srs // and Dynamic Update.
30744b22b933Srs // All TCP socket operations implemented by the platform layer MUST NOT BLOCK.
30754b22b933Srs // mDNSPlatformTCPConnect initiates a TCP connection with a peer, adding the socket descriptor to the
30764b22b933Srs // main event loop.  The return value indicates whether the connection succeeded, failed, or is pending
30774b22b933Srs // (i.e. the call would block.)  On return, the descriptor parameter is set to point to the connected socket.
30784b22b933Srs // The TCPConnectionCallback is subsequently invoked when the connection
30794b22b933Srs // completes (in which case the ConnectionEstablished parameter is true), or data is available for
30804b22b933Srs // reading on the socket (indicated by the ConnectionEstablished parameter being false.)  If the connection
30814b22b933Srs // asynchronously fails, the TCPConnectionCallback should be invoked as usual, with the error being
30824b22b933Srs // returned in subsequent calls to PlatformReadTCP or PlatformWriteTCP.  (This allows for platforms
30834b22b933Srs // with limited asynchronous error detection capabilities.)  PlatformReadTCP and PlatformWriteTCP must
30845ffb0c9bSToomas Soome // return the number of bytes read/written, 0 if the call would block, and -1 if an error.  PlatformReadTCP
30855ffb0c9bSToomas Soome // should set the closed argument if the socket has been closed.
30864b22b933Srs // PlatformTCPCloseConnection must close the connection to the peer and remove the descriptor from the
30874b22b933Srs // event loop.  CloseConnectin may be called at any time, including in a ConnectionCallback.
30884b22b933Srs 
30895ffb0c9bSToomas Soome typedef enum
30905ffb0c9bSToomas Soome {
30915ffb0c9bSToomas Soome     kTCPSocketFlags_Zero   = 0,
30925ffb0c9bSToomas Soome     kTCPSocketFlags_UseTLS = (1 << 0)
30935ffb0c9bSToomas Soome } TCPSocketFlags;
30945ffb0c9bSToomas Soome 
30955ffb0c9bSToomas Soome typedef void (*TCPConnectionCallback)(TCPSocket *sock, void *context, mDNSBool ConnectionEstablished, mStatus err);
3096*472cd20dSToomas Soome typedef void (*TCPAcceptedCallback)(TCPSocket *sock, mDNSAddr *addr, mDNSIPPort *port,
3097*472cd20dSToomas Soome 									const char *remoteName, void *context);
3098*472cd20dSToomas Soome extern TCPSocket *mDNSPlatformTCPSocket(TCPSocketFlags flags, mDNSAddr_Type addrtype, mDNSIPPort *port, domainname *hostname, mDNSBool useBackgroundTrafficClass); // creates a TCP socket
3099*472cd20dSToomas Soome extern TCPListener *mDNSPlatformTCPListen(mDNSAddr_Type addrtype, mDNSIPPort *port, mDNSAddr *addr,
3100*472cd20dSToomas Soome 										  TCPSocketFlags socketFlags, mDNSBool reuseAddr, int queueLength,
3101*472cd20dSToomas Soome 										  TCPAcceptedCallback callback, void *context); // Listen on a port
3102*472cd20dSToomas Soome extern mStatus mDNSPlatformTCPSocketSetCallback(TCPSocket *sock, TCPConnectionCallback callback, void *context);
31035ffb0c9bSToomas Soome extern TCPSocket *mDNSPlatformTCPAccept(TCPSocketFlags flags, int sd);
31045ffb0c9bSToomas Soome extern int        mDNSPlatformTCPGetFD(TCPSocket *sock);
3105*472cd20dSToomas Soome extern mDNSBool   mDNSPlatformTCPWritable(TCPSocket *sock);
3106*472cd20dSToomas Soome extern mStatus    mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, mDNSOpaque16 dstport,
31075ffb0c9bSToomas Soome                                          mDNSInterfaceID InterfaceID, TCPConnectionCallback callback, void *context);
31085ffb0c9bSToomas Soome extern void       mDNSPlatformTCPCloseConnection(TCPSocket *sock);
31095ffb0c9bSToomas Soome extern long       mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool *closed);
31105ffb0c9bSToomas Soome extern long       mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned long len);
3111c65ebfc7SToomas Soome extern UDPSocket *mDNSPlatformUDPSocket(const mDNSIPPort requestedport);
31125ffb0c9bSToomas Soome extern mDNSu16    mDNSPlatformGetUDPPort(UDPSocket *sock);
31135ffb0c9bSToomas Soome extern void       mDNSPlatformUDPClose(UDPSocket *sock);
3114c65ebfc7SToomas Soome extern mDNSBool   mDNSPlatformUDPSocketEncounteredEOF(const UDPSocket *sock);
3115c65ebfc7SToomas Soome extern void       mDNSPlatformReceiveBPF_fd(int fd);
3116c65ebfc7SToomas Soome extern void       mDNSPlatformUpdateProxyList(const mDNSInterfaceID InterfaceID);
31175ffb0c9bSToomas Soome extern void       mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID);
3118c65ebfc7SToomas Soome extern void       mDNSPlatformSetLocalAddressCacheEntry(const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID);
31195ffb0c9bSToomas Soome extern void       mDNSPlatformSourceAddrForDest(mDNSAddr *const src, const mDNSAddr *const dst);
31205ffb0c9bSToomas Soome extern void       mDNSPlatformSendKeepalive(mDNSAddr *sadd, mDNSAddr *dadd, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu32 seq, mDNSu32 ack, mDNSu16 win);
3121c65ebfc7SToomas Soome extern mStatus    mDNSPlatformRetrieveTCPInfo(mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr,  mDNSIPPort *rport, mDNSTCPInfo *mti);
3122c65ebfc7SToomas Soome extern mStatus    mDNSPlatformGetRemoteMacAddr(mDNSAddr *raddr);
31235ffb0c9bSToomas Soome extern mStatus    mDNSPlatformStoreSPSMACAddr(mDNSAddr *spsaddr, char *ifname);
3124c65ebfc7SToomas Soome extern mStatus    mDNSPlatformClearSPSData(void);
3125c65ebfc7SToomas Soome extern mStatus    mDNSPlatformStoreOwnerOptRecord(char *ifname, DNSMessage *msg, int length);
31265ffb0c9bSToomas Soome 
31275ffb0c9bSToomas Soome // mDNSPlatformTLSSetupCerts/mDNSPlatformTLSTearDownCerts used by dnsextd
31285ffb0c9bSToomas Soome extern mStatus    mDNSPlatformTLSSetupCerts(void);
31295ffb0c9bSToomas Soome extern void       mDNSPlatformTLSTearDownCerts(void);
31304b22b933Srs 
31314b22b933Srs // Platforms that support unicast browsing and dynamic update registration for clients who do not specify a domain
31324b22b933Srs // in browse/registration calls must implement these routines to get the "default" browse/registration list.
31334b22b933Srs 
3134c65ebfc7SToomas Soome extern mDNSBool   mDNSPlatformSetDNSConfig(mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **RegDomains,
3135*472cd20dSToomas Soome                                            DNameListElem **BrowseDomains, mDNSBool ackConfig);
3136c65ebfc7SToomas Soome extern mStatus    mDNSPlatformGetPrimaryInterface(mDNSAddr *v4, mDNSAddr *v6, mDNSAddr *router);
31375ffb0c9bSToomas Soome extern void       mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status);
31384b22b933Srs 
3139c65ebfc7SToomas Soome extern void       mDNSPlatformSetAllowSleep(mDNSBool allowSleep, const char *reason);
3140c65ebfc7SToomas Soome extern void       mDNSPlatformPreventSleep(mDNSu32 timeout, const char *reason);
3141c65ebfc7SToomas Soome extern void       mDNSPlatformSendWakeupPacket(mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration);
31424b22b933Srs 
31435ffb0c9bSToomas Soome extern mDNSBool   mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID);
3144*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
3145*472cd20dSToomas Soome extern mDNSBool   mDNSPlatformInterfaceIsAWDL(mDNSInterfaceID interfaceID);
3146*472cd20dSToomas Soome #endif
31475ffb0c9bSToomas Soome extern mDNSBool   mDNSPlatformValidRecordForQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
3148c65ebfc7SToomas Soome extern mDNSBool   mDNSPlatformValidRecordForInterface(const AuthRecord *rr, mDNSInterfaceID InterfaceID);
31495ffb0c9bSToomas Soome extern mDNSBool   mDNSPlatformValidQuestionForInterface(DNSQuestion *q, const NetworkInterfaceInfo *intf);
31505ffb0c9bSToomas Soome 
31515ffb0c9bSToomas Soome extern void mDNSPlatformFormatTime(unsigned long t, mDNSu8 *buf, int bufsize);
31524b22b933Srs 
3153*472cd20dSToomas Soome // Platform event API
3154*472cd20dSToomas Soome 
31554b22b933Srs #ifdef _LEGACY_NAT_TRAVERSAL_
31564b22b933Srs // Support for legacy NAT traversal protocols, implemented by the platform layer and callable by the core.
31575ffb0c9bSToomas Soome extern void     LNT_SendDiscoveryMsg(mDNS *m);
31585ffb0c9bSToomas Soome extern void     LNT_ConfigureRouterInfo(mDNS *m, const mDNSInterfaceID InterfaceID, const mDNSu8 *const data, const mDNSu16 len);
31595ffb0c9bSToomas Soome extern mStatus  LNT_GetExternalAddress(mDNS *m);
31605ffb0c9bSToomas Soome extern mStatus  LNT_MapPort(mDNS *m, NATTraversalInfo *const n);
31615ffb0c9bSToomas Soome extern mStatus  LNT_UnmapPort(mDNS *m, NATTraversalInfo *const n);
31625ffb0c9bSToomas Soome extern void     LNT_ClearState(mDNS *const m);
31634b22b933Srs #endif // _LEGACY_NAT_TRAVERSAL_
31644b22b933Srs 
31654b22b933Srs // The core mDNS code provides these functions, for the platform support code to call at appropriate times
31664b22b933Srs //
31674b22b933Srs // mDNS_SetFQDN() is called once on startup (typically from mDNSPlatformInit())
31684b22b933Srs // and then again on each subsequent change of the host name.
31694b22b933Srs //
31704b22b933Srs // mDNS_RegisterInterface() is used by the platform support layer to inform mDNSCore of what
31714b22b933Srs // physical and/or logical interfaces are available for sending and receiving packets.
31724b22b933Srs // Typically it is called on startup for each available interface, but register/deregister may be
31734b22b933Srs // called again later, on multiple occasions, to inform the core of interface configuration changes.
31744b22b933Srs // If set->Advertise is set non-zero, then mDNS_RegisterInterface() also registers the standard
31754b22b933Srs // resource records that should be associated with every publicised IP address/interface:
31764b22b933Srs // -- Name-to-address records (A/AAAA)
31774b22b933Srs // -- Address-to-name records (PTR)
31784b22b933Srs // -- Host information (HINFO)
31794b22b933Srs // IMPORTANT: The specified mDNSInterfaceID MUST NOT be 0, -1, or -2; these values have special meaning
31804b22b933Srs // mDNS_RegisterInterface does not result in the registration of global hostnames via dynamic update -
31814b22b933Srs // see mDNS_SetPrimaryInterfaceInfo, mDNS_AddDynDNSHostName, etc. for this purpose.
31824b22b933Srs // Note that the set may be deallocated immediately after it is deregistered via mDNS_DeegisterInterface.
31834b22b933Srs //
31844b22b933Srs // mDNS_RegisterDNS() is used by the platform support layer to provide the core with the addresses of
31854b22b933Srs // available domain name servers for unicast queries/updates.  RegisterDNS() should be called once for
31864b22b933Srs // each name server, typically at startup, or when a new name server becomes available.  DeregiterDNS()
31874b22b933Srs // must be called whenever a registered name server becomes unavailable.  DeregisterDNSList deregisters
31884b22b933Srs // all registered servers.  mDNS_DNSRegistered() returns true if one or more servers are registered in the core.
31894b22b933Srs //
31904b22b933Srs // mDNSCoreInitComplete() is called when the platform support layer is finished.
31914b22b933Srs // Typically this is at the end of mDNSPlatformInit(), but may be later
31924b22b933Srs // (on platforms like OT that allow asynchronous initialization of the networking stack).
31934b22b933Srs //
31944b22b933Srs // mDNSCoreReceive() is called when a UDP packet is received
31954b22b933Srs //
31964b22b933Srs // mDNSCoreMachineSleep() is called when the machine sleeps or wakes
31974b22b933Srs // (This refers to heavyweight laptop-style sleep/wake that disables network access,
31984b22b933Srs // not lightweight second-by-second CPU power management modes.)
31994b22b933Srs 
32004b22b933Srs extern void     mDNS_SetFQDN(mDNS *const m);
32015ffb0c9bSToomas Soome extern void     mDNS_ActivateNetWake_internal  (mDNS *const m, NetworkInterfaceInfo *set);
32025ffb0c9bSToomas Soome extern void     mDNS_DeactivateNetWake_internal(mDNS *const m, NetworkInterfaceInfo *set);
3203c65ebfc7SToomas Soome 
3204c65ebfc7SToomas Soome // Attributes that controls the Bonjour operation initiation and response speed for an interface.
3205c65ebfc7SToomas Soome typedef enum
3206c65ebfc7SToomas Soome {
3207c65ebfc7SToomas Soome     FastActivation,     // For p2p* and DirectLink type interfaces
3208c65ebfc7SToomas Soome     NormalActivation,   // For standard interface timing
3209c65ebfc7SToomas Soome     SlowActivation      // For flapping interfaces
3210c65ebfc7SToomas Soome } InterfaceActivationSpeed;
3211c65ebfc7SToomas Soome 
3212c65ebfc7SToomas Soome extern mStatus  mDNS_RegisterInterface  (mDNS *const m, NetworkInterfaceInfo *set, InterfaceActivationSpeed probeDelay);
3213c65ebfc7SToomas Soome extern void     mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, InterfaceActivationSpeed probeDelay);
32144b22b933Srs extern void     mDNSCoreInitComplete(mDNS *const m, mStatus result);
3215c65ebfc7SToomas Soome extern void     mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end,
32165ffb0c9bSToomas Soome                                 const mDNSAddr *const srcaddr, const mDNSIPPort srcport,
32175ffb0c9bSToomas Soome                                 const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID);
3218*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
3219*472cd20dSToomas Soome extern void     mDNSCoreReceiveForQuerier(mDNS *m, DNSMessage *msg, const mDNSu8 *end, mdns_querier_t querier, mdns_dns_service_t service);
3220*472cd20dSToomas Soome #endif
3221*472cd20dSToomas Soome extern CacheRecord *mDNSCheckCacheFlushRecords(mDNS *m, CacheRecord *CacheFlushRecords, mDNSBool id_is_zero, int numAnswers,
3222*472cd20dSToomas Soome 											   DNSQuestion *unicastQuestion, CacheRecord *NSECCachePtr, CacheRecord *NSECRecords,
3223*472cd20dSToomas Soome 											   mDNSu8 rcode);
32245ffb0c9bSToomas Soome extern void     mDNSCoreRestartQueries(mDNS *const m);
32255ffb0c9bSToomas Soome extern void     mDNSCoreRestartQuestion(mDNS *const m, DNSQuestion *q);
32265ffb0c9bSToomas Soome extern void     mDNSCoreRestartRegistration(mDNS *const m, AuthRecord  *rr, int announceCount);
32275ffb0c9bSToomas Soome typedef void (*FlushCache)(mDNS *const m);
32285ffb0c9bSToomas Soome typedef void (*CallbackBeforeStartQuery)(mDNS *const m, void *context);
32295ffb0c9bSToomas Soome extern void     mDNSCoreRestartAddressQueries(mDNS *const m, mDNSBool SearchDomainsChanged, FlushCache flushCacheRecords,
32305ffb0c9bSToomas Soome                                               CallbackBeforeStartQuery beforeQueryStart, void *context);
32315ffb0c9bSToomas Soome extern mDNSBool mDNSCoreHaveAdvertisedMulticastServices(mDNS *const m);
32324b22b933Srs extern void     mDNSCoreMachineSleep(mDNS *const m, mDNSBool wake);
32335ffb0c9bSToomas Soome extern mDNSBool mDNSCoreReadyForSleep(mDNS *m, mDNSs32 now);
3234*472cd20dSToomas Soome 
3235*472cd20dSToomas Soome typedef enum
3236*472cd20dSToomas Soome {
3237*472cd20dSToomas Soome     mDNSNextWakeReason_Null                        = 0,
3238*472cd20dSToomas Soome     mDNSNextWakeReason_NATPortMappingRenewal       = 1,
3239*472cd20dSToomas Soome     mDNSNextWakeReason_RecordRegistrationRenewal   = 2,
3240*472cd20dSToomas Soome     mDNSNextWakeReason_UpkeepWake                  = 3,
3241*472cd20dSToomas Soome     mDNSNextWakeReason_DHCPLeaseRenewal            = 4,
3242*472cd20dSToomas Soome     mDNSNextWakeReason_SleepProxyRegistrationRetry = 5
3243*472cd20dSToomas Soome } mDNSNextWakeReason;
3244*472cd20dSToomas Soome 
3245*472cd20dSToomas Soome extern mDNSs32  mDNSCoreIntervalToNextWake(mDNS *const m, mDNSs32 now, mDNSNextWakeReason *outReason);
32465ffb0c9bSToomas Soome 
32475ffb0c9bSToomas Soome extern void     mDNSCoreReceiveRawPacket  (mDNS *const m, const mDNSu8 *const p, const mDNSu8 *const end, const mDNSInterfaceID InterfaceID);
32484b22b933Srs 
32494b22b933Srs extern mDNSBool mDNSAddrIsDNSMulticast(const mDNSAddr *ip);
32504b22b933Srs 
32515ffb0c9bSToomas Soome extern CacheRecord *CreateNewCacheEntry(mDNS *const m, const mDNSu32 slot, CacheGroup *cg, mDNSs32 delay, mDNSBool Add, const mDNSAddr *sourceAddress);
3252c65ebfc7SToomas Soome extern CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 namehash, const domainname *const name);
32535ffb0c9bSToomas Soome extern void ReleaseCacheRecord(mDNS *const m, CacheRecord *r);
32545ffb0c9bSToomas Soome extern void ScheduleNextCacheCheckTime(mDNS *const m, const mDNSu32 slot, const mDNSs32 event);
32555ffb0c9bSToomas Soome extern void SetNextCacheCheckTimeForRecord(mDNS *const m, CacheRecord *const rr);
32565ffb0c9bSToomas Soome extern void GrantCacheExtensions(mDNS *const m, DNSQuestion *q, mDNSu32 lease);
3257*472cd20dSToomas Soome extern void MakeNegativeCacheRecord(mDNS *const m, CacheRecord *const cr, const domainname *const name,
3258*472cd20dSToomas Soome     const mDNSu32 namehash, const mDNSu16 rrtype, const mDNSu16 rrclass, mDNSu32 ttl_seconds, mDNSInterfaceID InterfaceID,
3259*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
3260*472cd20dSToomas Soome     mdns_dns_service_t service);
3261*472cd20dSToomas Soome #else
3262*472cd20dSToomas Soome     DNSServer *dnsserver);
3263*472cd20dSToomas Soome #endif
32645ffb0c9bSToomas Soome extern void CompleteDeregistration(mDNS *const m, AuthRecord *rr);
32655ffb0c9bSToomas Soome extern void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheRecord *const rr, const QC_result AddRecord);
32665ffb0c9bSToomas Soome extern void AnswerQuestionByFollowingCNAME(mDNS *const m, DNSQuestion *q, ResourceRecord *rr);
32675ffb0c9bSToomas Soome extern char *InterfaceNameForID(mDNS *const m, const mDNSInterfaceID InterfaceID);
3268*472cd20dSToomas Soome #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
32695ffb0c9bSToomas Soome extern void DNSServerChangeForQuestion(mDNS *const m, DNSQuestion *q, DNSServer *newServer);
3270*472cd20dSToomas Soome #endif
32715ffb0c9bSToomas Soome extern void ActivateUnicastRegistration(mDNS *const m, AuthRecord *const rr);
32725ffb0c9bSToomas Soome extern void CheckSuppressUnusableQuestions(mDNS *const m);
32735ffb0c9bSToomas Soome extern void RetrySearchDomainQuestions(mDNS *const m);
32745ffb0c9bSToomas Soome extern mDNSBool DomainEnumQuery(const domainname *qname);
32755ffb0c9bSToomas Soome extern mStatus UpdateKeepaliveRData(mDNS *const m, AuthRecord *rr, NetworkInterfaceInfo *const intf, mDNSBool updateMac, char *ethAddr);
32765ffb0c9bSToomas Soome extern void  UpdateKeepaliveRMACAsync(mDNS *const m, void *context);
3277c65ebfc7SToomas Soome extern void UpdateRMAC(mDNS *const m, void *context);
32785ffb0c9bSToomas Soome 
32795ffb0c9bSToomas Soome // Used only in logging to restrict the number of /etc/hosts entries printed
32805ffb0c9bSToomas Soome extern void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result);
32815ffb0c9bSToomas Soome // exported for using the hash for /etc/hosts AuthRecords
3282c65ebfc7SToomas Soome extern AuthGroup *AuthGroupForName(AuthHash *r, const mDNSu32 namehash, const domainname *const name);
3283c65ebfc7SToomas Soome extern AuthGroup *AuthGroupForRecord(AuthHash *r, const ResourceRecord *const rr);
32845ffb0c9bSToomas Soome extern AuthGroup *InsertAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr);
32855ffb0c9bSToomas Soome extern AuthGroup *RemoveAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr);
32865ffb0c9bSToomas Soome 
32875ffb0c9bSToomas Soome #if APPLE_OSX_mDNSResponder
32885ffb0c9bSToomas Soome // For now this LocalSleepProxy stuff is specific to Mac OS X.
32895ffb0c9bSToomas Soome // In the future, if there's demand, we may see if we can abstract it out cleanly into the platform layer
32903b436d06SToomas Soome extern mStatus ActivateLocalProxy(NetworkInterfaceInfo *const intf, mDNSBool offloadKeepAlivesOnly, mDNSBool *keepaliveOnly);
32915ffb0c9bSToomas Soome extern mDNSBool SupportsInNICProxy(NetworkInterfaceInfo *const intf);
32925ffb0c9bSToomas Soome #endif
32935ffb0c9bSToomas Soome 
3294c65ebfc7SToomas Soome typedef void ProxyCallback (void *socket, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr,
32955ffb0c9bSToomas Soome     const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context);
3296c65ebfc7SToomas Soome extern void mDNSPlatformInitDNSProxySkts(ProxyCallback *UDPCallback, ProxyCallback *TCPCallback);
32975ffb0c9bSToomas Soome extern void mDNSPlatformCloseDNSProxySkts(mDNS *const m);
32985ffb0c9bSToomas Soome extern void mDNSPlatformDisposeProxyContext(void *context);
32995ffb0c9bSToomas Soome extern mDNSu8 *DNSProxySetAttributes(DNSQuestion *q, DNSMessageHeader *h, DNSMessage *msg, mDNSu8 *start, mDNSu8 *limit);
33005ffb0c9bSToomas Soome 
33015ffb0c9bSToomas Soome #if APPLE_OSX_mDNSResponder
3302*472cd20dSToomas Soome extern void mDNSPlatformGetDNSRoutePolicy(DNSQuestion *q);
33035ffb0c9bSToomas Soome #endif
3304c65ebfc7SToomas Soome extern void mDNSPlatformSetSocktOpt(void *sock, mDNSTransport_Type transType, mDNSAddr_Type addrType, const DNSQuestion *q);
33055ffb0c9bSToomas Soome extern mDNSs32 mDNSPlatformGetPID(void);
3306cda73f64SToomas Soome extern mDNSBool mDNSValidKeepAliveRecord(AuthRecord *rr);
3307c65ebfc7SToomas Soome extern mDNSBool CacheRecordRmvEventsForQuestion(mDNS *const m, DNSQuestion *q);
3308*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, RANDOM_AWDL_HOSTNAME)
3309*472cd20dSToomas Soome extern void GetRandomUUIDLabel(domainlabel *label);
3310*472cd20dSToomas Soome extern void GetRandomUUIDLocalHostname(domainname *hostname);
3311*472cd20dSToomas Soome #endif
3312*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, METRICS)
3313*472cd20dSToomas Soome extern void uDNSMetricsClear(uDNSMetrics *metrics);
3314*472cd20dSToomas Soome #endif
33155ffb0c9bSToomas Soome 
33165ffb0c9bSToomas Soome // ***************************************************************************
33175ffb0c9bSToomas Soome #if 0
33185ffb0c9bSToomas Soome #pragma mark -
33195ffb0c9bSToomas Soome #pragma mark - Sleep Proxy
33205ffb0c9bSToomas Soome #endif
33215ffb0c9bSToomas Soome 
33225ffb0c9bSToomas Soome // Sleep Proxy Server Property Encoding
33235ffb0c9bSToomas Soome //
33245ffb0c9bSToomas Soome // Sleep Proxy Servers are advertised using a structured service name, consisting of four
33255ffb0c9bSToomas Soome // metrics followed by a human-readable name. The metrics assist clients in deciding which
33265ffb0c9bSToomas Soome // Sleep Proxy Server(s) to use when multiple are available on the network. Each metric
33275ffb0c9bSToomas Soome // is a two-digit decimal number in the range 10-99. Lower metrics are generally better.
33285ffb0c9bSToomas Soome //
33295ffb0c9bSToomas Soome //   AA-BB-CC-DD.FF Name
33305ffb0c9bSToomas Soome //
33315ffb0c9bSToomas Soome // Metrics:
33325ffb0c9bSToomas Soome //
33335ffb0c9bSToomas Soome // AA = Intent
33345ffb0c9bSToomas Soome // BB = Portability
33355ffb0c9bSToomas Soome // CC = Marginal Power
33365ffb0c9bSToomas Soome // DD = Total Power
33375ffb0c9bSToomas Soome // FF = Features Supported (Currently TCP Keepalive only)
33385ffb0c9bSToomas Soome //
33395ffb0c9bSToomas Soome //
33405ffb0c9bSToomas Soome // ** Intent Metric **
33415ffb0c9bSToomas Soome //
33425ffb0c9bSToomas Soome // 20 = Dedicated Sleep Proxy Server -- a device, permanently powered on,
33435ffb0c9bSToomas Soome //      installed for the express purpose of providing Sleep Proxy Service.
33445ffb0c9bSToomas Soome //
33455ffb0c9bSToomas Soome // 30 = Primary Network Infrastructure Hardware -- a router, DHCP server, NAT gateway,
33465ffb0c9bSToomas Soome //      or similar permanently installed device which is permanently powered on.
33475ffb0c9bSToomas Soome //      This is hardware designed for the express purpose of being network
33485ffb0c9bSToomas Soome //      infrastructure, and for most home users is typically a single point
33495ffb0c9bSToomas Soome //      of failure for the local network -- e.g. most home users only have
33505ffb0c9bSToomas Soome //      a single NAT gateway / DHCP server. Even though in principle the
33515ffb0c9bSToomas Soome //      hardware might technically be capable of running different software,
33525ffb0c9bSToomas Soome //      a typical user is unlikely to do that. e.g. AirPort base station.
33535ffb0c9bSToomas Soome //
33545ffb0c9bSToomas Soome // 40 = Primary Network Infrastructure Software -- a general-purpose computer
33555ffb0c9bSToomas Soome //      (e.g. Mac, Windows, Linux, etc.) which is currently running DHCP server
33565ffb0c9bSToomas Soome //      or NAT gateway software, but the user could choose to turn that off
33575ffb0c9bSToomas Soome //      fairly easily. e.g. iMac running Internet Sharing
33585ffb0c9bSToomas Soome //
33595ffb0c9bSToomas Soome // 50 = Secondary Network Infrastructure Hardware -- like primary infrastructure
33605ffb0c9bSToomas Soome //      hardware, except not a single point of failure for the entire local network.
33615ffb0c9bSToomas Soome //      For example, an AirPort base station in bridge mode. This may have clients
33625ffb0c9bSToomas Soome //      associated with it, and if it goes away those clients will be inconvenienced,
33635ffb0c9bSToomas Soome //      but unlike the NAT gateway / DHCP server, the entire local network is not
33645ffb0c9bSToomas Soome //      dependent on it.
33655ffb0c9bSToomas Soome //
33665ffb0c9bSToomas Soome // 60 = Secondary Network Infrastructure Software -- like 50, but in a general-
33675ffb0c9bSToomas Soome //      purpose CPU.
33685ffb0c9bSToomas Soome //
33695ffb0c9bSToomas Soome // 70 = Incidentally Available Hardware -- a device which has no power switch
33705ffb0c9bSToomas Soome //      and is generally left powered on all the time. Even though it is not a
33715ffb0c9bSToomas Soome //      part of what we conventionally consider network infrastructure (router,
33725ffb0c9bSToomas Soome //      DHCP, NAT, DNS, etc.), and the rest of the network can operate fine
33735ffb0c9bSToomas Soome //      without it, since it's available and unlikely to be turned off, it is a
33745ffb0c9bSToomas Soome //      reasonable candidate for providing Sleep Proxy Service e.g. Apple TV,
33755ffb0c9bSToomas Soome //      or an AirPort base station in client mode, associated with an existing
33765ffb0c9bSToomas Soome //      wireless network (e.g. AirPort Express connected to a music system, or
33775ffb0c9bSToomas Soome //      being used to share a USB printer).
33785ffb0c9bSToomas Soome //
33795ffb0c9bSToomas Soome // 80 = Incidentally Available Software -- a general-purpose computer which
33805ffb0c9bSToomas Soome //      happens at this time to be set to "never sleep", and as such could be
33815ffb0c9bSToomas Soome //      useful as a Sleep Proxy Server, but has not been intentionally provided
33825ffb0c9bSToomas Soome //      for this purpose. Of all the Intent Metric categories this is the
33835ffb0c9bSToomas Soome //      one most likely to be shut down or put to sleep without warning.
33845ffb0c9bSToomas Soome //      However, if nothing else is availalable, it may be better than nothing.
33855ffb0c9bSToomas Soome //      e.g. Office computer in the workplace which has been set to "never sleep"
33865ffb0c9bSToomas Soome //
33875ffb0c9bSToomas Soome //
33885ffb0c9bSToomas Soome // ** Portability Metric **
33895ffb0c9bSToomas Soome //
33905ffb0c9bSToomas Soome // Inversely related to mass of device, on the basis that, all other things
33915ffb0c9bSToomas Soome // being equal, heavier devices are less likely to be moved than lighter devices.
33925ffb0c9bSToomas Soome // E.g. A MacBook running Internet Sharing is probably more likely to be
33935ffb0c9bSToomas Soome // put to sleep and taken away than a Mac Pro running Internet Sharing.
33945ffb0c9bSToomas Soome // The Portability Metric is a logarithmic decibel scale, computed by taking the
33955ffb0c9bSToomas Soome // (approximate) mass of the device in milligrammes, taking the base 10 logarithm
33965ffb0c9bSToomas Soome // of that, multiplying by 10, and subtracting the result from 100:
33975ffb0c9bSToomas Soome //
33985ffb0c9bSToomas Soome //   Portability Metric = 100 - (log10(mg) * 10)
33995ffb0c9bSToomas Soome //
34005ffb0c9bSToomas Soome // The Portability Metric is not necessarily computed literally from the actual
34015ffb0c9bSToomas Soome // mass of the device; the intent is just that lower numbers indicate more
34025ffb0c9bSToomas Soome // permanent devices, and higher numbers indicate devices more likely to be
34035ffb0c9bSToomas Soome // removed from the network, e.g., in order of increasing portability:
34045ffb0c9bSToomas Soome //
34055ffb0c9bSToomas Soome // Mac Pro < iMac < Laptop < iPhone
34065ffb0c9bSToomas Soome //
34075ffb0c9bSToomas Soome // Example values:
34085ffb0c9bSToomas Soome //
34095ffb0c9bSToomas Soome // 10 = 1 metric tonne
34105ffb0c9bSToomas Soome // 40 = 1kg
34115ffb0c9bSToomas Soome // 70 = 1g
34125ffb0c9bSToomas Soome // 90 = 10mg
34135ffb0c9bSToomas Soome //
34145ffb0c9bSToomas Soome //
34155ffb0c9bSToomas Soome // ** Marginal Power and Total Power Metrics **
34165ffb0c9bSToomas Soome //
34175ffb0c9bSToomas Soome // The Marginal Power Metric is the power difference between sleeping and staying awake
34185ffb0c9bSToomas Soome // to be a Sleep Proxy Server.
34195ffb0c9bSToomas Soome //
34205ffb0c9bSToomas Soome // The Total Power Metric is the total power consumption when being Sleep Proxy Server.
34215ffb0c9bSToomas Soome //
34225ffb0c9bSToomas Soome // The Power Metrics use a logarithmic decibel scale, computed as ten times the
34235ffb0c9bSToomas Soome // base 10 logarithm of the (approximate) power in microwatts:
34245ffb0c9bSToomas Soome //
34255ffb0c9bSToomas Soome //   Power Metric = log10(uW) * 10
34265ffb0c9bSToomas Soome //
34275ffb0c9bSToomas Soome // Higher values indicate higher power consumption. Example values:
34285ffb0c9bSToomas Soome //
34295ffb0c9bSToomas Soome // 10 =  10 uW
34305ffb0c9bSToomas Soome // 20 = 100 uW
34315ffb0c9bSToomas Soome // 30 =   1 mW
34325ffb0c9bSToomas Soome // 60 =   1 W
34335ffb0c9bSToomas Soome // 90 =   1 kW
34345ffb0c9bSToomas Soome 
34355ffb0c9bSToomas Soome typedef enum
34365ffb0c9bSToomas Soome {
34375ffb0c9bSToomas Soome     mDNSSleepProxyMetric_Dedicated          = 20,
34385ffb0c9bSToomas Soome     mDNSSleepProxyMetric_PrimaryHardware    = 30,
34395ffb0c9bSToomas Soome     mDNSSleepProxyMetric_PrimarySoftware    = 40,
34405ffb0c9bSToomas Soome     mDNSSleepProxyMetric_SecondaryHardware  = 50,
34415ffb0c9bSToomas Soome     mDNSSleepProxyMetric_SecondarySoftware  = 60,
34425ffb0c9bSToomas Soome     mDNSSleepProxyMetric_IncidentalHardware = 70,
34435ffb0c9bSToomas Soome     mDNSSleepProxyMetric_IncidentalSoftware = 80
34445ffb0c9bSToomas Soome } mDNSSleepProxyMetric;
34455ffb0c9bSToomas Soome 
34465ffb0c9bSToomas Soome typedef enum
34475ffb0c9bSToomas Soome {
34485ffb0c9bSToomas Soome     mDNS_NoWake        = 0, // System does not support Wake on LAN
34495ffb0c9bSToomas Soome     mDNS_WakeOnAC      = 1, // System supports Wake on LAN when connected to AC power only
34505ffb0c9bSToomas Soome     mDNS_WakeOnBattery = 2  // System supports Wake on LAN on battery
34515ffb0c9bSToomas Soome } mDNSWakeForNetworkAccess;
34525ffb0c9bSToomas Soome 
34535ffb0c9bSToomas Soome extern void mDNSCoreBeSleepProxyServer_internal(mDNS *const m, mDNSu8 sps, mDNSu8 port, mDNSu8 marginalpower, mDNSu8 totpower, mDNSu8 features);
34545ffb0c9bSToomas Soome #define mDNSCoreBeSleepProxyServer(M,S,P,MP,TP,F)                       \
34555ffb0c9bSToomas Soome     do { mDNS_Lock(m); mDNSCoreBeSleepProxyServer_internal((M),(S),(P),(MP),(TP),(F)); mDNS_Unlock(m); } while(0)
34565ffb0c9bSToomas Soome 
34575ffb0c9bSToomas Soome extern void FindSPSInCache(mDNS *const m, const DNSQuestion *const q, const CacheRecord *sps[3]);
34585ffb0c9bSToomas Soome #define PrototypeSPSName(X) ((X)[0] >= 11 && (X)[3] == '-' && (X)[ 4] == '9' && (X)[ 5] == '9' && \
34595ffb0c9bSToomas Soome                              (X)[6] == '-' && (X)[ 7] == '9' && (X)[ 8] == '9' && \
34605ffb0c9bSToomas Soome                              (X)[9] == '-' && (X)[10] == '9' && (X)[11] == '9'    )
34615ffb0c9bSToomas Soome #define ValidSPSName(X) ((X)[0] >= 5 && mDNSIsDigit((X)[1]) && mDNSIsDigit((X)[2]) && mDNSIsDigit((X)[4]) && mDNSIsDigit((X)[5]))
34625ffb0c9bSToomas Soome #define SPSMetric(X) (!ValidSPSName(X) || PrototypeSPSName(X) ? 1000000 : \
34635ffb0c9bSToomas Soome                       ((X)[1]-'0') * 100000 + ((X)[2]-'0') * 10000 + ((X)[4]-'0') * 1000 + ((X)[5]-'0') * 100 + ((X)[7]-'0') * 10 + ((X)[8]-'0'))
34645ffb0c9bSToomas Soome #define LocalSPSMetric(X) ( (X)->SPSType * 10000 + (X)->SPSPortability * 100 + (X)->SPSMarginalPower)
34655ffb0c9bSToomas Soome #define SPSFeatures(X) ((X)[0] >= 13 && (X)[12] =='.' ? ((X)[13]-'0') : 0 )
34665ffb0c9bSToomas Soome 
34675ffb0c9bSToomas Soome #define MD5_DIGEST_LENGTH   16          /* digest length in bytes */
34685ffb0c9bSToomas Soome #define MD5_BLOCK_BYTES     64          /* block size in bytes */
34695ffb0c9bSToomas Soome #define MD5_BLOCK_LONG       (MD5_BLOCK_BYTES / sizeof(mDNSu32))
34705ffb0c9bSToomas Soome 
34715ffb0c9bSToomas Soome typedef struct MD5state_st
34725ffb0c9bSToomas Soome {
34735ffb0c9bSToomas Soome     mDNSu32 A,B,C,D;
34745ffb0c9bSToomas Soome     mDNSu32 Nl,Nh;
34755ffb0c9bSToomas Soome     mDNSu32 data[MD5_BLOCK_LONG];
3476*472cd20dSToomas Soome     mDNSu32 num;
34775ffb0c9bSToomas Soome } MD5_CTX;
34785ffb0c9bSToomas Soome 
34795ffb0c9bSToomas Soome extern int MD5_Init(MD5_CTX *c);
34805ffb0c9bSToomas Soome extern int MD5_Update(MD5_CTX *c, const void *data, unsigned long len);
34815ffb0c9bSToomas Soome extern int MD5_Final(unsigned char *md, MD5_CTX *c);
34825ffb0c9bSToomas Soome 
34834b22b933Srs // ***************************************************************************
34844b22b933Srs #if 0
34855ffb0c9bSToomas Soome #pragma mark -
34864b22b933Srs #pragma mark - Compile-Time assertion checks
34874b22b933Srs #endif
34884b22b933Srs 
34894b22b933Srs // Some C compiler cleverness. We can make the compiler check certain things for
34904b22b933Srs // us, and report compile-time errors if anything is wrong. The usual way to do
34914b22b933Srs // this would be to use a run-time "if" statement, but then you don't find out
34924b22b933Srs // what's wrong until you run the software. This way, if the assertion condition
34934b22b933Srs // is false, the array size is negative, and the complier complains immediately.
34944b22b933Srs 
34955ffb0c9bSToomas Soome struct CompileTimeAssertionChecks_mDNS
34965ffb0c9bSToomas Soome {
34975ffb0c9bSToomas Soome     // Check that the compiler generated our on-the-wire packet format structure definitions
34985ffb0c9bSToomas Soome     // properly packed, without adding padding bytes to align fields on 32-bit or 64-bit boundaries.
34995ffb0c9bSToomas Soome     char assert0[(sizeof(rdataSRV)         == 262                          ) ? 1 : -1];
35005ffb0c9bSToomas Soome     char assert1[(sizeof(DNSMessageHeader) ==  12                          ) ? 1 : -1];
35015ffb0c9bSToomas Soome     char assert2[(sizeof(DNSMessage)       ==  12+AbsoluteMaxDNSMessageData) ? 1 : -1];
35025ffb0c9bSToomas Soome     char assert3[(sizeof(mDNSs8)           ==   1                          ) ? 1 : -1];
35035ffb0c9bSToomas Soome     char assert4[(sizeof(mDNSu8)           ==   1                          ) ? 1 : -1];
35045ffb0c9bSToomas Soome     char assert5[(sizeof(mDNSs16)          ==   2                          ) ? 1 : -1];
35055ffb0c9bSToomas Soome     char assert6[(sizeof(mDNSu16)          ==   2                          ) ? 1 : -1];
35065ffb0c9bSToomas Soome     char assert7[(sizeof(mDNSs32)          ==   4                          ) ? 1 : -1];
35075ffb0c9bSToomas Soome     char assert8[(sizeof(mDNSu32)          ==   4                          ) ? 1 : -1];
35085ffb0c9bSToomas Soome     char assert9[(sizeof(mDNSOpaque16)     ==   2                          ) ? 1 : -1];
35095ffb0c9bSToomas Soome     char assertA[(sizeof(mDNSOpaque32)     ==   4                          ) ? 1 : -1];
35105ffb0c9bSToomas Soome     char assertB[(sizeof(mDNSOpaque128)    ==  16                          ) ? 1 : -1];
35115ffb0c9bSToomas Soome     char assertC[(sizeof(CacheRecord  )    ==  sizeof(CacheGroup)          ) ? 1 : -1];
35125ffb0c9bSToomas Soome     char assertD[(sizeof(int)              >=  4                           ) ? 1 : -1];
35135ffb0c9bSToomas Soome     char assertE[(StandardAuthRDSize       >=  256                         ) ? 1 : -1];
35145ffb0c9bSToomas Soome     char assertF[(sizeof(EthernetHeader)   ==   14                         ) ? 1 : -1];
35155ffb0c9bSToomas Soome     char assertG[(sizeof(ARP_EthIP     )   ==   28                         ) ? 1 : -1];
35165ffb0c9bSToomas Soome     char assertH[(sizeof(IPv4Header    )   ==   20                         ) ? 1 : -1];
35175ffb0c9bSToomas Soome     char assertI[(sizeof(IPv6Header    )   ==   40                         ) ? 1 : -1];
35185ffb0c9bSToomas Soome     char assertJ[(sizeof(IPv6NDP       )   ==   24                         ) ? 1 : -1];
35195ffb0c9bSToomas Soome     char assertK[(sizeof(UDPHeader     )   ==    8                         ) ? 1 : -1];
35205ffb0c9bSToomas Soome     char assertL[(sizeof(IKEHeader     )   ==   28                         ) ? 1 : -1];
35215ffb0c9bSToomas Soome     char assertM[(sizeof(TCPHeader     )   ==   20                         ) ? 1 : -1];
3522c65ebfc7SToomas Soome 	char assertN[(sizeof(rdataOPT)		   ==   24                         ) ? 1 : -1];
3523c65ebfc7SToomas Soome 	char assertP[(sizeof(PCPMapRequest)    ==   60                         ) ? 1 : -1];
3524c65ebfc7SToomas Soome 	char assertQ[(sizeof(PCPMapReply)      ==   60                         ) ? 1 : -1];
3525c65ebfc7SToomas Soome 
35265ffb0c9bSToomas Soome 
35275ffb0c9bSToomas Soome     // Check our structures are reasonable sizes. Including overly-large buffers, or embedding
35285ffb0c9bSToomas Soome     // other overly-large structures instead of having a pointer to them, can inadvertently
35295ffb0c9bSToomas Soome     // cause structure sizes (and therefore memory usage) to balloon unreasonably.
35305ffb0c9bSToomas Soome     char sizecheck_RDataBody           [(sizeof(RDataBody)            ==   264) ? 1 : -1];
35315ffb0c9bSToomas Soome     char sizecheck_ResourceRecord      [(sizeof(ResourceRecord)       <=    72) ? 1 : -1];
3532*472cd20dSToomas Soome     char sizecheck_AuthRecord          [(sizeof(AuthRecord)           <=  1176) ? 1 : -1];
35335ffb0c9bSToomas Soome     char sizecheck_CacheRecord         [(sizeof(CacheRecord)          <=   232) ? 1 : -1];
35345ffb0c9bSToomas Soome     char sizecheck_CacheGroup          [(sizeof(CacheGroup)           <=   232) ? 1 : -1];
3535*472cd20dSToomas Soome     char sizecheck_DNSQuestion         [(sizeof(DNSQuestion)          <=  1216) ? 1 : -1];
3536*472cd20dSToomas Soome     char sizecheck_ZoneData            [(sizeof(ZoneData)             <=  2048) ? 1 : -1];
35375ffb0c9bSToomas Soome     char sizecheck_NATTraversalInfo    [(sizeof(NATTraversalInfo)     <=   200) ? 1 : -1];
35385ffb0c9bSToomas Soome     char sizecheck_HostnameInfo        [(sizeof(HostnameInfo)         <=  3050) ? 1 : -1];
3539*472cd20dSToomas Soome #if !MDNSRESPONDER_SUPPORTS(APPLE, QUERIER)
3540*472cd20dSToomas Soome     char sizecheck_DNSServer           [(sizeof(DNSServer)            <=   328) ? 1 : -1];
3541*472cd20dSToomas Soome #endif
3542*472cd20dSToomas Soome     char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <=  9000) ? 1 : -1];
3543*472cd20dSToomas Soome     char sizecheck_ServiceRecordSet    [(sizeof(ServiceRecordSet)     <=  4760) ? 1 : -1];
3544*472cd20dSToomas Soome     char sizecheck_DomainAuthInfo      [(sizeof(DomainAuthInfo)       <=   944) ? 1 : -1];
35455ffb0c9bSToomas Soome #if APPLE_OSX_mDNSResponder
3546*472cd20dSToomas Soome     char sizecheck_ClientTunnel        [(sizeof(ClientTunnel)         <=  1560) ? 1 : -1];
3547*472cd20dSToomas Soome #endif
3548*472cd20dSToomas Soome #if MDNSRESPONDER_SUPPORTS(APPLE, OS_LOG)
3549*472cd20dSToomas Soome     // structure size is assumed by LogRedact routine.
3550*472cd20dSToomas Soome     char sizecheck_mDNSAddr            [(sizeof(mDNSAddr)             ==    20) ? 1 : -1];
3551*472cd20dSToomas Soome     char sizecheck_mDNSv4Addr          [(sizeof(mDNSv4Addr)           ==     4) ? 1 : -1];
3552*472cd20dSToomas Soome     char sizecheck_mDNSv6Addr          [(sizeof(mDNSv6Addr)           ==    16) ? 1 : -1];
35535ffb0c9bSToomas Soome #endif
35545ffb0c9bSToomas Soome };
35555ffb0c9bSToomas Soome 
35565ffb0c9bSToomas Soome // Routine to initialize device-info TXT record contents
35575ffb0c9bSToomas Soome mDNSu32 initializeDeviceInfoTXT(mDNS *m, mDNSu8 *ptr);
35585ffb0c9bSToomas Soome 
35594b22b933Srs // ***************************************************************************
35604b22b933Srs 
35614b22b933Srs #ifdef __cplusplus
35625ffb0c9bSToomas Soome }
35634b22b933Srs #endif
35644b22b933Srs 
35654b22b933Srs #endif
3566