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
1478