xref: /titanic_52/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSEmbeddedAPI.h (revision 5ffb0c9b03b5149ff4f5821a62be4a52408ada2a)
14b22b933Srs200217 /* -*- Mode: C; tab-width: 4 -*-
24b22b933Srs200217  *
3*5ffb0c9bSToomas Soome  * Copyright (c) 2002-2013 Apple Computer, Inc. All rights reserved.
44b22b933Srs200217  *
54b22b933Srs200217  * Licensed under the Apache License, Version 2.0 (the "License");
64b22b933Srs200217  * you may not use this file except in compliance with the License.
74b22b933Srs200217  * You may obtain a copy of the License at
84b22b933Srs200217  *
94b22b933Srs200217  *     http://www.apache.org/licenses/LICENSE-2.0
104b22b933Srs200217  *
114b22b933Srs200217  * Unless required by applicable law or agreed to in writing, software
124b22b933Srs200217  * distributed under the License is distributed on an "AS IS" BASIS,
134b22b933Srs200217  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
144b22b933Srs200217  * See the License for the specific language governing permissions and
154b22b933Srs200217  * limitations under the License.
164b22b933Srs200217 
174b22b933Srs200217    NOTE:
184b22b933Srs200217    If you're building an application that uses DNS Service Discovery
194b22b933Srs200217    this is probably NOT the header file you're looking for.
204b22b933Srs200217    In most cases you will want to use /usr/include/dns_sd.h instead.
214b22b933Srs200217 
224b22b933Srs200217    This header file defines the lowest level raw interface to mDNSCore,
234b22b933Srs200217    which is appropriate *only* on tiny embedded systems where everything
244b22b933Srs200217    runs in a single address space and memory is extremely constrained.
254b22b933Srs200217    All the APIs here are malloc-free, which means that the caller is
264b22b933Srs200217    responsible for passing in a pointer to the relevant storage that
274b22b933Srs200217    will be used in the execution of that call, and (when called with
284b22b933Srs200217    correct parameters) all the calls are guaranteed to succeed. There
294b22b933Srs200217    is never a case where a call can suffer intermittent failures because
304b22b933Srs200217    the implementation calls malloc() and sometimes malloc() returns NULL
314b22b933Srs200217    because memory is so limited that no more is available.
324b22b933Srs200217    This is primarily for devices that need to have precisely known fixed
334b22b933Srs200217    memory requirements, with absolutely no uncertainty or run-time variation,
344b22b933Srs200217    but that certainty comes at a cost of more difficult programming.
354b22b933Srs200217 
364b22b933Srs200217    For applications running on general-purpose desktop operating systems
374b22b933Srs200217    (Mac OS, Linux, Solaris, Windows, etc.) the API you should use is
384b22b933Srs200217    /usr/include/dns_sd.h, which defines the API by which multiple
394b22b933Srs200217    independent client processes communicate their DNS Service Discovery
404b22b933Srs200217    requests to a single "mdnsd" daemon running in the background.
414b22b933Srs200217 
424b22b933Srs200217    Even on platforms that don't run multiple independent processes in
434b22b933Srs200217    multiple independent address spaces, you can still use the preferred
444b22b933Srs200217    dns_sd.h APIs by linking in "dnssd_clientshim.c", which implements
454b22b933Srs200217    the standard "dns_sd.h" API calls, allocates any required storage
464b22b933Srs200217    using malloc(), and then calls through to the low-level malloc-free
474b22b933Srs200217    mDNSCore routines defined here. This has the benefit that even though
484b22b933Srs200217    you're running on a small embedded system with a single address space,
494b22b933Srs200217    you can still use the exact same client C code as you'd use on a
504b22b933Srs200217    general-purpose desktop system.
514b22b933Srs200217 
524b22b933Srs200217  */
534b22b933Srs200217 
54*5ffb0c9bSToomas Soome #ifndef __mDNSEmbeddedAPI_h
55*5ffb0c9bSToomas Soome #define __mDNSEmbeddedAPI_h
564b22b933Srs200217 
57*5ffb0c9bSToomas Soome #if defined(EFI32) || defined(EFI64) || defined(EFIX64)
58*5ffb0c9bSToomas Soome // EFI doesn't have stdarg.h unless it's building with GCC.
594b22b933Srs200217 #include "Tiano.h"
60*5ffb0c9bSToomas Soome #if !defined(__GNUC__)
614b22b933Srs200217 #define va_list         VA_LIST
624b22b933Srs200217 #define va_start(a, b)  VA_START(a, b)
634b22b933Srs200217 #define va_end(a)       VA_END(a)
644b22b933Srs200217 #define va_arg(a, b)    VA_ARG(a, b)
65*5ffb0c9bSToomas Soome #endif
664b22b933Srs200217 #else
674b22b933Srs200217 #include <stdarg.h>     // stdarg.h is required for for va_list support for the mDNS_vsnprintf declaration
684b22b933Srs200217 #endif
694b22b933Srs200217 
704b22b933Srs200217 #include "mDNSDebug.h"
71*5ffb0c9bSToomas Soome #if APPLE_OSX_mDNSResponder
72*5ffb0c9bSToomas Soome #include <uuid/uuid.h>
73*5ffb0c9bSToomas Soome #endif
744b22b933Srs200217 
754b22b933Srs200217 #ifdef __cplusplus
764b22b933Srs200217 extern "C" {
774b22b933Srs200217 #endif
784b22b933Srs200217 
794b22b933Srs200217 // ***************************************************************************
80*5ffb0c9bSToomas Soome // Feature removal compile options & limited resource targets
81*5ffb0c9bSToomas Soome 
82*5ffb0c9bSToomas Soome // The following compile options are responsible for removing certain features from mDNSCore to reduce the
83*5ffb0c9bSToomas Soome // memory footprint for use in embedded systems with limited resources.
84*5ffb0c9bSToomas Soome 
85*5ffb0c9bSToomas Soome // UNICAST_DISABLED - disables unicast DNS functionality, including Wide Area Bonjour
86*5ffb0c9bSToomas Soome // ANONYMOUS_DISABLED - disables anonymous functionality
87*5ffb0c9bSToomas Soome // DNSSEC_DISABLED - disables DNSSEC functionality
88*5ffb0c9bSToomas Soome // SPC_DISABLED - disables Bonjour Sleep Proxy client
89*5ffb0c9bSToomas Soome // IDLESLEEPCONTROL_DISABLED - disables sleep control for Bonjour Sleep Proxy clients
90*5ffb0c9bSToomas Soome 
91*5ffb0c9bSToomas Soome // In order to disable the above features pass the option to your compiler, e.g. -D UNICAST_DISABLED
92*5ffb0c9bSToomas Soome 
93*5ffb0c9bSToomas Soome // Additionally, the LIMITED_RESOURCES_TARGET compile option will eliminate caching and
94*5ffb0c9bSToomas Soome // and reduce the maximum DNS message sizes.
95*5ffb0c9bSToomas Soome 
96*5ffb0c9bSToomas Soome #ifdef LIMITED_RESOURCES_TARGET
97*5ffb0c9bSToomas Soome // Don't support jumbo frames
98*5ffb0c9bSToomas Soome #define AbsoluteMaxDNSMessageData 	1500
99*5ffb0c9bSToomas Soome // By the time you add IPv6 header (40 bytes) UDP header (8 bytes) and DNS message header (12 bytes)
100*5ffb0c9bSToomas Soome // this makes 1560 which is 60 bytes over the standard Ethernet MTU. D'oh!
101*5ffb0c9bSToomas Soome 
102*5ffb0c9bSToomas Soome // StandardAuthRDSize is 264 (256+8), which is large enough to hold a maximum-sized SRV record (6 + 256 bytes)
103*5ffb0c9bSToomas Soome #define MaximumRDSize				264
104*5ffb0c9bSToomas Soome // Don't cache anything
105*5ffb0c9bSToomas Soome #define AUTH_HASH_SLOTS 			1
106*5ffb0c9bSToomas Soome #define CACHE_HASH_SLOTS			1
107*5ffb0c9bSToomas Soome #endif
108*5ffb0c9bSToomas Soome 
109*5ffb0c9bSToomas Soome // ***************************************************************************
1104b22b933Srs200217 // Function scope indicators
1114b22b933Srs200217 
1124b22b933Srs200217 // If you see "mDNSlocal" before a function name in a C file, it means the function is not callable outside this file
1134b22b933Srs200217 #ifndef mDNSlocal
1144b22b933Srs200217 #define mDNSlocal static
1154b22b933Srs200217 #endif
1164b22b933Srs200217 // If you see "mDNSexport" before a symbol in a C file, it means the symbol is exported for use by clients
1174b22b933Srs200217 // For every "mDNSexport" in a C file, there needs to be a corresponding "extern" declaration in some header file
1184b22b933Srs200217 // (When a C file #includes a header file, the "extern" declarations tell the compiler:
1194b22b933Srs200217 // "This symbol exists -- but not necessarily in this C file.")
1204b22b933Srs200217 #ifndef mDNSexport
1214b22b933Srs200217 #define mDNSexport
1224b22b933Srs200217 #endif
1234b22b933Srs200217 
1244b22b933Srs200217 // Explanation: These local/export markers are a little habit of mine for signaling the programmers' intentions.
1254b22b933Srs200217 // When "mDNSlocal" is just a synonym for "static", and "mDNSexport" is a complete no-op, you could be
1264b22b933Srs200217 // forgiven for asking what purpose they serve. The idea is that if you see "mDNSexport" in front of a
1274b22b933Srs200217 // function definition it means the programmer intended it to be exported and callable from other files
1284b22b933Srs200217 // in the project. If you see "mDNSlocal" in front of a function definition it means the programmer
1294b22b933Srs200217 // intended it to be private to that file. If you see neither in front of a function definition it
1304b22b933Srs200217 // means the programmer forgot (so you should work out which it is supposed to be, and fix it).
1314b22b933Srs200217 // Using "mDNSlocal" instead of "static" makes it easier to do a textual searches for one or the other.
1324b22b933Srs200217 // For example you can do a search for "static" to find if any functions declare any local variables as "static"
1334b22b933Srs200217 // (generally a bad idea unless it's also "const", because static storage usually risks being non-thread-safe)
1344b22b933Srs200217 // without the results being cluttered with hundreds of matches for functions declared static.
1354b22b933Srs200217 // - Stuart Cheshire
1364b22b933Srs200217 
1374b22b933Srs200217 // ***************************************************************************
1384b22b933Srs200217 // Structure packing macro
1394b22b933Srs200217 
1404b22b933Srs200217 // If we're not using GNUC, it's not fatal.
1414b22b933Srs200217 // Most compilers naturally pack the on-the-wire structures correctly anyway, so a plain "struct" is usually fine.
1424b22b933Srs200217 // In the event that structures are not packed correctly, mDNS_Init() will detect this and report an error, so the
1434b22b933Srs200217 // developer will know what's wrong, and can investigate what needs to be done on that compiler to provide proper packing.
1444b22b933Srs200217 #ifndef packedstruct
1454b22b933Srs200217  #if ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9)))
1464b22b933Srs200217   #define packedstruct struct __attribute__((__packed__))
1474b22b933Srs200217   #define packedunion  union  __attribute__((__packed__))
1484b22b933Srs200217  #else
1494b22b933Srs200217   #define packedstruct struct
1504b22b933Srs200217   #define packedunion  union
1514b22b933Srs200217  #endif
1524b22b933Srs200217 #endif
1534b22b933Srs200217 
1544b22b933Srs200217 // ***************************************************************************
1554b22b933Srs200217 #if 0
1564b22b933Srs200217 #pragma mark - DNS Resource Record class and type constants
1574b22b933Srs200217 #endif
1584b22b933Srs200217 
1594b22b933Srs200217 typedef enum                            // From RFC 1035
1604b22b933Srs200217 {
1614b22b933Srs200217     kDNSClass_IN               = 1,     // Internet
1624b22b933Srs200217     kDNSClass_CS               = 2,     // CSNET
1634b22b933Srs200217     kDNSClass_CH               = 3,     // CHAOS
1644b22b933Srs200217     kDNSClass_HS               = 4,     // Hesiod
1654b22b933Srs200217     kDNSClass_NONE             = 254,   // Used in DNS UPDATE [RFC 2136]
1664b22b933Srs200217 
1674b22b933Srs200217     kDNSClass_Mask             = 0x7FFF, // Multicast DNS uses the bottom 15 bits to identify the record class...
1684b22b933Srs200217     kDNSClass_UniqueRRSet      = 0x8000, // ... and the top bit indicates that all other cached records are now invalid
1694b22b933Srs200217 
1704b22b933Srs200217     kDNSQClass_ANY             = 255,   // Not a DNS class, but a DNS query class, meaning "all classes"
1714b22b933Srs200217     kDNSQClass_UnicastResponse = 0x8000 // Top bit set in a question means "unicast response acceptable"
1724b22b933Srs200217 } DNS_ClassValues;
1734b22b933Srs200217 
1744b22b933Srs200217 typedef enum                // From RFC 1035
1754b22b933Srs200217 {
1764b22b933Srs200217     kDNSType_A = 1,         //  1 Address
1774b22b933Srs200217     kDNSType_NS,            //  2 Name Server
1784b22b933Srs200217     kDNSType_MD,            //  3 Mail Destination
1794b22b933Srs200217     kDNSType_MF,            //  4 Mail Forwarder
1804b22b933Srs200217     kDNSType_CNAME,         //  5 Canonical Name
1814b22b933Srs200217     kDNSType_SOA,           //  6 Start of Authority
1824b22b933Srs200217     kDNSType_MB,            //  7 Mailbox
1834b22b933Srs200217     kDNSType_MG,            //  8 Mail Group
1844b22b933Srs200217     kDNSType_MR,            //  9 Mail Rename
1854b22b933Srs200217     kDNSType_NULL,          // 10 NULL RR
1864b22b933Srs200217     kDNSType_WKS,           // 11 Well-known-service
1874b22b933Srs200217     kDNSType_PTR,           // 12 Domain name pointer
1884b22b933Srs200217     kDNSType_HINFO,         // 13 Host information
1894b22b933Srs200217     kDNSType_MINFO,         // 14 Mailbox information
1904b22b933Srs200217     kDNSType_MX,            // 15 Mail Exchanger
1914b22b933Srs200217     kDNSType_TXT,           // 16 Arbitrary text string
192*5ffb0c9bSToomas Soome     kDNSType_RP,            // 17 Responsible person
193*5ffb0c9bSToomas Soome     kDNSType_AFSDB,         // 18 AFS cell database
194*5ffb0c9bSToomas Soome     kDNSType_X25,           // 19 X_25 calling address
195*5ffb0c9bSToomas Soome     kDNSType_ISDN,          // 20 ISDN calling address
196*5ffb0c9bSToomas Soome     kDNSType_RT,            // 21 Router
197*5ffb0c9bSToomas Soome     kDNSType_NSAP,          // 22 NSAP address
198*5ffb0c9bSToomas Soome     kDNSType_NSAP_PTR,      // 23 Reverse NSAP lookup (deprecated)
199*5ffb0c9bSToomas Soome     kDNSType_SIG,           // 24 Security signature
200*5ffb0c9bSToomas Soome     kDNSType_KEY,           // 25 Security key
201*5ffb0c9bSToomas Soome     kDNSType_PX,            // 26 X.400 mail mapping
202*5ffb0c9bSToomas Soome     kDNSType_GPOS,          // 27 Geographical position (withdrawn)
203*5ffb0c9bSToomas Soome     kDNSType_AAAA,          // 28 IPv6 Address
204*5ffb0c9bSToomas Soome     kDNSType_LOC,           // 29 Location Information
205*5ffb0c9bSToomas Soome     kDNSType_NXT,           // 30 Next domain (security)
206*5ffb0c9bSToomas Soome     kDNSType_EID,           // 31 Endpoint identifier
207*5ffb0c9bSToomas Soome     kDNSType_NIMLOC,        // 32 Nimrod Locator
208*5ffb0c9bSToomas Soome     kDNSType_SRV,           // 33 Service record
209*5ffb0c9bSToomas Soome     kDNSType_ATMA,          // 34 ATM Address
210*5ffb0c9bSToomas Soome     kDNSType_NAPTR,         // 35 Naming Authority PoinTeR
211*5ffb0c9bSToomas Soome     kDNSType_KX,            // 36 Key Exchange
212*5ffb0c9bSToomas Soome     kDNSType_CERT,          // 37 Certification record
213*5ffb0c9bSToomas Soome     kDNSType_A6,            // 38 IPv6 Address (deprecated)
214*5ffb0c9bSToomas Soome     kDNSType_DNAME,         // 39 Non-terminal DNAME (for IPv6)
215*5ffb0c9bSToomas Soome     kDNSType_SINK,          // 40 Kitchen sink (experimental)
216*5ffb0c9bSToomas Soome     kDNSType_OPT,           // 41 EDNS0 option (meta-RR)
217*5ffb0c9bSToomas Soome     kDNSType_APL,           // 42 Address Prefix List
218*5ffb0c9bSToomas Soome     kDNSType_DS,            // 43 Delegation Signer
219*5ffb0c9bSToomas Soome     kDNSType_SSHFP,         // 44 SSH Key Fingerprint
220*5ffb0c9bSToomas Soome     kDNSType_IPSECKEY,      // 45 IPSECKEY
221*5ffb0c9bSToomas Soome     kDNSType_RRSIG,         // 46 RRSIG
222*5ffb0c9bSToomas Soome     kDNSType_NSEC,          // 47 Denial of Existence
223*5ffb0c9bSToomas Soome     kDNSType_DNSKEY,        // 48 DNSKEY
224*5ffb0c9bSToomas Soome     kDNSType_DHCID,         // 49 DHCP Client Identifier
225*5ffb0c9bSToomas Soome     kDNSType_NSEC3,         // 50 Hashed Authenticated Denial of Existence
226*5ffb0c9bSToomas Soome     kDNSType_NSEC3PARAM,    // 51 Hashed Authenticated Denial of Existence
2274b22b933Srs200217 
228*5ffb0c9bSToomas Soome     kDNSType_HIP = 55,      // 55 Host Identity Protocol
2294b22b933Srs200217 
230*5ffb0c9bSToomas Soome     kDNSType_SPF = 99,      // 99 Sender Policy Framework for E-Mail
231*5ffb0c9bSToomas Soome     kDNSType_UINFO,         // 100 IANA-Reserved
232*5ffb0c9bSToomas Soome     kDNSType_UID,           // 101 IANA-Reserved
233*5ffb0c9bSToomas Soome     kDNSType_GID,           // 102 IANA-Reserved
234*5ffb0c9bSToomas Soome     kDNSType_UNSPEC,        // 103 IANA-Reserved
235*5ffb0c9bSToomas Soome 
236*5ffb0c9bSToomas Soome     kDNSType_TKEY = 249,    // 249 Transaction key
237*5ffb0c9bSToomas Soome     kDNSType_TSIG,          // 250 Transaction signature
238*5ffb0c9bSToomas Soome     kDNSType_IXFR,          // 251 Incremental zone transfer
239*5ffb0c9bSToomas Soome     kDNSType_AXFR,          // 252 Transfer zone of authority
240*5ffb0c9bSToomas Soome     kDNSType_MAILB,         // 253 Transfer mailbox records
241*5ffb0c9bSToomas Soome     kDNSType_MAILA,         // 254 Transfer mail agent records
242*5ffb0c9bSToomas Soome     kDNSQType_ANY           // Not a DNS type, but a DNS query type, meaning "all types"
2434b22b933Srs200217 } DNS_TypeValues;
2444b22b933Srs200217 
2454b22b933Srs200217 // ***************************************************************************
2464b22b933Srs200217 #if 0
247*5ffb0c9bSToomas Soome #pragma mark -
2484b22b933Srs200217 #pragma mark - Simple types
2494b22b933Srs200217 #endif
2504b22b933Srs200217 
2514b22b933Srs200217 // mDNS defines its own names for these common types to simplify portability across
2524b22b933Srs200217 // multiple platforms that may each have their own (different) names for these types.
253*5ffb0c9bSToomas Soome typedef unsigned char mDNSBool;
2544b22b933Srs200217 typedef   signed char mDNSs8;
2554b22b933Srs200217 typedef unsigned char mDNSu8;
2564b22b933Srs200217 typedef   signed short mDNSs16;
2574b22b933Srs200217 typedef unsigned short mDNSu16;
2584b22b933Srs200217 
259*5ffb0c9bSToomas Soome // Source: http://www.unix.org/version2/whatsnew/lp64_wp.html
260*5ffb0c9bSToomas Soome // http://software.intel.com/sites/products/documentation/hpc/mkl/lin/MKL_UG_structure/Support_for_ILP64_Programming.htm
261*5ffb0c9bSToomas Soome // It can be safely assumed that int is 32bits on the platform
2624b22b933Srs200217 #if defined(_ILP64) || defined(__ILP64__)
2634b22b933Srs200217 typedef   signed int32 mDNSs32;
2644b22b933Srs200217 typedef unsigned int32 mDNSu32;
265*5ffb0c9bSToomas Soome #else
2664b22b933Srs200217 typedef   signed int mDNSs32;
2674b22b933Srs200217 typedef unsigned int mDNSu32;
2684b22b933Srs200217 #endif
2694b22b933Srs200217 
2704b22b933Srs200217 // To enforce useful type checking, we make mDNSInterfaceID be a pointer to a dummy struct
2714b22b933Srs200217 // This way, mDNSInterfaceIDs can be assigned, and compared with each other, but not with other types
2724b22b933Srs200217 // Declaring the type to be the typical generic "void *" would lack this type checking
2734b22b933Srs200217 typedef struct mDNSInterfaceID_dummystruct { void *dummy; } *mDNSInterfaceID;
2744b22b933Srs200217 
2754b22b933Srs200217 // These types are for opaque two- and four-byte identifiers.
2764b22b933Srs200217 // The "NotAnInteger" fields of the unions allow the value to be conveniently passed around in a
2774b22b933Srs200217 // register for the sake of efficiency, and compared for equality or inequality, but don't forget --
2784b22b933Srs200217 // just because it is in a register doesn't mean it is an integer. Operations like greater than,
2794b22b933Srs200217 // less than, add, multiply, increment, decrement, etc., are undefined for opaque identifiers,
2804b22b933Srs200217 // and if you make the mistake of trying to do those using the NotAnInteger field, then you'll
2814b22b933Srs200217 // find you get code that doesn't work consistently on big-endian and little-endian machines.
282*5ffb0c9bSToomas Soome #if defined(_WIN32)
283*5ffb0c9bSToomas Soome  #pragma pack(push,2)
284*5ffb0c9bSToomas Soome #elif !defined(__GNUC__)
285*5ffb0c9bSToomas Soome  #pragma pack(1)
286*5ffb0c9bSToomas Soome #endif
287*5ffb0c9bSToomas Soome typedef       union { mDNSu8 b[ 2]; mDNSu16 NotAnInteger; } mDNSOpaque16;
288*5ffb0c9bSToomas Soome typedef       union { mDNSu8 b[ 4]; mDNSu32 NotAnInteger; } mDNSOpaque32;
2894b22b933Srs200217 typedef packedunion { mDNSu8 b[ 6]; mDNSu16 w[3]; mDNSu32 l[1]; } mDNSOpaque48;
290*5ffb0c9bSToomas Soome typedef       union { mDNSu8 b[ 8]; mDNSu16 w[4]; mDNSu32 l[2]; } mDNSOpaque64;
291*5ffb0c9bSToomas Soome typedef       union { mDNSu8 b[16]; mDNSu16 w[8]; mDNSu32 l[4]; } mDNSOpaque128;
292*5ffb0c9bSToomas Soome #if defined(_WIN32)
293*5ffb0c9bSToomas Soome  #pragma pack(pop)
294*5ffb0c9bSToomas Soome #elif !defined(__GNUC__)
295*5ffb0c9bSToomas Soome  #pragma pack()
296*5ffb0c9bSToomas Soome #endif
2974b22b933Srs200217 
2984b22b933Srs200217 typedef mDNSOpaque16 mDNSIPPort;        // An IP port is a two-byte opaque identifier (not an integer)
2994b22b933Srs200217 typedef mDNSOpaque32 mDNSv4Addr;        // An IP address is a four-byte opaque identifier (not an integer)
3004b22b933Srs200217 typedef mDNSOpaque128 mDNSv6Addr;       // An IPv6 address is a 16-byte opaque identifier (not an integer)
3014b22b933Srs200217 typedef mDNSOpaque48 mDNSEthAddr;       // An Ethernet address is a six-byte opaque identifier (not an integer)
3024b22b933Srs200217 
303*5ffb0c9bSToomas Soome // Bit operations for opaque 64 bit quantity. Uses the 32 bit quantity(l[2]) to set and clear bits
304*5ffb0c9bSToomas Soome #define mDNSNBBY 8
305*5ffb0c9bSToomas Soome #define bit_set_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] |= (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
306*5ffb0c9bSToomas Soome #define bit_clr_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] &= ~(1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
307*5ffb0c9bSToomas Soome #define bit_get_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] & (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
308*5ffb0c9bSToomas Soome 
3094b22b933Srs200217 enum
3104b22b933Srs200217 {
3114b22b933Srs200217     mDNSAddrType_None    = 0,
3124b22b933Srs200217     mDNSAddrType_IPv4    = 4,
3134b22b933Srs200217     mDNSAddrType_IPv6    = 6,
3144b22b933Srs200217     mDNSAddrType_Unknown = ~0   // Special marker value used in known answer list recording
3154b22b933Srs200217 };
3164b22b933Srs200217 
317*5ffb0c9bSToomas Soome enum
318*5ffb0c9bSToomas Soome {
319*5ffb0c9bSToomas Soome     mDNSTransport_None = 0,
320*5ffb0c9bSToomas Soome     mDNSTransport_UDP  = 1,
321*5ffb0c9bSToomas Soome     mDNSTransport_TCP  = 2
322*5ffb0c9bSToomas Soome };
323*5ffb0c9bSToomas Soome 
3244b22b933Srs200217 typedef struct
3254b22b933Srs200217 {
3264b22b933Srs200217     mDNSs32 type;
3274b22b933Srs200217     union { mDNSv6Addr v6; mDNSv4Addr v4; } ip;
3284b22b933Srs200217 } mDNSAddr;
3294b22b933Srs200217 
3304b22b933Srs200217 enum { mDNSfalse = 0, mDNStrue = 1 };
3314b22b933Srs200217 
3324b22b933Srs200217 #define mDNSNULL 0L
3334b22b933Srs200217 
3344b22b933Srs200217 enum
3354b22b933Srs200217 {
3364b22b933Srs200217     mStatus_Waiting           = 1,
3374b22b933Srs200217     mStatus_NoError           = 0,
3384b22b933Srs200217 
3394b22b933Srs200217     // mDNS return values are in the range FFFE FF00 (-65792) to FFFE FFFF (-65537)
3404b22b933Srs200217     // The top end of the range (FFFE FFFF) is used for error codes;
3414b22b933Srs200217     // the bottom end of the range (FFFE FF00) is used for non-error values;
3424b22b933Srs200217 
3434b22b933Srs200217     // Error codes:
3444b22b933Srs200217     mStatus_UnknownErr                = -65537,     // First value: 0xFFFE FFFF
3454b22b933Srs200217     mStatus_NoSuchNameErr             = -65538,
3464b22b933Srs200217     mStatus_NoMemoryErr               = -65539,
3474b22b933Srs200217     mStatus_BadParamErr               = -65540,
3484b22b933Srs200217     mStatus_BadReferenceErr           = -65541,
3494b22b933Srs200217     mStatus_BadStateErr               = -65542,
3504b22b933Srs200217     mStatus_BadFlagsErr               = -65543,
3514b22b933Srs200217     mStatus_UnsupportedErr            = -65544,
3524b22b933Srs200217     mStatus_NotInitializedErr         = -65545,
3534b22b933Srs200217     mStatus_NoCache                   = -65546,
3544b22b933Srs200217     mStatus_AlreadyRegistered         = -65547,
3554b22b933Srs200217     mStatus_NameConflict              = -65548,
3564b22b933Srs200217     mStatus_Invalid                   = -65549,
3574b22b933Srs200217     mStatus_Firewall                  = -65550,
3584b22b933Srs200217     mStatus_Incompatible              = -65551,
3594b22b933Srs200217     mStatus_BadInterfaceErr           = -65552,
3604b22b933Srs200217     mStatus_Refused                   = -65553,
3614b22b933Srs200217     mStatus_NoSuchRecord              = -65554,
3624b22b933Srs200217     mStatus_NoAuth                    = -65555,
3634b22b933Srs200217     mStatus_NoSuchKey                 = -65556,
3644b22b933Srs200217     mStatus_NATTraversal              = -65557,
3654b22b933Srs200217     mStatus_DoubleNAT                 = -65558,
3664b22b933Srs200217     mStatus_BadTime                   = -65559,
3674b22b933Srs200217     mStatus_BadSig                    = -65560,     // while we define this per RFC 2845, BIND 9 returns Refused for bad/missing signatures
3684b22b933Srs200217     mStatus_BadKey                    = -65561,
3694b22b933Srs200217     mStatus_TransientErr              = -65562,     // transient failures, e.g. sending packets shortly after a network transition or wake from sleep
370*5ffb0c9bSToomas Soome     mStatus_ServiceNotRunning         = -65563,     // Background daemon not running
371*5ffb0c9bSToomas Soome     mStatus_NATPortMappingUnsupported = -65564,     // NAT doesn't support PCP, NAT-PMP or UPnP
372*5ffb0c9bSToomas Soome     mStatus_NATPortMappingDisabled    = -65565,     // NAT supports PCP, NAT-PMP or UPnP, but it's disabled by the administrator
373*5ffb0c9bSToomas Soome     mStatus_NoRouter                  = -65566,
374*5ffb0c9bSToomas Soome     mStatus_PollingMode               = -65567,
375*5ffb0c9bSToomas Soome     mStatus_Timeout                   = -65568,
376*5ffb0c9bSToomas Soome     // -65568 to -65786 currently unused; available for allocation
3774b22b933Srs200217 
3784b22b933Srs200217     // tcp connection status
3794b22b933Srs200217     mStatus_ConnPending       = -65787,
3804b22b933Srs200217     mStatus_ConnFailed        = -65788,
3814b22b933Srs200217     mStatus_ConnEstablished   = -65789,
3824b22b933Srs200217 
3834b22b933Srs200217     // Non-error values:
3844b22b933Srs200217     mStatus_GrowCache         = -65790,
3854b22b933Srs200217     mStatus_ConfigChanged     = -65791,
3864b22b933Srs200217     mStatus_MemFree           = -65792      // Last value: 0xFFFE FF00
3874b22b933Srs200217                                 // mStatus_MemFree is the last legal mDNS error code, at the end of the range allocated for mDNS
3884b22b933Srs200217 };
3894b22b933Srs200217 
3904b22b933Srs200217 typedef mDNSs32 mStatus;
391*5ffb0c9bSToomas Soome #define MaxIp 5 // Needs to be consistent with MaxInputIf in dns_services.h
392*5ffb0c9bSToomas Soome 
393*5ffb0c9bSToomas Soome typedef enum { q_stop = 0, q_start } q_state;
394*5ffb0c9bSToomas Soome typedef enum { reg_stop = 0, reg_start } reg_state;
3954b22b933Srs200217 
3964b22b933Srs200217 // RFC 1034/1035 specify that a domain label consists of a length byte plus up to 63 characters
3974b22b933Srs200217 #define MAX_DOMAIN_LABEL 63
3984b22b933Srs200217 typedef struct { mDNSu8 c[ 64]; } domainlabel;      // One label: length byte and up to 63 characters
3994b22b933Srs200217 
400*5ffb0c9bSToomas Soome // RFC 1034/1035/2181 specify that a domain name (length bytes and data bytes) may be up to 255 bytes long,
401*5ffb0c9bSToomas Soome // plus the terminating zero at the end makes 256 bytes total in the on-the-wire format.
402*5ffb0c9bSToomas Soome #define MAX_DOMAIN_NAME 256
403*5ffb0c9bSToomas Soome typedef struct { mDNSu8 c[256]; } domainname;       // Up to 256 bytes of length-prefixed domainlabels
4044b22b933Srs200217 
4054b22b933Srs200217 typedef struct { mDNSu8 c[256]; } UTF8str255;       // Null-terminated C string
4064b22b933Srs200217 
407*5ffb0c9bSToomas Soome // The longest legal textual form of a DNS name is 1009 bytes, including the C-string terminating NULL at the end.
4084b22b933Srs200217 // Explanation:
4094b22b933Srs200217 // When a native domainname object is converted to printable textual form using ConvertDomainNameToCString(),
4104b22b933Srs200217 // non-printing characters are represented in the conventional DNS way, as '\ddd', where ddd is a three-digit decimal number.
411*5ffb0c9bSToomas Soome // The longest legal domain name is 256 bytes, in the form of four labels as shown below:
412*5ffb0c9bSToomas Soome // Length byte, 63 data bytes, length byte, 63 data bytes, length byte, 63 data bytes, length byte, 62 data bytes, zero byte.
4134b22b933Srs200217 // Each label is encoded textually as characters followed by a trailing dot.
4144b22b933Srs200217 // If every character has to be represented as a four-byte escape sequence, then this makes the maximum textual form four labels
4154b22b933Srs200217 // plus the C-string terminating NULL as shown below:
416*5ffb0c9bSToomas Soome // 63*4+1 + 63*4+1 + 63*4+1 + 62*4+1 + 1 = 1009.
4174b22b933Srs200217 // Note that MAX_ESCAPED_DOMAIN_LABEL is not normally used: If you're only decoding a single label, escaping is usually not required.
4184b22b933Srs200217 // It is for domain names, where dots are used as label separators, that proper escaping is vital.
4194b22b933Srs200217 #define MAX_ESCAPED_DOMAIN_LABEL 254
420*5ffb0c9bSToomas Soome #define MAX_ESCAPED_DOMAIN_NAME 1009
421*5ffb0c9bSToomas Soome 
422*5ffb0c9bSToomas Soome // MAX_REVERSE_MAPPING_NAME
423*5ffb0c9bSToomas Soome // For IPv4: "123.123.123.123.in-addr.arpa."  30 bytes including terminating NUL
424*5ffb0c9bSToomas 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
425*5ffb0c9bSToomas Soome 
426*5ffb0c9bSToomas Soome #define MAX_REVERSE_MAPPING_NAME_V4 30
427*5ffb0c9bSToomas Soome #define MAX_REVERSE_MAPPING_NAME_V6 74
428*5ffb0c9bSToomas Soome #define MAX_REVERSE_MAPPING_NAME    74
4294b22b933Srs200217 
4304b22b933Srs200217 // Most records have a TTL of 75 minutes, so that their 80% cache-renewal query occurs once per hour.
4314b22b933Srs200217 // For records containing a hostname (in the name on the left, or in the rdata on the right),
4324b22b933Srs200217 // like A, AAAA, reverse-mapping PTR, and SRV, we use a two-minute TTL by default, because we don't want
4334b22b933Srs200217 // them to hang around for too long in the cache if the host in question crashes or otherwise goes away.
4344b22b933Srs200217 
4354b22b933Srs200217 #define kStandardTTL (3600UL * 100 / 80)
4364b22b933Srs200217 #define kHostNameTTL 120UL
437*5ffb0c9bSToomas Soome 
438*5ffb0c9bSToomas Soome // Some applications want to register their SRV records with a lower ttl so that in case the server
439*5ffb0c9bSToomas Soome // using a dynamic port number restarts, the clients will not have stale information for more than
440*5ffb0c9bSToomas Soome // 10 seconds
441*5ffb0c9bSToomas Soome 
442*5ffb0c9bSToomas Soome #define kHostNameSmallTTL 10UL
443*5ffb0c9bSToomas Soome 
444*5ffb0c9bSToomas Soome 
445*5ffb0c9bSToomas Soome // Multicast DNS uses announcements (gratuitous responses) to update peer caches.
446*5ffb0c9bSToomas Soome // This means it is feasible to use relatively larger TTL values than we might otherwise
447*5ffb0c9bSToomas Soome // use, because we have a cache coherency protocol to keep the peer caches up to date.
448*5ffb0c9bSToomas Soome // With Unicast DNS, once an authoritative server gives a record with a certain TTL value to a client
449*5ffb0c9bSToomas Soome // or caching server, that client or caching server is entitled to hold onto the record until its TTL
450*5ffb0c9bSToomas Soome // expires, and has no obligation to contact the authoritative server again until that time arrives.
451*5ffb0c9bSToomas Soome // This means that whereas Multicast DNS can use announcements to pre-emptively update stale data
452*5ffb0c9bSToomas Soome // before it would otherwise have expired, standard Unicast DNS (not using LLQs) has no equivalent
453*5ffb0c9bSToomas Soome // mechanism, and TTL expiry is the *only* mechanism by which stale data gets deleted. Because of this,
454*5ffb0c9bSToomas Soome // we currently limit the TTL to ten seconds in such cases where no dynamic cache updating is possible.
455*5ffb0c9bSToomas Soome #define kStaticCacheTTL 10
4564b22b933Srs200217 
4574b22b933Srs200217 #define DefaultTTLforRRType(X) (((X) == kDNSType_A || (X) == kDNSType_AAAA || (X) == kDNSType_SRV) ? kHostNameTTL : kStandardTTL)
458*5ffb0c9bSToomas Soome #define mDNS_KeepaliveRecord(rr) ((rr)->rrtype == kDNSType_NULL && SameDomainLabel(SecondLabel((rr)->name)->c, (mDNSu8 *)"\x0A_keepalive"))
459*5ffb0c9bSToomas Soome 
460*5ffb0c9bSToomas Soome // Number of times keepalives are sent if no ACK is received before waking up the system
461*5ffb0c9bSToomas Soome // this is analogous to net.inet.tcp.keepcnt
462*5ffb0c9bSToomas Soome #define kKeepaliveRetryCount    10
463*5ffb0c9bSToomas Soome // The frequency at which keepalives are retried if no ACK is received
464*5ffb0c9bSToomas Soome #define kKeepaliveRetryInterval 30
465*5ffb0c9bSToomas Soome 
466*5ffb0c9bSToomas Soome typedef struct AuthRecord_struct AuthRecord;
467*5ffb0c9bSToomas Soome typedef struct ServiceRecordSet_struct ServiceRecordSet;
468*5ffb0c9bSToomas Soome typedef struct CacheRecord_struct CacheRecord;
469*5ffb0c9bSToomas Soome typedef struct CacheGroup_struct CacheGroup;
470*5ffb0c9bSToomas Soome typedef struct AuthGroup_struct AuthGroup;
471*5ffb0c9bSToomas Soome typedef struct DNSQuestion_struct DNSQuestion;
472*5ffb0c9bSToomas Soome typedef struct ZoneData_struct ZoneData;
473*5ffb0c9bSToomas Soome typedef struct mDNS_struct mDNS;
474*5ffb0c9bSToomas Soome typedef struct mDNS_PlatformSupport_struct mDNS_PlatformSupport;
475*5ffb0c9bSToomas Soome typedef struct NATTraversalInfo_struct NATTraversalInfo;
476*5ffb0c9bSToomas Soome typedef struct ResourceRecord_struct ResourceRecord;
477*5ffb0c9bSToomas Soome 
478*5ffb0c9bSToomas Soome // Structure to abstract away the differences between TCP/SSL sockets, and one for UDP sockets
479*5ffb0c9bSToomas Soome // The actual definition of these structures appear in the appropriate platform support code
480*5ffb0c9bSToomas Soome typedef struct TCPSocket_struct TCPSocket;
481*5ffb0c9bSToomas Soome typedef struct UDPSocket_struct UDPSocket;
4824b22b933Srs200217 
4834b22b933Srs200217 // ***************************************************************************
4844b22b933Srs200217 #if 0
485*5ffb0c9bSToomas Soome #pragma mark -
4864b22b933Srs200217 #pragma mark - DNS Message structures
4874b22b933Srs200217 #endif
4884b22b933Srs200217 
4894b22b933Srs200217 #define mDNS_numZones   numQuestions
4904b22b933Srs200217 #define mDNS_numPrereqs numAnswers
4914b22b933Srs200217 #define mDNS_numUpdates numAuthorities
4924b22b933Srs200217 
4934b22b933Srs200217 typedef packedstruct
4944b22b933Srs200217 {
4954b22b933Srs200217     mDNSOpaque16 id;
4964b22b933Srs200217     mDNSOpaque16 flags;
4974b22b933Srs200217     mDNSu16 numQuestions;
4984b22b933Srs200217     mDNSu16 numAnswers;
4994b22b933Srs200217     mDNSu16 numAuthorities;
5004b22b933Srs200217     mDNSu16 numAdditionals;
5014b22b933Srs200217 } DNSMessageHeader;
5024b22b933Srs200217 
5034b22b933Srs200217 // We can send and receive packets up to 9000 bytes (Ethernet Jumbo Frame size, if that ever becomes widely used)
5044b22b933Srs200217 // However, in the normal case we try to limit packets to 1500 bytes so that we don't get IP fragmentation on standard Ethernet
5054b22b933Srs200217 // 40 (IPv6 header) + 8 (UDP header) + 12 (DNS message header) + 1440 (DNS message body) = 1500 total
506*5ffb0c9bSToomas Soome #ifndef AbsoluteMaxDNSMessageData
5074b22b933Srs200217 #define AbsoluteMaxDNSMessageData 8940
508*5ffb0c9bSToomas Soome #endif
5094b22b933Srs200217 #define NormalMaxDNSMessageData 1440
5104b22b933Srs200217 typedef packedstruct
5114b22b933Srs200217 {
5124b22b933Srs200217     DNSMessageHeader h;                     // Note: Size 12 bytes
5134b22b933Srs200217     mDNSu8 data[AbsoluteMaxDNSMessageData]; // 40 (IPv6) + 8 (UDP) + 12 (DNS header) + 8940 (data) = 9000
5144b22b933Srs200217 } DNSMessage;
5154b22b933Srs200217 
516*5ffb0c9bSToomas Soome typedef struct tcpInfo_t
517*5ffb0c9bSToomas Soome {
518*5ffb0c9bSToomas Soome     mDNS             *m;
519*5ffb0c9bSToomas Soome     TCPSocket        *sock;
520*5ffb0c9bSToomas Soome     DNSMessage request;
521*5ffb0c9bSToomas Soome     int requestLen;
522*5ffb0c9bSToomas Soome     DNSQuestion      *question;   // For queries
523*5ffb0c9bSToomas Soome     AuthRecord       *rr;         // For record updates
524*5ffb0c9bSToomas Soome     mDNSAddr Addr;
525*5ffb0c9bSToomas Soome     mDNSIPPort Port;
526*5ffb0c9bSToomas Soome     mDNSIPPort SrcPort;
527*5ffb0c9bSToomas Soome     DNSMessage       *reply;
528*5ffb0c9bSToomas Soome     mDNSu16 replylen;
529*5ffb0c9bSToomas Soome     unsigned long nread;
530*5ffb0c9bSToomas Soome     int numReplies;
531*5ffb0c9bSToomas Soome } tcpInfo_t;
532*5ffb0c9bSToomas Soome 
5334b22b933Srs200217 // ***************************************************************************
5344b22b933Srs200217 #if 0
535*5ffb0c9bSToomas Soome #pragma mark -
536*5ffb0c9bSToomas Soome #pragma mark - Other Packet Format Structures
537*5ffb0c9bSToomas Soome #endif
538*5ffb0c9bSToomas Soome 
539*5ffb0c9bSToomas Soome typedef packedstruct
540*5ffb0c9bSToomas Soome {
541*5ffb0c9bSToomas Soome     mDNSEthAddr dst;
542*5ffb0c9bSToomas Soome     mDNSEthAddr src;
543*5ffb0c9bSToomas Soome     mDNSOpaque16 ethertype;
544*5ffb0c9bSToomas Soome } EthernetHeader;           // 14 bytes
545*5ffb0c9bSToomas Soome 
546*5ffb0c9bSToomas Soome typedef packedstruct
547*5ffb0c9bSToomas Soome {
548*5ffb0c9bSToomas Soome     mDNSOpaque16 hrd;
549*5ffb0c9bSToomas Soome     mDNSOpaque16 pro;
550*5ffb0c9bSToomas Soome     mDNSu8 hln;
551*5ffb0c9bSToomas Soome     mDNSu8 pln;
552*5ffb0c9bSToomas Soome     mDNSOpaque16 op;
553*5ffb0c9bSToomas Soome     mDNSEthAddr sha;
554*5ffb0c9bSToomas Soome     mDNSv4Addr spa;
555*5ffb0c9bSToomas Soome     mDNSEthAddr tha;
556*5ffb0c9bSToomas Soome     mDNSv4Addr tpa;
557*5ffb0c9bSToomas Soome } ARP_EthIP;                // 28 bytes
558*5ffb0c9bSToomas Soome 
559*5ffb0c9bSToomas Soome typedef packedstruct
560*5ffb0c9bSToomas Soome {
561*5ffb0c9bSToomas Soome     mDNSu8 vlen;
562*5ffb0c9bSToomas Soome     mDNSu8 tos;
563*5ffb0c9bSToomas Soome     mDNSu16 totlen;
564*5ffb0c9bSToomas Soome     mDNSOpaque16 id;
565*5ffb0c9bSToomas Soome     mDNSOpaque16 flagsfrags;
566*5ffb0c9bSToomas Soome     mDNSu8 ttl;
567*5ffb0c9bSToomas Soome     mDNSu8 protocol;        // Payload type: 0x06 = TCP, 0x11 = UDP
568*5ffb0c9bSToomas Soome     mDNSu16 checksum;
569*5ffb0c9bSToomas Soome     mDNSv4Addr src;
570*5ffb0c9bSToomas Soome     mDNSv4Addr dst;
571*5ffb0c9bSToomas Soome } IPv4Header;               // 20 bytes
572*5ffb0c9bSToomas Soome 
573*5ffb0c9bSToomas Soome typedef packedstruct
574*5ffb0c9bSToomas Soome {
575*5ffb0c9bSToomas Soome     mDNSu32 vcf;            // Version, Traffic Class, Flow Label
576*5ffb0c9bSToomas Soome     mDNSu16 len;            // Payload Length
577*5ffb0c9bSToomas Soome     mDNSu8 pro;             // Type of next header: 0x06 = TCP, 0x11 = UDP, 0x3A = ICMPv6
578*5ffb0c9bSToomas Soome     mDNSu8 ttl;             // Hop Limit
579*5ffb0c9bSToomas Soome     mDNSv6Addr src;
580*5ffb0c9bSToomas Soome     mDNSv6Addr dst;
581*5ffb0c9bSToomas Soome } IPv6Header;               // 40 bytes
582*5ffb0c9bSToomas Soome 
583*5ffb0c9bSToomas Soome typedef packedstruct
584*5ffb0c9bSToomas Soome {
585*5ffb0c9bSToomas Soome     mDNSv6Addr src;
586*5ffb0c9bSToomas Soome     mDNSv6Addr dst;
587*5ffb0c9bSToomas Soome     mDNSOpaque32 len;
588*5ffb0c9bSToomas Soome     mDNSOpaque32 pro;
589*5ffb0c9bSToomas Soome } IPv6PseudoHeader;         // 40 bytes
590*5ffb0c9bSToomas Soome 
591*5ffb0c9bSToomas Soome typedef union
592*5ffb0c9bSToomas Soome {
593*5ffb0c9bSToomas Soome     mDNSu8 bytes[20];
594*5ffb0c9bSToomas Soome     ARP_EthIP arp;
595*5ffb0c9bSToomas Soome     IPv4Header v4;
596*5ffb0c9bSToomas Soome     IPv6Header v6;
597*5ffb0c9bSToomas Soome } NetworkLayerPacket;
598*5ffb0c9bSToomas Soome 
599*5ffb0c9bSToomas Soome typedef packedstruct
600*5ffb0c9bSToomas Soome {
601*5ffb0c9bSToomas Soome     mDNSIPPort src;
602*5ffb0c9bSToomas Soome     mDNSIPPort dst;
603*5ffb0c9bSToomas Soome     mDNSu32 seq;
604*5ffb0c9bSToomas Soome     mDNSu32 ack;
605*5ffb0c9bSToomas Soome     mDNSu8 offset;
606*5ffb0c9bSToomas Soome     mDNSu8 flags;
607*5ffb0c9bSToomas Soome     mDNSu16 window;
608*5ffb0c9bSToomas Soome     mDNSu16 checksum;
609*5ffb0c9bSToomas Soome     mDNSu16 urgent;
610*5ffb0c9bSToomas Soome } TCPHeader;                // 20 bytes; IP protocol type 0x06
611*5ffb0c9bSToomas Soome 
612*5ffb0c9bSToomas Soome typedef struct
613*5ffb0c9bSToomas Soome {
614*5ffb0c9bSToomas Soome     mDNSInterfaceID IntfId;
615*5ffb0c9bSToomas Soome     mDNSu32 seq;
616*5ffb0c9bSToomas Soome     mDNSu32 ack;
617*5ffb0c9bSToomas Soome     mDNSu16 window;
618*5ffb0c9bSToomas Soome } mDNSTCPInfo;
619*5ffb0c9bSToomas Soome 
620*5ffb0c9bSToomas Soome typedef packedstruct
621*5ffb0c9bSToomas Soome {
622*5ffb0c9bSToomas Soome     mDNSIPPort src;
623*5ffb0c9bSToomas Soome     mDNSIPPort dst;
624*5ffb0c9bSToomas Soome     mDNSu16 len;            // Length including UDP header (i.e. minimum value is 8 bytes)
625*5ffb0c9bSToomas Soome     mDNSu16 checksum;
626*5ffb0c9bSToomas Soome } UDPHeader;                // 8 bytes; IP protocol type 0x11
627*5ffb0c9bSToomas Soome 
628*5ffb0c9bSToomas Soome typedef packedstruct
629*5ffb0c9bSToomas Soome {
630*5ffb0c9bSToomas Soome     mDNSu8 type;            // 0x87 == Neighbor Solicitation, 0x88 == Neighbor Advertisement
631*5ffb0c9bSToomas Soome     mDNSu8 code;
632*5ffb0c9bSToomas Soome     mDNSu16 checksum;
633*5ffb0c9bSToomas Soome     mDNSu32 flags_res;      // R/S/O flags and reserved bits
634*5ffb0c9bSToomas Soome     mDNSv6Addr target;
635*5ffb0c9bSToomas Soome     // Typically 8 bytes of options are also present
636*5ffb0c9bSToomas Soome } IPv6NDP;                  // 24 bytes or more; IP protocol type 0x3A
637*5ffb0c9bSToomas Soome 
638*5ffb0c9bSToomas Soome typedef struct
639*5ffb0c9bSToomas Soome {
640*5ffb0c9bSToomas Soome     mDNSAddr    ipaddr;
641*5ffb0c9bSToomas Soome     char        ethaddr[18];
642*5ffb0c9bSToomas Soome } IPAddressMACMapping;
643*5ffb0c9bSToomas Soome 
644*5ffb0c9bSToomas Soome #define NDP_Sol 0x87
645*5ffb0c9bSToomas Soome #define NDP_Adv 0x88
646*5ffb0c9bSToomas Soome 
647*5ffb0c9bSToomas Soome #define NDP_Router    0x80
648*5ffb0c9bSToomas Soome #define NDP_Solicited 0x40
649*5ffb0c9bSToomas Soome #define NDP_Override  0x20
650*5ffb0c9bSToomas Soome 
651*5ffb0c9bSToomas Soome #define NDP_SrcLL 1
652*5ffb0c9bSToomas Soome #define NDP_TgtLL 2
653*5ffb0c9bSToomas Soome 
654*5ffb0c9bSToomas Soome typedef union
655*5ffb0c9bSToomas Soome {
656*5ffb0c9bSToomas Soome     mDNSu8 bytes[20];
657*5ffb0c9bSToomas Soome     TCPHeader tcp;
658*5ffb0c9bSToomas Soome     UDPHeader udp;
659*5ffb0c9bSToomas Soome     IPv6NDP ndp;
660*5ffb0c9bSToomas Soome } TransportLayerPacket;
661*5ffb0c9bSToomas Soome 
662*5ffb0c9bSToomas Soome typedef packedstruct
663*5ffb0c9bSToomas Soome {
664*5ffb0c9bSToomas Soome     mDNSOpaque64 InitiatorCookie;
665*5ffb0c9bSToomas Soome     mDNSOpaque64 ResponderCookie;
666*5ffb0c9bSToomas Soome     mDNSu8 NextPayload;
667*5ffb0c9bSToomas Soome     mDNSu8 Version;
668*5ffb0c9bSToomas Soome     mDNSu8 ExchangeType;
669*5ffb0c9bSToomas Soome     mDNSu8 Flags;
670*5ffb0c9bSToomas Soome     mDNSOpaque32 MessageID;
671*5ffb0c9bSToomas Soome     mDNSu32 Length;
672*5ffb0c9bSToomas Soome } IKEHeader;                // 28 bytes
673*5ffb0c9bSToomas Soome 
674*5ffb0c9bSToomas Soome // ***************************************************************************
675*5ffb0c9bSToomas Soome #if 0
676*5ffb0c9bSToomas Soome #pragma mark -
6774b22b933Srs200217 #pragma mark - Resource Record structures
6784b22b933Srs200217 #endif
6794b22b933Srs200217 
6804b22b933Srs200217 // Authoritative Resource Records:
6814b22b933Srs200217 // There are four basic types: Shared, Advisory, Unique, Known Unique
6824b22b933Srs200217 
6834b22b933Srs200217 // * Shared Resource Records do not have to be unique
6844b22b933Srs200217 // -- Shared Resource Records are used for DNS-SD service PTRs
6854b22b933Srs200217 // -- It is okay for several hosts to have RRs with the same name but different RDATA
6864b22b933Srs200217 // -- We use a random delay on responses to reduce collisions when all the hosts respond to the same query
6874b22b933Srs200217 // -- These RRs typically have moderately high TTLs (e.g. one hour)
6884b22b933Srs200217 // -- These records are announced on startup and topology changes for the benefit of passive listeners
6894b22b933Srs200217 // -- These records send a goodbye packet when deregistering
6904b22b933Srs200217 //
6914b22b933Srs200217 // * Advisory Resource Records are like Shared Resource Records, except they don't send a goodbye packet
6924b22b933Srs200217 //
6934b22b933Srs200217 // * Unique Resource Records should be unique among hosts within any given mDNS scope
6944b22b933Srs200217 // -- The majority of Resource Records are of this type
6954b22b933Srs200217 // -- If two entities on the network have RRs with the same name but different RDATA, this is a conflict
6964b22b933Srs200217 // -- Responses may be sent immediately, because only one host should be responding to any particular query
6974b22b933Srs200217 // -- These RRs typically have low TTLs (e.g. a few minutes)
6984b22b933Srs200217 // -- On startup and after topology changes, a host issues queries to verify uniqueness
6994b22b933Srs200217 
7004b22b933Srs200217 // * Known Unique Resource Records are treated like Unique Resource Records, except that mDNS does
7014b22b933Srs200217 // not have to verify their uniqueness because this is already known by other means (e.g. the RR name
7024b22b933Srs200217 // is derived from the host's IP or Ethernet address, which is already known to be a unique identifier).
7034b22b933Srs200217 
7044b22b933Srs200217 // Summary of properties of different record types:
7054b22b933Srs200217 // Probe?    Does this record type send probes before announcing?
7064b22b933Srs200217 // Conflict? Does this record type react if we observe an apparent conflict?
7074b22b933Srs200217 // Goodbye?  Does this record type send a goodbye packet on departure?
7084b22b933Srs200217 //
7094b22b933Srs200217 //               Probe? Conflict? Goodbye? Notes
7104b22b933Srs200217 // Unregistered                            Should not appear in any list (sanity check value)
7114b22b933Srs200217 // Shared         No      No       Yes     e.g. Service PTR record
7124b22b933Srs200217 // Deregistering  No      No       Yes     Shared record about to announce its departure and leave the list
7134b22b933Srs200217 // Advisory       No      No       No
7144b22b933Srs200217 // Unique         Yes     Yes      No      Record intended to be unique -- will probe to verify
7154b22b933Srs200217 // Verified       Yes     Yes      No      Record has completed probing, and is verified unique
7164b22b933Srs200217 // KnownUnique    No      Yes      No      Record is assumed by other means to be unique
7174b22b933Srs200217 
7184b22b933Srs200217 // Valid lifecycle of a record:
7194b22b933Srs200217 // Unregistered ->                   Shared      -> Deregistering -(goodbye)-> Unregistered
7204b22b933Srs200217 // Unregistered ->                   Advisory                               -> Unregistered
7214b22b933Srs200217 // Unregistered -> Unique -(probe)-> Verified                               -> Unregistered
7224b22b933Srs200217 // Unregistered ->                   KnownUnique                            -> Unregistered
7234b22b933Srs200217 
7244b22b933Srs200217 // Each Authoritative kDNSRecordType has only one bit set. This makes it easy to quickly see if a record
7254b22b933Srs200217 // is one of a particular set of types simply by performing the appropriate bitwise masking operation.
7264b22b933Srs200217 
7274b22b933Srs200217 // Cache Resource Records (received from the network):
7284b22b933Srs200217 // There are four basic types: Answer, Unique Answer, Additional, Unique Additional
7294b22b933Srs200217 // Bit 7 (the top bit) of kDNSRecordType is always set for Cache Resource Records; always clear for Authoritative Resource Records
730*5ffb0c9bSToomas Soome // Bit 6 (value 0x40) is set for answer records; clear for authority/additional records
7314b22b933Srs200217 // Bit 5 (value 0x20) is set for records received with the kDNSClass_UniqueRRSet
7324b22b933Srs200217 
7334b22b933Srs200217 enum
7344b22b933Srs200217 {
7354b22b933Srs200217     kDNSRecordTypeUnregistered     = 0x00,  // Not currently in any list
7364b22b933Srs200217     kDNSRecordTypeDeregistering    = 0x01,  // Shared record about to announce its departure and leave the list
7374b22b933Srs200217 
7384b22b933Srs200217     kDNSRecordTypeUnique           = 0x02,  // Will become a kDNSRecordTypeVerified when probing is complete
7394b22b933Srs200217 
7404b22b933Srs200217     kDNSRecordTypeAdvisory         = 0x04,  // Like Shared, but no goodbye packet
7414b22b933Srs200217     kDNSRecordTypeShared           = 0x08,  // Shared means record name does not have to be unique -- use random delay on responses
7424b22b933Srs200217 
7434b22b933Srs200217     kDNSRecordTypeVerified         = 0x10,  // Unique means mDNS should check that name is unique (and then send immediate responses)
7444b22b933Srs200217     kDNSRecordTypeKnownUnique      = 0x20,  // Known Unique means mDNS can assume name is unique without checking
7454b22b933Srs200217                                             // For Dynamic Update records, Known Unique means the record must already exist on the server.
7464b22b933Srs200217     kDNSRecordTypeUniqueMask       = (kDNSRecordTypeUnique | kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique),
747*5ffb0c9bSToomas Soome     kDNSRecordTypeActiveSharedMask = (kDNSRecordTypeAdvisory         | kDNSRecordTypeShared),
748*5ffb0c9bSToomas Soome     kDNSRecordTypeActiveUniqueMask = (kDNSRecordTypeVerified         | kDNSRecordTypeKnownUnique),
749*5ffb0c9bSToomas Soome     kDNSRecordTypeActiveMask       = (kDNSRecordTypeActiveSharedMask | kDNSRecordTypeActiveUniqueMask),
7504b22b933Srs200217 
7514b22b933Srs200217     kDNSRecordTypePacketAdd        = 0x80,  // Received in the Additional  Section of a DNS Response
7524b22b933Srs200217     kDNSRecordTypePacketAddUnique  = 0x90,  // Received in the Additional  Section of a DNS Response with kDNSClass_UniqueRRSet set
7534b22b933Srs200217     kDNSRecordTypePacketAuth       = 0xA0,  // Received in the Authorities Section of a DNS Response
7544b22b933Srs200217     kDNSRecordTypePacketAuthUnique = 0xB0,  // Received in the Authorities Section of a DNS Response with kDNSClass_UniqueRRSet set
7554b22b933Srs200217     kDNSRecordTypePacketAns        = 0xC0,  // Received in the Answer      Section of a DNS Response
7564b22b933Srs200217     kDNSRecordTypePacketAnsUnique  = 0xD0,  // Received in the Answer      Section of a DNS Response with kDNSClass_UniqueRRSet set
7574b22b933Srs200217 
758*5ffb0c9bSToomas Soome     kDNSRecordTypePacketNegative   = 0xF0,  // Pseudo-RR generated to cache non-existence results like NXDomain
759*5ffb0c9bSToomas Soome 
760*5ffb0c9bSToomas Soome     kDNSRecordTypePacketUniqueMask = 0x10   // True for PacketAddUnique, PacketAnsUnique, PacketAuthUnique, kDNSRecordTypePacketNegative
7614b22b933Srs200217 };
7624b22b933Srs200217 
7634b22b933Srs200217 typedef packedstruct { mDNSu16 priority; mDNSu16 weight; mDNSIPPort port; domainname target;   } rdataSRV;
7644b22b933Srs200217 typedef packedstruct { mDNSu16 preference;                                domainname exchange; } rdataMX;
765*5ffb0c9bSToomas Soome typedef packedstruct { domainname mbox; domainname txt;                                        } rdataRP;
766*5ffb0c9bSToomas Soome typedef packedstruct { mDNSu16 preference; domainname map822; domainname mapx400;              } rdataPX;
767*5ffb0c9bSToomas Soome 
7684b22b933Srs200217 typedef packedstruct
7694b22b933Srs200217 {
7704b22b933Srs200217     domainname mname;
7714b22b933Srs200217     domainname rname;
7724b22b933Srs200217     mDNSs32 serial;     // Modular counter; increases when zone changes
7734b22b933Srs200217     mDNSu32 refresh;    // Time in seconds that a slave waits after successful replication of the database before it attempts replication again
7744b22b933Srs200217     mDNSu32 retry;      // Time in seconds that a slave waits after an unsuccessful replication attempt before it attempts replication again
7754b22b933Srs200217     mDNSu32 expire;     // Time in seconds that a slave holds on to old data while replication attempts remain unsuccessful
7764b22b933Srs200217     mDNSu32 min;        // Nominally the minimum record TTL for this zone, in seconds; also used for negative caching.
7774b22b933Srs200217 } rdataSOA;
7784b22b933Srs200217 
779*5ffb0c9bSToomas Soome // http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
780*5ffb0c9bSToomas Soome // Algorithm used for RRSIG, DS and DNS KEY
781*5ffb0c9bSToomas Soome #define CRYPTO_RSA_SHA1             0x05
782*5ffb0c9bSToomas Soome #define CRYPTO_DSA_NSEC3_SHA1       0x06
783*5ffb0c9bSToomas Soome #define CRYPTO_RSA_NSEC3_SHA1       0x07
784*5ffb0c9bSToomas Soome #define CRYPTO_RSA_SHA256           0x08
785*5ffb0c9bSToomas Soome #define CRYPTO_RSA_SHA512           0x0A
786*5ffb0c9bSToomas Soome 
787*5ffb0c9bSToomas Soome #define CRYPTO_ALG_MAX              0x0B
788*5ffb0c9bSToomas Soome 
789*5ffb0c9bSToomas Soome // alg - same as in RRSIG, DNS KEY or DS.
790*5ffb0c9bSToomas Soome // RFC 4034 defines SHA1
791*5ffb0c9bSToomas Soome // RFC 4509 defines SHA256
792*5ffb0c9bSToomas Soome // Note: NSEC3 also uses 1 for SHA1 and hence we will reuse for now till a new
793*5ffb0c9bSToomas Soome // value is assigned.
794*5ffb0c9bSToomas Soome //
795*5ffb0c9bSToomas Soome #define SHA1_DIGEST_TYPE        1
796*5ffb0c9bSToomas Soome #define SHA256_DIGEST_TYPE      2
797*5ffb0c9bSToomas Soome #define DIGEST_TYPE_MAX         3
798*5ffb0c9bSToomas Soome 
799*5ffb0c9bSToomas Soome // We need support for base64 and base32 encoding for displaying KEY, NSEC3
800*5ffb0c9bSToomas Soome // To make this platform agnostic, we define two types which the platform
801*5ffb0c9bSToomas Soome // needs to support
802*5ffb0c9bSToomas Soome #define ENC_BASE32              1
803*5ffb0c9bSToomas Soome #define ENC_BASE64              2
804*5ffb0c9bSToomas Soome #define ENC_ALG_MAX             3
805*5ffb0c9bSToomas Soome 
806*5ffb0c9bSToomas Soome #define DS_FIXED_SIZE           4
8074b22b933Srs200217 typedef packedstruct
8084b22b933Srs200217 {
809*5ffb0c9bSToomas Soome     mDNSu16 keyTag;
810*5ffb0c9bSToomas Soome     mDNSu8 alg;
811*5ffb0c9bSToomas Soome     mDNSu8 digestType;
812*5ffb0c9bSToomas Soome     mDNSu8  *digest;
813*5ffb0c9bSToomas Soome } rdataDS;
814*5ffb0c9bSToomas Soome 
815*5ffb0c9bSToomas Soome typedef struct TrustAnchor
816*5ffb0c9bSToomas Soome {
817*5ffb0c9bSToomas Soome     struct TrustAnchor *next;
818*5ffb0c9bSToomas Soome     int digestLen;
819*5ffb0c9bSToomas Soome     mDNSu32 validFrom;
820*5ffb0c9bSToomas Soome     mDNSu32 validUntil;
821*5ffb0c9bSToomas Soome     domainname zone;
822*5ffb0c9bSToomas Soome     rdataDS rds;
823*5ffb0c9bSToomas Soome } TrustAnchor;
824*5ffb0c9bSToomas Soome 
825*5ffb0c9bSToomas Soome //size of rdataRRSIG excluding signerName and signature (which are variable fields)
826*5ffb0c9bSToomas Soome #define RRSIG_FIXED_SIZE      18
827*5ffb0c9bSToomas Soome typedef packedstruct
828*5ffb0c9bSToomas Soome {
829*5ffb0c9bSToomas Soome     mDNSu16 typeCovered;
830*5ffb0c9bSToomas Soome     mDNSu8 alg;
831*5ffb0c9bSToomas Soome     mDNSu8 labels;
832*5ffb0c9bSToomas Soome     mDNSu32 origTTL;
833*5ffb0c9bSToomas Soome     mDNSu32 sigExpireTime;
834*5ffb0c9bSToomas Soome     mDNSu32 sigInceptTime;
835*5ffb0c9bSToomas Soome     mDNSu16 keyTag;
836*5ffb0c9bSToomas Soome     mDNSu8 *signerName;
837*5ffb0c9bSToomas Soome     // mDNSu8 *signature
838*5ffb0c9bSToomas Soome } rdataRRSig;
839*5ffb0c9bSToomas Soome 
840*5ffb0c9bSToomas Soome // RFC 4034: For DNS Key RR
841*5ffb0c9bSToomas Soome // flags - the valid value for DNSSEC is 256 (Zone signing key - ZSK) and 257 (Secure Entry Point) which also
842*5ffb0c9bSToomas Soome // includes the ZSK bit
843*5ffb0c9bSToomas Soome //
844*5ffb0c9bSToomas Soome #define DNSKEY_ZONE_SIGN_KEY        0x100
845*5ffb0c9bSToomas Soome #define DNSKEY_SECURE_ENTRY_POINT   0x101
846*5ffb0c9bSToomas Soome 
847*5ffb0c9bSToomas Soome // proto - the only valid value for protocol is 3 (See RFC 4034)
848*5ffb0c9bSToomas Soome #define DNSKEY_VALID_PROTO_VALUE    0x003
849*5ffb0c9bSToomas Soome 
850*5ffb0c9bSToomas Soome // alg - The only mandatory algorithm that we support is RSA/SHA-1
851*5ffb0c9bSToomas Soome // DNSSEC_RSA_SHA1_ALG
852*5ffb0c9bSToomas Soome 
853*5ffb0c9bSToomas Soome #define DNSKEY_FIXED_SIZE          4
854*5ffb0c9bSToomas Soome typedef packedstruct
855*5ffb0c9bSToomas Soome {
856*5ffb0c9bSToomas Soome     mDNSu16 flags;
857*5ffb0c9bSToomas Soome     mDNSu8 proto;
858*5ffb0c9bSToomas Soome     mDNSu8 alg;
859*5ffb0c9bSToomas Soome     mDNSu8  *data;
860*5ffb0c9bSToomas Soome } rdataDNSKey;
861*5ffb0c9bSToomas Soome 
862*5ffb0c9bSToomas Soome #define NSEC3_FIXED_SIZE          5
863*5ffb0c9bSToomas Soome #define NSEC3_FLAGS_OPTOUT        1
864*5ffb0c9bSToomas Soome #define NSEC3_MAX_ITERATIONS      2500
865*5ffb0c9bSToomas Soome typedef packedstruct
866*5ffb0c9bSToomas Soome {
867*5ffb0c9bSToomas Soome     mDNSu8 alg;
868*5ffb0c9bSToomas Soome     mDNSu8 flags;
869*5ffb0c9bSToomas Soome     mDNSu16 iterations;
870*5ffb0c9bSToomas Soome     mDNSu8 saltLength;
871*5ffb0c9bSToomas Soome     mDNSu8 *salt;
872*5ffb0c9bSToomas Soome     // hashLength, nxt, bitmap
873*5ffb0c9bSToomas Soome } rdataNSEC3;
874*5ffb0c9bSToomas Soome 
875*5ffb0c9bSToomas Soome // In the multicast usage of NSEC3, we know the actual size of RData
876*5ffb0c9bSToomas Soome // 4 bytes : HashAlg, Flags,Iterations
877*5ffb0c9bSToomas Soome // 5 bytes : Salt Length 1 byte, Salt 4 bytes
878*5ffb0c9bSToomas Soome // 21 bytes : HashLength 1 byte, Hash 20 bytes
879*5ffb0c9bSToomas Soome // 34 bytes : Window number, Bitmap length, Type bit map to include the first 256 types
880*5ffb0c9bSToomas Soome #define MCAST_NSEC3_RDLENGTH (4 + 5 + 21 + 34)
881*5ffb0c9bSToomas Soome #define SHA1_HASH_LENGTH 20
882*5ffb0c9bSToomas Soome 
883*5ffb0c9bSToomas Soome // Base32 encoding takes 5 bytes of the input and encodes as 8 bytes of output.
884*5ffb0c9bSToomas Soome // For example, SHA-1 hash of 20 bytes will be encoded as 20/5 * 8 = 32 base32
885*5ffb0c9bSToomas Soome // bytes. For a max domain name size of 255 bytes of base32 encoding : (255/8)*5
886*5ffb0c9bSToomas Soome // is the max hash length possible.
887*5ffb0c9bSToomas Soome #define NSEC3_MAX_HASH_LEN	155
888*5ffb0c9bSToomas Soome // In NSEC3, the names are hashed and stored in the first label and hence cannot exceed label
889*5ffb0c9bSToomas Soome // size.
890*5ffb0c9bSToomas Soome #define NSEC3_MAX_B32_LEN	MAX_DOMAIN_LABEL
891*5ffb0c9bSToomas Soome 
892*5ffb0c9bSToomas Soome // We define it here instead of dnssec.h so that these values can be used
893*5ffb0c9bSToomas Soome // in files without bringing in all of dnssec.h unnecessarily.
894*5ffb0c9bSToomas Soome typedef enum
895*5ffb0c9bSToomas Soome {
896*5ffb0c9bSToomas Soome     DNSSEC_Secure = 1,      // Securely validated and has a chain up to the trust anchor
897*5ffb0c9bSToomas Soome     DNSSEC_Insecure,        // Cannot build a chain up to the trust anchor
898*5ffb0c9bSToomas Soome     DNSSEC_Indeterminate,   // Not used currently
899*5ffb0c9bSToomas Soome     DNSSEC_Bogus,           // failed to validate signatures
900*5ffb0c9bSToomas Soome     DNSSEC_NoResponse       // No DNSSEC records to start with
901*5ffb0c9bSToomas Soome } DNSSECStatus;
902*5ffb0c9bSToomas Soome 
903*5ffb0c9bSToomas Soome #define DNSSECRecordType(rrtype) (((rrtype) == kDNSType_RRSIG) || ((rrtype) == kDNSType_NSEC) || ((rrtype) == kDNSType_DNSKEY) || ((rrtype) == kDNSType_DS) || \
904*5ffb0c9bSToomas Soome                                   ((rrtype) == kDNSType_NSEC3))
905*5ffb0c9bSToomas Soome 
906*5ffb0c9bSToomas Soome typedef enum
907*5ffb0c9bSToomas Soome {
908*5ffb0c9bSToomas Soome     platform_OSX = 1,   // OSX Platform
909*5ffb0c9bSToomas Soome     platform_iOS,       // iOS Platform
910*5ffb0c9bSToomas Soome     platform_Atv,       // Atv Platform
911*5ffb0c9bSToomas Soome     platform_NonApple   // Non-Apple (Windows, POSIX) Platform
912*5ffb0c9bSToomas Soome } Platform_t;
913*5ffb0c9bSToomas Soome 
914*5ffb0c9bSToomas Soome // EDNS Option Code registrations are recorded in the "DNS EDNS0 Options" section of
915*5ffb0c9bSToomas Soome // <http://www.iana.org/assignments/dns-parameters>
916*5ffb0c9bSToomas Soome 
917*5ffb0c9bSToomas Soome #define kDNSOpt_LLQ   1
918*5ffb0c9bSToomas Soome #define kDNSOpt_Lease 2
919*5ffb0c9bSToomas Soome #define kDNSOpt_NSID  3
920*5ffb0c9bSToomas Soome #define kDNSOpt_Owner 4
921*5ffb0c9bSToomas Soome #define kDNSOpt_Trace 65001  // 65001-65534 Reserved for Local/Experimental Use
922*5ffb0c9bSToomas Soome 
923*5ffb0c9bSToomas Soome typedef struct
924*5ffb0c9bSToomas Soome {
9254b22b933Srs200217     mDNSu16 vers;
9264b22b933Srs200217     mDNSu16 llqOp;
927*5ffb0c9bSToomas Soome     mDNSu16 err;        // Or UDP reply port, in setup request
928*5ffb0c9bSToomas 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
929*5ffb0c9bSToomas Soome     mDNSOpaque64 id;
930*5ffb0c9bSToomas Soome     mDNSu32 llqlease;
9314b22b933Srs200217 } LLQOptData;
9324b22b933Srs200217 
933*5ffb0c9bSToomas Soome typedef struct
934*5ffb0c9bSToomas Soome {
935*5ffb0c9bSToomas Soome     mDNSu8 vers;            // Version number of this Owner OPT record
936*5ffb0c9bSToomas Soome     mDNSs8 seq;             // Sleep/wake epoch
937*5ffb0c9bSToomas Soome     mDNSEthAddr HMAC;       // Host's primary identifier (e.g. MAC of on-board Ethernet)
938*5ffb0c9bSToomas Soome     mDNSEthAddr IMAC;       // Interface's MAC address (if different to primary MAC)
939*5ffb0c9bSToomas Soome     mDNSOpaque48 password;  // Optional password
940*5ffb0c9bSToomas Soome } OwnerOptData;
9414b22b933Srs200217 
942*5ffb0c9bSToomas Soome typedef struct
943*5ffb0c9bSToomas Soome {
944*5ffb0c9bSToomas Soome     mDNSu8    platf;      // Running platform (see enum Platform_t)
945*5ffb0c9bSToomas Soome     mDNSu32   mDNSv;      // mDNSResponder Version (DNS_SD_H defined in dns_sd.h)
946*5ffb0c9bSToomas Soome } TracerOptData;
947*5ffb0c9bSToomas Soome 
948*5ffb0c9bSToomas Soome // Note: rdataOPT format may be repeated an arbitrary number of times in a single resource record
9494b22b933Srs200217 typedef packedstruct
9504b22b933Srs200217 {
9514b22b933Srs200217     mDNSu16 opt;
9524b22b933Srs200217     mDNSu16 optlen;
953*5ffb0c9bSToomas Soome     union { LLQOptData llq; mDNSu32 updatelease; OwnerOptData owner; TracerOptData tracer; } u;
954*5ffb0c9bSToomas Soome } rdataOPT;
9554b22b933Srs200217 
956*5ffb0c9bSToomas Soome // Space needed to put OPT records into a packet:
957*5ffb0c9bSToomas Soome // Header         11  bytes (name 1, type 2, class 2, TTL 4, length 2)
958*5ffb0c9bSToomas Soome // LLQ   rdata    18  bytes (opt 2, len 2, vers 2, op 2, err 2, id 8, lease 4)
959*5ffb0c9bSToomas Soome // Lease rdata     8  bytes (opt 2, len 2, lease 4)
960*5ffb0c9bSToomas Soome // Owner rdata 12-24  bytes (opt 2, len 2, owner 8-20)
961*5ffb0c9bSToomas Soome // Trace rdata     9  bytes (opt 2, len 2, platf 1, mDNSv 4)
962*5ffb0c9bSToomas Soome 
963*5ffb0c9bSToomas Soome 
964*5ffb0c9bSToomas Soome #define DNSOpt_Header_Space                 11
965*5ffb0c9bSToomas Soome #define DNSOpt_LLQData_Space               (4 + 2 + 2 + 2 + 8 + 4)
966*5ffb0c9bSToomas Soome #define DNSOpt_LeaseData_Space             (4 + 4)
967*5ffb0c9bSToomas Soome #define DNSOpt_OwnerData_ID_Space          (4 + 2 + 6)
968*5ffb0c9bSToomas Soome #define DNSOpt_OwnerData_ID_Wake_Space     (4 + 2 + 6 + 6)
969*5ffb0c9bSToomas Soome #define DNSOpt_OwnerData_ID_Wake_PW4_Space (4 + 2 + 6 + 6 + 4)
970*5ffb0c9bSToomas Soome #define DNSOpt_OwnerData_ID_Wake_PW6_Space (4 + 2 + 6 + 6 + 6)
971*5ffb0c9bSToomas Soome #define DNSOpt_TraceData_Space             (4 + 1 + 4)
972*5ffb0c9bSToomas Soome 
973*5ffb0c9bSToomas Soome #define ValidOwnerLength(X) (   (X) == DNSOpt_OwnerData_ID_Space          - 4 || \
974*5ffb0c9bSToomas Soome                                 (X) == DNSOpt_OwnerData_ID_Wake_Space     - 4 || \
975*5ffb0c9bSToomas Soome                                 (X) == DNSOpt_OwnerData_ID_Wake_PW4_Space - 4 || \
976*5ffb0c9bSToomas Soome                                 (X) == DNSOpt_OwnerData_ID_Wake_PW6_Space - 4    )
977*5ffb0c9bSToomas Soome 
978*5ffb0c9bSToomas Soome #define DNSOpt_Owner_Space(A,B) (mDNSSameEthAddress((A),(B)) ? DNSOpt_OwnerData_ID_Space : DNSOpt_OwnerData_ID_Wake_Space)
979*5ffb0c9bSToomas Soome 
980*5ffb0c9bSToomas Soome #define DNSOpt_Data_Space(O) (                                  \
981*5ffb0c9bSToomas Soome         (O)->opt == kDNSOpt_LLQ   ? DNSOpt_LLQData_Space   :        \
982*5ffb0c9bSToomas Soome         (O)->opt == kDNSOpt_Lease ? DNSOpt_LeaseData_Space :        \
983*5ffb0c9bSToomas Soome         (O)->opt == kDNSOpt_Trace ? DNSOpt_TraceData_Space :        \
984*5ffb0c9bSToomas Soome         (O)->opt == kDNSOpt_Owner ? DNSOpt_Owner_Space(&(O)->u.owner.HMAC, &(O)->u.owner.IMAC) : 0x10000)
985*5ffb0c9bSToomas Soome 
986*5ffb0c9bSToomas Soome // NSEC record is defined in RFC 4034.
987*5ffb0c9bSToomas Soome // 16 bit RRTYPE space is split into 256 windows and each window has 256 bits (32 bytes).
988*5ffb0c9bSToomas Soome // If we create a structure for NSEC, it's size would be:
989*5ffb0c9bSToomas Soome //
990*5ffb0c9bSToomas Soome //   256 bytes domainname 'nextname'
991*5ffb0c9bSToomas Soome // + 256 * 34 = 8704 bytes of bitmap data
992*5ffb0c9bSToomas Soome // = 8960 bytes total
993*5ffb0c9bSToomas Soome //
994*5ffb0c9bSToomas Soome // This would be a waste, as types about 256 are not very common. But it would be odd, if we receive
995*5ffb0c9bSToomas Soome // a type above 256 (.US zone had TYPE65534 when this code was written) and not able to handle it.
996*5ffb0c9bSToomas Soome // Hence, we handle any size by not fixing a strucure in place. The following is just a placeholder
997*5ffb0c9bSToomas Soome // and never used anywhere.
998*5ffb0c9bSToomas Soome //
999*5ffb0c9bSToomas Soome #define NSEC_MCAST_WINDOW_SIZE 32
1000*5ffb0c9bSToomas Soome typedef struct
1001*5ffb0c9bSToomas Soome {
1002*5ffb0c9bSToomas Soome     domainname *next; //placeholders are uncommented because C89 in Windows requires that a struct has at least a member.
1003*5ffb0c9bSToomas Soome     char bitmap[32];
1004*5ffb0c9bSToomas Soome } rdataNSEC;
1005*5ffb0c9bSToomas Soome 
1006*5ffb0c9bSToomas Soome // StandardAuthRDSize is 264 (256+8), which is large enough to hold a maximum-sized SRV record (6 + 256 bytes)
10074b22b933Srs200217 // MaximumRDSize is 8K the absolute maximum we support (at least for now)
10084b22b933Srs200217 #define StandardAuthRDSize 264
1009*5ffb0c9bSToomas Soome #ifndef MaximumRDSize
10104b22b933Srs200217 #define MaximumRDSize 8192
1011*5ffb0c9bSToomas Soome #endif
10124b22b933Srs200217 
10134b22b933Srs200217 // InlineCacheRDSize is 68
10144b22b933Srs200217 // Records received from the network with rdata this size or less have their rdata stored right in the CacheRecord object
10154b22b933Srs200217 // Records received from the network with rdata larger than this have additional storage allocated for the rdata
10164b22b933Srs200217 // A quick unscientific sample from a busy network at Apple with lots of machines revealed this:
10174b22b933Srs200217 // 1461 records in cache
10184b22b933Srs200217 // 292 were one-byte TXT records
10194b22b933Srs200217 // 136 were four-byte A records
10204b22b933Srs200217 // 184 were sixteen-byte AAAA records
10214b22b933Srs200217 // 780 were various PTR, TXT and SRV records from 12-64 bytes
10224b22b933Srs200217 // Only 69 records had rdata bigger than 64 bytes
10234b22b933Srs200217 // Note that since CacheRecord object and a CacheGroup object are allocated out of the same pool, it's sensible to
10244b22b933Srs200217 // have them both be the same size. Making one smaller without making the other smaller won't actually save any memory.
10254b22b933Srs200217 #define InlineCacheRDSize 68
10264b22b933Srs200217 
1027*5ffb0c9bSToomas Soome // The RDataBody union defines the common rdata types that fit into our 264-byte limit
10284b22b933Srs200217 typedef union
10294b22b933Srs200217 {
10304b22b933Srs200217     mDNSu8 data[StandardAuthRDSize];
10314b22b933Srs200217     mDNSv4Addr ipv4;        // For 'A' record
1032*5ffb0c9bSToomas Soome     domainname name;        // For PTR, NS, CNAME, DNAME
1033*5ffb0c9bSToomas Soome     UTF8str255 txt;
1034*5ffb0c9bSToomas Soome     rdataMX mx;
10354b22b933Srs200217     mDNSv6Addr ipv6;        // For 'AAAA' record
1036*5ffb0c9bSToomas Soome     rdataSRV srv;
1037*5ffb0c9bSToomas Soome     rdataOPT opt[2];        // For EDNS0 OPT record; RDataBody may contain multiple variable-length rdataOPT objects packed together
10384b22b933Srs200217 } RDataBody;
10394b22b933Srs200217 
1040*5ffb0c9bSToomas Soome // The RDataBody2 union is the same as above, except it includes fields for the larger types like soa, rp, px
1041*5ffb0c9bSToomas Soome typedef union
1042*5ffb0c9bSToomas Soome {
1043*5ffb0c9bSToomas Soome     mDNSu8 data[StandardAuthRDSize];
1044*5ffb0c9bSToomas Soome     mDNSv4Addr ipv4;        // For 'A' record
1045*5ffb0c9bSToomas Soome     domainname name;        // For PTR, NS, CNAME, DNAME
1046*5ffb0c9bSToomas Soome     rdataSOA soa;           // This is large; not included in the normal RDataBody definition
1047*5ffb0c9bSToomas Soome     UTF8str255 txt;
1048*5ffb0c9bSToomas Soome     rdataMX mx;
1049*5ffb0c9bSToomas Soome     rdataRP rp;             // This is large; not included in the normal RDataBody definition
1050*5ffb0c9bSToomas Soome     rdataPX px;             // This is large; not included in the normal RDataBody definition
1051*5ffb0c9bSToomas Soome     mDNSv6Addr ipv6;        // For 'AAAA' record
1052*5ffb0c9bSToomas Soome     rdataSRV srv;
1053*5ffb0c9bSToomas Soome     rdataOPT opt[2];        // For EDNS0 OPT record; RDataBody may contain multiple variable-length rdataOPT objects packed together
1054*5ffb0c9bSToomas Soome     rdataDS ds;
1055*5ffb0c9bSToomas Soome     rdataDNSKey key;
1056*5ffb0c9bSToomas Soome     rdataRRSig rrsig;
1057*5ffb0c9bSToomas Soome } RDataBody2;
1058*5ffb0c9bSToomas Soome 
10594b22b933Srs200217 typedef struct
10604b22b933Srs200217 {
10614b22b933Srs200217     mDNSu16 MaxRDLength;    // Amount of storage allocated for rdata (usually sizeof(RDataBody))
1062*5ffb0c9bSToomas Soome     mDNSu16 padding;        // So that RDataBody is aligned on 32-bit boundary
10634b22b933Srs200217     RDataBody u;
10644b22b933Srs200217 } RData;
1065*5ffb0c9bSToomas Soome 
1066*5ffb0c9bSToomas Soome // sizeofRDataHeader should be 4 bytes
10674b22b933Srs200217 #define sizeofRDataHeader (sizeof(RData) - sizeof(RDataBody))
10684b22b933Srs200217 
1069*5ffb0c9bSToomas Soome // RData_small is a smaller version of the RData object, used for inline data storage embedded in a CacheRecord_struct
1070*5ffb0c9bSToomas Soome typedef struct
1071*5ffb0c9bSToomas Soome {
1072*5ffb0c9bSToomas Soome     mDNSu16 MaxRDLength;    // Storage allocated for data (may be greater than InlineCacheRDSize if additional storage follows this object)
1073*5ffb0c9bSToomas Soome     mDNSu16 padding;        // So that data is aligned on 32-bit boundary
1074*5ffb0c9bSToomas Soome     mDNSu8 data[InlineCacheRDSize];
1075*5ffb0c9bSToomas Soome } RData_small;
10764b22b933Srs200217 
1077*5ffb0c9bSToomas Soome // Note: Within an mDNSRecordCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
10784b22b933Srs200217 typedef void mDNSRecordCallback (mDNS *const m, AuthRecord *const rr, mStatus result);
10794b22b933Srs200217 
10804b22b933Srs200217 // Note:
10814b22b933Srs200217 // Restrictions: An mDNSRecordUpdateCallback may not make any mDNS API calls.
10824b22b933Srs200217 // The intent of this callback is to allow the client to free memory, if necessary.
10834b22b933Srs200217 // The internal data structures of the mDNS code may not be in a state where mDNS API calls may be made safely.
1084*5ffb0c9bSToomas Soome typedef void mDNSRecordUpdateCallback (mDNS *const m, AuthRecord *const rr, RData *OldRData, mDNSu16 OldRDLen);
1085*5ffb0c9bSToomas Soome 
1086*5ffb0c9bSToomas Soome // ***************************************************************************
1087*5ffb0c9bSToomas Soome #if 0
1088*5ffb0c9bSToomas Soome #pragma mark -
1089*5ffb0c9bSToomas Soome #pragma mark - NAT Traversal structures and constants
1090*5ffb0c9bSToomas Soome #endif
1091*5ffb0c9bSToomas Soome 
1092*5ffb0c9bSToomas Soome #define NATMAP_MAX_RETRY_INTERVAL    ((mDNSPlatformOneSecond * 60) * 15)    // Max retry interval is 15 minutes
1093*5ffb0c9bSToomas Soome #define NATMAP_MIN_RETRY_INTERVAL     (mDNSPlatformOneSecond * 2)           // Min retry interval is 2 seconds
1094*5ffb0c9bSToomas Soome #define NATMAP_INIT_RETRY             (mDNSPlatformOneSecond / 4)           // start at 250ms w/ exponential decay
1095*5ffb0c9bSToomas Soome #define NATMAP_DEFAULT_LEASE          (60 * 60 * 2)                         // 2 hour lease life in seconds
1096*5ffb0c9bSToomas Soome #define NATMAP_VERS 0
1097*5ffb0c9bSToomas Soome 
1098*5ffb0c9bSToomas Soome typedef enum
1099*5ffb0c9bSToomas Soome {
1100*5ffb0c9bSToomas Soome     NATOp_AddrRequest    = 0,
1101*5ffb0c9bSToomas Soome     NATOp_MapUDP         = 1,
1102*5ffb0c9bSToomas Soome     NATOp_MapTCP         = 2,
1103*5ffb0c9bSToomas Soome 
1104*5ffb0c9bSToomas Soome     NATOp_AddrResponse   = 0x80 | 0,
1105*5ffb0c9bSToomas Soome     NATOp_MapUDPResponse = 0x80 | 1,
1106*5ffb0c9bSToomas Soome     NATOp_MapTCPResponse = 0x80 | 2,
1107*5ffb0c9bSToomas Soome } NATOp_t;
1108*5ffb0c9bSToomas Soome 
1109*5ffb0c9bSToomas Soome enum
1110*5ffb0c9bSToomas Soome {
1111*5ffb0c9bSToomas Soome     NATErr_None    = 0,
1112*5ffb0c9bSToomas Soome     NATErr_Vers    = 1,
1113*5ffb0c9bSToomas Soome     NATErr_Refused = 2,
1114*5ffb0c9bSToomas Soome     NATErr_NetFail = 3,
1115*5ffb0c9bSToomas Soome     NATErr_Res     = 4,
1116*5ffb0c9bSToomas Soome     NATErr_Opcode  = 5
1117*5ffb0c9bSToomas Soome };
1118*5ffb0c9bSToomas Soome 
1119*5ffb0c9bSToomas Soome typedef mDNSu16 NATErr_t;
1120*5ffb0c9bSToomas Soome 
1121*5ffb0c9bSToomas Soome typedef packedstruct
1122*5ffb0c9bSToomas Soome {
1123*5ffb0c9bSToomas Soome     mDNSu8 vers;
1124*5ffb0c9bSToomas Soome     mDNSu8 opcode;
1125*5ffb0c9bSToomas Soome } NATAddrRequest;
1126*5ffb0c9bSToomas Soome 
1127*5ffb0c9bSToomas Soome typedef packedstruct
1128*5ffb0c9bSToomas Soome {
1129*5ffb0c9bSToomas Soome     mDNSu8 vers;
1130*5ffb0c9bSToomas Soome     mDNSu8 opcode;
1131*5ffb0c9bSToomas Soome     mDNSu16 err;
1132*5ffb0c9bSToomas Soome     mDNSu32 upseconds;          // Time since last NAT engine reboot, in seconds
1133*5ffb0c9bSToomas Soome     mDNSv4Addr ExtAddr;
1134*5ffb0c9bSToomas Soome } NATAddrReply;
1135*5ffb0c9bSToomas Soome 
1136*5ffb0c9bSToomas Soome typedef packedstruct
1137*5ffb0c9bSToomas Soome {
1138*5ffb0c9bSToomas Soome     mDNSu8 vers;
1139*5ffb0c9bSToomas Soome     mDNSu8 opcode;
1140*5ffb0c9bSToomas Soome     mDNSOpaque16 unused;
1141*5ffb0c9bSToomas Soome     mDNSIPPort intport;
1142*5ffb0c9bSToomas Soome     mDNSIPPort extport;
1143*5ffb0c9bSToomas Soome     mDNSu32 NATReq_lease;
1144*5ffb0c9bSToomas Soome } NATPortMapRequest;
1145*5ffb0c9bSToomas Soome 
1146*5ffb0c9bSToomas Soome typedef packedstruct
1147*5ffb0c9bSToomas Soome {
1148*5ffb0c9bSToomas Soome     mDNSu8 vers;
1149*5ffb0c9bSToomas Soome     mDNSu8 opcode;
1150*5ffb0c9bSToomas Soome     mDNSu16 err;
1151*5ffb0c9bSToomas Soome     mDNSu32 upseconds;          // Time since last NAT engine reboot, in seconds
1152*5ffb0c9bSToomas Soome     mDNSIPPort intport;
1153*5ffb0c9bSToomas Soome     mDNSIPPort extport;
1154*5ffb0c9bSToomas Soome     mDNSu32 NATRep_lease;
1155*5ffb0c9bSToomas Soome } NATPortMapReply;
1156*5ffb0c9bSToomas Soome 
1157*5ffb0c9bSToomas Soome // PCP Support for IPv4 mappings
1158*5ffb0c9bSToomas Soome 
1159*5ffb0c9bSToomas Soome #define PCP_VERS 0x02
1160*5ffb0c9bSToomas Soome #define PCP_WAITSECS_AFTER_EPOCH_INVALID 5
1161*5ffb0c9bSToomas Soome 
1162*5ffb0c9bSToomas Soome typedef enum
1163*5ffb0c9bSToomas Soome {
1164*5ffb0c9bSToomas Soome     PCPOp_Announce = 0,
1165*5ffb0c9bSToomas Soome     PCPOp_Map      = 1
1166*5ffb0c9bSToomas Soome } PCPOp_t;
1167*5ffb0c9bSToomas Soome 
1168*5ffb0c9bSToomas Soome typedef enum
1169*5ffb0c9bSToomas Soome {
1170*5ffb0c9bSToomas Soome     PCPProto_All = 0,
1171*5ffb0c9bSToomas Soome     PCPProto_TCP = 6,
1172*5ffb0c9bSToomas Soome     PCPProto_UDP = 17
1173*5ffb0c9bSToomas Soome } PCPProto_t;
1174*5ffb0c9bSToomas Soome 
1175*5ffb0c9bSToomas Soome typedef enum
1176*5ffb0c9bSToomas Soome {
1177*5ffb0c9bSToomas Soome     PCPResult_Success         = 0,
1178*5ffb0c9bSToomas Soome     PCPResult_UnsuppVersion   = 1,
1179*5ffb0c9bSToomas Soome     PCPResult_NotAuthorized   = 2,
1180*5ffb0c9bSToomas Soome     PCPResult_MalformedReq    = 3,
1181*5ffb0c9bSToomas Soome     PCPResult_UnsuppOpcode    = 4,
1182*5ffb0c9bSToomas Soome     PCPResult_UnsuppOption    = 5,
1183*5ffb0c9bSToomas Soome     PCPResult_MalformedOption = 6,
1184*5ffb0c9bSToomas Soome     PCPResult_NetworkFailure  = 7,
1185*5ffb0c9bSToomas Soome     PCPResult_NoResources     = 8,
1186*5ffb0c9bSToomas Soome     PCPResult_UnsuppProtocol  = 9,
1187*5ffb0c9bSToomas Soome     PCPResult_UserExQuota     = 10,
1188*5ffb0c9bSToomas Soome     PCPResult_CantProvideExt  = 11,
1189*5ffb0c9bSToomas Soome     PCPResult_AddrMismatch    = 12,
1190*5ffb0c9bSToomas Soome     PCPResult_ExcesRemotePeer = 13
1191*5ffb0c9bSToomas Soome } PCPResult_t;
1192*5ffb0c9bSToomas Soome 
1193*5ffb0c9bSToomas Soome typedef packedstruct
1194*5ffb0c9bSToomas Soome {
1195*5ffb0c9bSToomas Soome     mDNSu8       version;
1196*5ffb0c9bSToomas Soome     mDNSu8       opCode;
1197*5ffb0c9bSToomas Soome     mDNSOpaque16 reserved;
1198*5ffb0c9bSToomas Soome     mDNSu32      lifetime;
1199*5ffb0c9bSToomas Soome     mDNSv6Addr   clientAddr;
1200*5ffb0c9bSToomas Soome     mDNSu32      nonce[3];
1201*5ffb0c9bSToomas Soome     mDNSu8       protocol;
1202*5ffb0c9bSToomas Soome     mDNSu8       reservedMapOp[3];
1203*5ffb0c9bSToomas Soome     mDNSIPPort   intPort;
1204*5ffb0c9bSToomas Soome     mDNSIPPort   extPort;
1205*5ffb0c9bSToomas Soome     mDNSv6Addr   extAddress;
1206*5ffb0c9bSToomas Soome } PCPMapRequest;
1207*5ffb0c9bSToomas Soome 
1208*5ffb0c9bSToomas Soome typedef packedstruct
1209*5ffb0c9bSToomas Soome {
1210*5ffb0c9bSToomas Soome     mDNSu8     version;
1211*5ffb0c9bSToomas Soome     mDNSu8     opCode;
1212*5ffb0c9bSToomas Soome     mDNSu8     reserved;
1213*5ffb0c9bSToomas Soome     mDNSu8     result;
1214*5ffb0c9bSToomas Soome     mDNSu32    lifetime;
1215*5ffb0c9bSToomas Soome     mDNSu32    epoch;
1216*5ffb0c9bSToomas Soome     mDNSu32    clientAddrParts[3];
1217*5ffb0c9bSToomas Soome     mDNSu32    nonce[3];
1218*5ffb0c9bSToomas Soome     mDNSu8     protocol;
1219*5ffb0c9bSToomas Soome     mDNSu8     reservedMapOp[3];
1220*5ffb0c9bSToomas Soome     mDNSIPPort intPort;
1221*5ffb0c9bSToomas Soome     mDNSIPPort extPort;
1222*5ffb0c9bSToomas Soome     mDNSv6Addr extAddress;
1223*5ffb0c9bSToomas Soome } PCPMapReply;
1224*5ffb0c9bSToomas Soome 
1225*5ffb0c9bSToomas Soome // LNT Support
1226*5ffb0c9bSToomas Soome 
1227*5ffb0c9bSToomas Soome typedef enum
1228*5ffb0c9bSToomas Soome {
1229*5ffb0c9bSToomas Soome     LNTDiscoveryOp      = 1,
1230*5ffb0c9bSToomas Soome     LNTExternalAddrOp   = 2,
1231*5ffb0c9bSToomas Soome     LNTPortMapOp        = 3,
1232*5ffb0c9bSToomas Soome     LNTPortMapDeleteOp  = 4
1233*5ffb0c9bSToomas Soome } LNTOp_t;
1234*5ffb0c9bSToomas Soome 
1235*5ffb0c9bSToomas Soome #define LNT_MAXBUFSIZE 8192
1236*5ffb0c9bSToomas Soome typedef struct tcpLNTInfo_struct tcpLNTInfo;
1237*5ffb0c9bSToomas Soome struct tcpLNTInfo_struct
1238*5ffb0c9bSToomas Soome {
1239*5ffb0c9bSToomas Soome     tcpLNTInfo       *next;
1240*5ffb0c9bSToomas Soome     mDNS             *m;
1241*5ffb0c9bSToomas Soome     NATTraversalInfo *parentNATInfo;    // pointer back to the parent NATTraversalInfo
1242*5ffb0c9bSToomas Soome     TCPSocket        *sock;
1243*5ffb0c9bSToomas Soome     LNTOp_t op;                         // operation performed using this connection
1244*5ffb0c9bSToomas Soome     mDNSAddr Address;                   // router address
1245*5ffb0c9bSToomas Soome     mDNSIPPort Port;                    // router port
1246*5ffb0c9bSToomas Soome     mDNSu8           *Request;          // xml request to router
1247*5ffb0c9bSToomas Soome     int requestLen;
1248*5ffb0c9bSToomas Soome     mDNSu8           *Reply;            // xml reply from router
1249*5ffb0c9bSToomas Soome     int replyLen;
1250*5ffb0c9bSToomas Soome     unsigned long nread;                // number of bytes read so far
1251*5ffb0c9bSToomas Soome     int retries;                        // number of times we've tried to do this port mapping
1252*5ffb0c9bSToomas Soome };
1253*5ffb0c9bSToomas Soome 
1254*5ffb0c9bSToomas Soome typedef void (*NATTraversalClientCallback)(mDNS *m, NATTraversalInfo *n);
1255*5ffb0c9bSToomas Soome 
1256*5ffb0c9bSToomas Soome // if m->timenow <  ExpiryTime then we have an active mapping, and we'll renew halfway to expiry
1257*5ffb0c9bSToomas Soome // if m->timenow >= ExpiryTime then our mapping has expired, and we're trying to create one
1258*5ffb0c9bSToomas Soome 
1259*5ffb0c9bSToomas Soome typedef enum
1260*5ffb0c9bSToomas Soome {
1261*5ffb0c9bSToomas Soome     NATTProtocolNone    = 0,
1262*5ffb0c9bSToomas Soome     NATTProtocolNATPMP  = 1,
1263*5ffb0c9bSToomas Soome     NATTProtocolUPNPIGD = 2,
1264*5ffb0c9bSToomas Soome     NATTProtocolPCP     = 3,
1265*5ffb0c9bSToomas Soome } NATTProtocol;
1266*5ffb0c9bSToomas Soome 
1267*5ffb0c9bSToomas Soome struct NATTraversalInfo_struct
1268*5ffb0c9bSToomas Soome {
1269*5ffb0c9bSToomas Soome     // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
1270*5ffb0c9bSToomas Soome     NATTraversalInfo           *next;
1271*5ffb0c9bSToomas Soome 
1272*5ffb0c9bSToomas Soome     mDNSs32 ExpiryTime;                             // Time this mapping expires, or zero if no mapping
1273*5ffb0c9bSToomas Soome     mDNSs32 retryInterval;                          // Current interval, between last packet we sent and the next one
1274*5ffb0c9bSToomas Soome     mDNSs32 retryPortMap;                           // If Protocol is nonzero, time to send our next mapping packet
1275*5ffb0c9bSToomas Soome     mStatus NewResult;                              // New error code; will be copied to Result just prior to invoking callback
1276*5ffb0c9bSToomas Soome     NATTProtocol lastSuccessfulProtocol;            // To send correct deletion request & update non-PCP external address operations
1277*5ffb0c9bSToomas Soome     mDNSBool sentNATPMP;                            // Whether we just sent a NAT-PMP packet, so we won't send another if
1278*5ffb0c9bSToomas Soome                                                     //    we receive another NAT-PMP "Unsupported Version" packet
1279*5ffb0c9bSToomas Soome 
1280*5ffb0c9bSToomas Soome #ifdef _LEGACY_NAT_TRAVERSAL_
1281*5ffb0c9bSToomas Soome     tcpLNTInfo tcpInfo;                             // Legacy NAT traversal (UPnP) TCP connection
1282*5ffb0c9bSToomas Soome #endif
1283*5ffb0c9bSToomas Soome 
1284*5ffb0c9bSToomas Soome     // Result fields: When the callback is invoked these fields contain the answers the client is looking for
1285*5ffb0c9bSToomas Soome     // When the callback is invoked ExternalPort is *usually* set to be the same the same as RequestedPort, except:
1286*5ffb0c9bSToomas Soome     // (a) When we're behind a NAT gateway with port mapping disabled, ExternalPort is reported as zero to
1287*5ffb0c9bSToomas Soome     //     indicate that we don't currently have a working mapping (but RequestedPort retains the external port
1288*5ffb0c9bSToomas Soome     //     we'd like to get, the next time we meet an accomodating NAT gateway willing to give us one).
1289*5ffb0c9bSToomas Soome     // (b) When we have a routable non-RFC1918 address, we don't *need* a port mapping, so ExternalPort
1290*5ffb0c9bSToomas Soome     //     is reported as the same as our InternalPort, since that is effectively our externally-visible port too.
1291*5ffb0c9bSToomas Soome     //     Again, RequestedPort retains the external port we'd like to get the next time we find ourself behind a NAT gateway.
1292*5ffb0c9bSToomas Soome     // To improve stability of port mappings, RequestedPort is updated any time we get a successful
1293*5ffb0c9bSToomas Soome     // mapping response from the PCP, NAT-PMP or UPnP gateway. For example, if we ask for port 80, and
1294*5ffb0c9bSToomas Soome     // get assigned port 81, then thereafter we'll contine asking for port 81.
1295*5ffb0c9bSToomas Soome     mDNSInterfaceID InterfaceID;
1296*5ffb0c9bSToomas Soome     mDNSv4Addr ExternalAddress;                     // Initially set to onesIPv4Addr, until first callback
1297*5ffb0c9bSToomas Soome     mDNSv4Addr NewAddress;                          // May be updated with actual value assigned by gateway
1298*5ffb0c9bSToomas Soome     mDNSIPPort ExternalPort;
1299*5ffb0c9bSToomas Soome     mDNSu32 Lifetime;
1300*5ffb0c9bSToomas Soome     mStatus Result;
1301*5ffb0c9bSToomas Soome 
1302*5ffb0c9bSToomas Soome     // Client API fields: The client must set up these fields *before* making any NAT traversal API calls
1303*5ffb0c9bSToomas Soome     mDNSu8 Protocol;                                // NATOp_MapUDP or NATOp_MapTCP, or zero if just requesting the external IP address
1304*5ffb0c9bSToomas Soome     mDNSIPPort IntPort;                             // Client's internal port number (doesn't change)
1305*5ffb0c9bSToomas Soome     mDNSIPPort RequestedPort;                       // Requested external port; may be updated with actual value assigned by gateway
1306*5ffb0c9bSToomas Soome     mDNSu32 NATLease;                               // Requested lifetime in seconds (doesn't change)
1307*5ffb0c9bSToomas Soome     NATTraversalClientCallback clientCallback;
1308*5ffb0c9bSToomas Soome     void                       *clientContext;
1309*5ffb0c9bSToomas Soome };
1310*5ffb0c9bSToomas Soome 
1311*5ffb0c9bSToomas Soome // ***************************************************************************
1312*5ffb0c9bSToomas Soome #if 0
1313*5ffb0c9bSToomas Soome #pragma mark -
1314*5ffb0c9bSToomas Soome #pragma mark - DNSServer & McastResolver structures and constants
1315*5ffb0c9bSToomas Soome #endif
1316*5ffb0c9bSToomas Soome 
1317*5ffb0c9bSToomas Soome enum
1318*5ffb0c9bSToomas Soome {
1319*5ffb0c9bSToomas Soome     DNSServer_Untested = 0,
1320*5ffb0c9bSToomas Soome     DNSServer_Passed   = 1,
1321*5ffb0c9bSToomas Soome     DNSServer_Failed   = 2,
1322*5ffb0c9bSToomas Soome     DNSServer_Disabled = 3
1323*5ffb0c9bSToomas Soome };
1324*5ffb0c9bSToomas Soome 
1325*5ffb0c9bSToomas Soome enum
1326*5ffb0c9bSToomas Soome {
1327*5ffb0c9bSToomas Soome     DNSServer_FlagDelete = 1,
1328*5ffb0c9bSToomas Soome     DNSServer_FlagNew    = 2
1329*5ffb0c9bSToomas Soome };
1330*5ffb0c9bSToomas Soome 
1331*5ffb0c9bSToomas Soome enum
1332*5ffb0c9bSToomas Soome {
1333*5ffb0c9bSToomas Soome     McastResolver_FlagDelete = 1,
1334*5ffb0c9bSToomas Soome     McastResolver_FlagNew    = 2
1335*5ffb0c9bSToomas Soome };
1336*5ffb0c9bSToomas Soome 
1337*5ffb0c9bSToomas Soome typedef struct McastResolver
1338*5ffb0c9bSToomas Soome {
1339*5ffb0c9bSToomas Soome     struct McastResolver *next;
1340*5ffb0c9bSToomas Soome     mDNSInterfaceID interface;
1341*5ffb0c9bSToomas Soome     mDNSu32 flags;              // Set when we're planning to delete this from the list
1342*5ffb0c9bSToomas Soome     domainname domain;
1343*5ffb0c9bSToomas Soome     mDNSu32 timeout;            // timeout value for questions
1344*5ffb0c9bSToomas Soome } McastResolver;
1345*5ffb0c9bSToomas Soome 
1346*5ffb0c9bSToomas Soome // scoped values for DNSServer matching
1347*5ffb0c9bSToomas Soome enum
1348*5ffb0c9bSToomas Soome {
1349*5ffb0c9bSToomas Soome     kScopeNone         = 0,        // DNS server used by unscoped questions
1350*5ffb0c9bSToomas Soome     kScopeInterfaceID  = 1,        // Scoped DNS server used only by scoped questions
1351*5ffb0c9bSToomas Soome     kScopeServiceID    = 2         // Service specific DNS server used only by questions
1352*5ffb0c9bSToomas Soome                                    // have a matching serviceID
1353*5ffb0c9bSToomas Soome };
1354*5ffb0c9bSToomas Soome 
1355*5ffb0c9bSToomas Soome // Note: DNSSECAware is set if we are able to get a valid response to
1356*5ffb0c9bSToomas Soome // a DNSSEC question. In some cases it is possible that the proxy
1357*5ffb0c9bSToomas Soome // strips the EDNS0 option and we just get a plain response with no
1358*5ffb0c9bSToomas Soome // signatures. But we still mark DNSSECAware in that case. As DNSSECAware
1359*5ffb0c9bSToomas Soome // is only used to determine whether DNSSEC_VALIDATION_SECURE_OPTIONAL
1360*5ffb0c9bSToomas Soome // should be turned off or not, it is sufficient that we are getting
1361*5ffb0c9bSToomas Soome // responses back.
1362*5ffb0c9bSToomas Soome typedef struct DNSServer
1363*5ffb0c9bSToomas Soome {
1364*5ffb0c9bSToomas Soome     struct DNSServer *next;
1365*5ffb0c9bSToomas Soome     mDNSInterfaceID interface;  // DNS requests should be sent on this interface
1366*5ffb0c9bSToomas Soome     mDNSs32 serviceID;
1367*5ffb0c9bSToomas Soome     mDNSAddr addr;
1368*5ffb0c9bSToomas Soome     mDNSIPPort port;
1369*5ffb0c9bSToomas Soome     mDNSOpaque16 testid;
1370*5ffb0c9bSToomas Soome     mDNSu32 flags;              // Set when we're planning to delete this from the list
1371*5ffb0c9bSToomas Soome     mDNSu32 teststate;          // Have we sent bug-detection query to this server?
1372*5ffb0c9bSToomas Soome     mDNSs32 lasttest;           // Time we sent last bug-detection query to this server
1373*5ffb0c9bSToomas Soome     domainname domain;          // name->server matching for "split dns"
1374*5ffb0c9bSToomas Soome     mDNSs32 penaltyTime;        // amount of time this server is penalized
1375*5ffb0c9bSToomas Soome     mDNSu32 scoped;             // See the scoped enum above
1376*5ffb0c9bSToomas Soome     mDNSu32 timeout;            // timeout value for questions
1377*5ffb0c9bSToomas Soome     mDNSBool cellIntf;          // Resolver from Cellular Interface ?
1378*5ffb0c9bSToomas Soome     mDNSu16 resGroupID;         // ID of the resolver group that contains this DNSServer
1379*5ffb0c9bSToomas Soome     mDNSBool req_A;             // If set, send v4 query (DNSConfig allows A queries)
1380*5ffb0c9bSToomas Soome     mDNSBool req_AAAA;          // If set, send v6 query (DNSConfig allows AAAA queries)
1381*5ffb0c9bSToomas Soome     mDNSBool req_DO;            // If set, okay to send DNSSEC queries (EDNS DO bit is supported)
1382*5ffb0c9bSToomas Soome     mDNSBool retransDO;         // Total Retransmissions for queries sent with DO option
1383*5ffb0c9bSToomas Soome     mDNSBool DNSSECAware;       // set if we are able to receive a response to a request
1384*5ffb0c9bSToomas Soome                                 // sent with DO option.
1385*5ffb0c9bSToomas Soome } DNSServer;
13864b22b933Srs200217 
13874b22b933Srs200217 typedef struct
13884b22b933Srs200217 {
1389*5ffb0c9bSToomas Soome     mDNSu8 *AnonData;
1390*5ffb0c9bSToomas Soome     int AnonDataLen;
1391*5ffb0c9bSToomas Soome     mDNSu32 salt;
1392*5ffb0c9bSToomas Soome     ResourceRecord *nsec3RR;
1393*5ffb0c9bSToomas Soome     mDNSInterfaceID SendNow;     // The interface ID that this record should be sent on
1394*5ffb0c9bSToomas Soome } AnonymousInfo;
1395*5ffb0c9bSToomas Soome 
1396*5ffb0c9bSToomas Soome struct ResourceRecord_struct
1397*5ffb0c9bSToomas Soome {
13984b22b933Srs200217     mDNSu8 RecordType;                  // See enum above
13994b22b933Srs200217     mDNSu16 rrtype;
14004b22b933Srs200217     mDNSu16 rrclass;
14014b22b933Srs200217     mDNSu32 rroriginalttl;              // In seconds
1402*5ffb0c9bSToomas Soome     mDNSu16 rdlength;                   // Size of the raw rdata, in bytes, in the on-the-wire format
1403*5ffb0c9bSToomas Soome                                         // (In-memory storage may be larger, for structures containing 'holes', like SOA)
1404*5ffb0c9bSToomas Soome     mDNSu16 rdestimate;                 // Upper bound on on-the-wire size of rdata after name compression
14054b22b933Srs200217     mDNSu32 namehash;                   // Name-based (i.e. case-insensitive) hash of name
14064b22b933Srs200217     mDNSu32 rdatahash;                  // For rdata containing domain name (e.g. PTR, SRV, CNAME etc.), case-insensitive name hash
14074b22b933Srs200217                                         // else, for all other rdata, 32-bit hash of the raw rdata
14084b22b933Srs200217                                         // Note: This requirement is important. Various routines like AddAdditionalsToResponseList(),
14094b22b933Srs200217                                         // ReconfirmAntecedents(), etc., use rdatahash as a pre-flight check to see
14104b22b933Srs200217                                         // whether it's worth doing a full SameDomainName() call. If the rdatahash
14114b22b933Srs200217                                         // is not a correct case-insensitive name hash, they'll get false negatives.
1412*5ffb0c9bSToomas Soome 
1413*5ffb0c9bSToomas Soome     // Grouping pointers together at the end of the structure improves the memory layout efficiency
1414*5ffb0c9bSToomas Soome     mDNSInterfaceID InterfaceID;        // Set if this RR is specific to one interface
1415*5ffb0c9bSToomas Soome                                         // For records received off the wire, InterfaceID is *always* set to the receiving interface
1416*5ffb0c9bSToomas Soome                                         // For our authoritative records, InterfaceID is usually zero, except for those few records
1417*5ffb0c9bSToomas Soome                                         // that are interface-specific (e.g. address records, especially linklocal addresses)
1418*5ffb0c9bSToomas Soome     const domainname *name;
14194b22b933Srs200217     RData           *rdata;             // Pointer to storage for this rdata
1420*5ffb0c9bSToomas Soome     DNSServer       *rDNSServer;        // Unicast DNS server authoritative for this entry;null for multicast
1421*5ffb0c9bSToomas Soome     AnonymousInfo   *AnonInfo;          // Anonymous Information
1422*5ffb0c9bSToomas Soome };
1423*5ffb0c9bSToomas Soome 
14244b22b933Srs200217 
14254b22b933Srs200217 // Unless otherwise noted, states may apply to either independent record registrations or service registrations
14264b22b933Srs200217 typedef enum
14274b22b933Srs200217 {
1428*5ffb0c9bSToomas Soome     regState_Zero              = 0,
1429*5ffb0c9bSToomas Soome     regState_Pending           = 1,     // update sent, reply not received
1430*5ffb0c9bSToomas Soome     regState_Registered        = 2,     // update sent, reply received
1431*5ffb0c9bSToomas Soome     regState_DeregPending      = 3,     // dereg sent, reply not received
1432*5ffb0c9bSToomas Soome     regState_Unregistered      = 4,     // not in any list
1433*5ffb0c9bSToomas Soome     regState_Refresh           = 5,     // outstanding refresh (or target change) message
1434*5ffb0c9bSToomas Soome     regState_NATMap            = 6,     // establishing NAT port mapping
1435*5ffb0c9bSToomas Soome     regState_UpdatePending     = 7,     // update in flight as result of mDNS_Update call
1436*5ffb0c9bSToomas Soome     regState_NoTarget          = 8,     // SRV Record registration pending registration of hostname
1437*5ffb0c9bSToomas Soome     regState_NATError          = 9     // unable to complete NAT traversal
14384b22b933Srs200217 } regState_t;
14394b22b933Srs200217 
1440*5ffb0c9bSToomas Soome enum
14414b22b933Srs200217 {
1442*5ffb0c9bSToomas Soome     Target_Manual = 0,
1443*5ffb0c9bSToomas Soome     Target_AutoHost = 1,
1444*5ffb0c9bSToomas Soome     Target_AutoHostAndNATMAP = 2
1445*5ffb0c9bSToomas Soome };
14464b22b933Srs200217 
1447*5ffb0c9bSToomas Soome typedef enum
1448*5ffb0c9bSToomas Soome {
1449*5ffb0c9bSToomas Soome     mergeState_Zero = 0,
1450*5ffb0c9bSToomas Soome     mergeState_DontMerge = 1  // Set on fatal error conditions to disable merging
1451*5ffb0c9bSToomas Soome } mergeState_t;
14524b22b933Srs200217 
1453*5ffb0c9bSToomas Soome #define AUTH_GROUP_NAME_SIZE    128
1454*5ffb0c9bSToomas Soome struct AuthGroup_struct             // Header object for a list of AuthRecords with the same name
1455*5ffb0c9bSToomas Soome {
1456*5ffb0c9bSToomas Soome     AuthGroup      *next;               // Next AuthGroup object in this hash table bucket
1457*5ffb0c9bSToomas Soome     mDNSu32 namehash;                   // Name-based (i.e. case insensitive) hash of name
1458*5ffb0c9bSToomas Soome     AuthRecord     *members;            // List of CacheRecords with this same name
1459*5ffb0c9bSToomas Soome     AuthRecord    **rrauth_tail;        // Tail end of that list
1460*5ffb0c9bSToomas Soome     domainname     *name;               // Common name for all AuthRecords in this list
1461*5ffb0c9bSToomas Soome     AuthRecord     *NewLocalOnlyRecords;
1462*5ffb0c9bSToomas Soome     mDNSu8 namestorage[AUTH_GROUP_NAME_SIZE];
1463*5ffb0c9bSToomas Soome };
14644b22b933Srs200217 
1465*5ffb0c9bSToomas Soome #ifndef AUTH_HASH_SLOTS
1466*5ffb0c9bSToomas Soome #define AUTH_HASH_SLOTS 499
1467*5ffb0c9bSToomas Soome #endif
1468*5ffb0c9bSToomas Soome #define FORALL_AUTHRECORDS(SLOT,AG,AR)                              \
1469*5ffb0c9bSToomas Soome     for ((SLOT) = 0; (SLOT) < AUTH_HASH_SLOTS; (SLOT)++)                                                                     \
1470*5ffb0c9bSToomas Soome         for ((AG)=m->rrauth.rrauth_hash[(SLOT)]; (AG); (AG)=(AG)->next)                                                                         \
1471*5ffb0c9bSToomas Soome             for ((AR) = (AG)->members; (AR); (AR)=(AR)->next)
14724b22b933Srs200217 
1473*5ffb0c9bSToomas Soome typedef union AuthEntity_union AuthEntity;
1474*5ffb0c9bSToomas Soome union AuthEntity_union { AuthEntity *next; AuthGroup ag; };
1475*5ffb0c9bSToomas Soome typedef struct {
1476*5ffb0c9bSToomas Soome     mDNSu32 rrauth_size;                // Total number of available auth entries
1477*5ffb0c9bSToomas Soome     mDNSu32 rrauth_totalused;           // Number of auth entries currently occupied
1478*5ffb0c9bSToomas Soome     mDNSu32 rrauth_report;
1479*5ffb0c9bSToomas Soome     mDNSu8 rrauth_lock;                 // For debugging: Set at times when these lists may not be modified
1480*5ffb0c9bSToomas Soome     AuthEntity *rrauth_free;
1481*5ffb0c9bSToomas Soome     AuthGroup *rrauth_hash[AUTH_HASH_SLOTS];
1482*5ffb0c9bSToomas Soome }AuthHash;
14834b22b933Srs200217 
1484*5ffb0c9bSToomas Soome // AuthRecordAny includes mDNSInterface_Any and interface specific auth records.
1485*5ffb0c9bSToomas Soome typedef enum
1486*5ffb0c9bSToomas Soome {
1487*5ffb0c9bSToomas Soome     AuthRecordAny,              // registered for *Any, NOT including P2P interfaces
1488*5ffb0c9bSToomas Soome     AuthRecordAnyIncludeP2P,    // registered for *Any, including P2P interfaces
1489*5ffb0c9bSToomas Soome     AuthRecordAnyIncludeAWDL,   // registered for *Any, including AWDL interface
1490*5ffb0c9bSToomas Soome     AuthRecordAnyIncludeAWDLandP2P, // registered for *Any, including AWDL and P2P interfaces
1491*5ffb0c9bSToomas Soome     AuthRecordLocalOnly,
1492*5ffb0c9bSToomas Soome     AuthRecordP2P               // discovered over D2D/P2P framework
1493*5ffb0c9bSToomas Soome } AuthRecType;
1494*5ffb0c9bSToomas Soome 
1495*5ffb0c9bSToomas Soome typedef enum
1496*5ffb0c9bSToomas Soome {
1497*5ffb0c9bSToomas Soome     AuthFlagsWakeOnly = 0x1     // WakeOnly service
1498*5ffb0c9bSToomas Soome } AuthRecordFlags;
14994b22b933Srs200217 
15004b22b933Srs200217 struct AuthRecord_struct
15014b22b933Srs200217 {
15024b22b933Srs200217     // For examples of how to set up this structure for use in mDNS_Register(),
15034b22b933Srs200217     // see mDNS_AdvertiseInterface() or mDNS_RegisterService().
15044b22b933Srs200217     // Basically, resrec and persistent metadata need to be set up before calling mDNS_Register().
15054b22b933Srs200217     // mDNS_SetupResourceRecord() is avaliable as a helper routine to set up most fields to sensible default values for you
15064b22b933Srs200217 
15074b22b933Srs200217     AuthRecord     *next;               // Next in list; first element of structure for efficiency reasons
15084b22b933Srs200217     // Field Group 1: Common ResourceRecord fields
1509*5ffb0c9bSToomas Soome     ResourceRecord resrec;              // 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit
15104b22b933Srs200217 
15114b22b933Srs200217     // Field Group 2: Persistent metadata for Authoritative Records
1512*5ffb0c9bSToomas Soome     AuthRecord     *Additional1;        // Recommended additional record to include in response (e.g. SRV for PTR record)
1513*5ffb0c9bSToomas Soome     AuthRecord     *Additional2;        // Another additional (e.g. TXT for PTR record)
15144b22b933Srs200217     AuthRecord     *DependentOn;        // This record depends on another for its uniqueness checking
15154b22b933Srs200217     AuthRecord     *RRSet;              // This unique record is part of an RRSet
15164b22b933Srs200217     mDNSRecordCallback *RecordCallback; // Callback function to call for state changes, and to free memory asynchronously on deregistration
15174b22b933Srs200217     void           *RecordContext;      // Context parameter for the callback function
1518*5ffb0c9bSToomas Soome     mDNSu8 AutoTarget;                  // Set if the target of this record (PTR, CNAME, SRV, etc.) is our host name
15194b22b933Srs200217     mDNSu8 AllowRemoteQuery;            // Set if we allow hosts not on the local link to query this record
15204b22b933Srs200217     mDNSu8 ForceMCast;                  // Set by client to advertise solely via multicast, even for apparently unicast names
1521*5ffb0c9bSToomas Soome     mDNSu8 AuthFlags;
1522*5ffb0c9bSToomas Soome 
1523*5ffb0c9bSToomas Soome     OwnerOptData WakeUp;                // WakeUp.HMAC.l[0] nonzero indicates that this is a Sleep Proxy record
1524*5ffb0c9bSToomas Soome     mDNSAddr AddressProxy;              // For reverse-mapping Sleep Proxy PTR records, address in question
1525*5ffb0c9bSToomas Soome     mDNSs32 TimeRcvd;                   // In platform time units
1526*5ffb0c9bSToomas Soome     mDNSs32 TimeExpire;                 // In platform time units
1527*5ffb0c9bSToomas Soome     AuthRecType ARType;                 // LocalOnly, P2P or Normal ?
1528*5ffb0c9bSToomas Soome     mDNSs32 KATimeExpire;               // In platform time units: time to send keepalive packet for the proxy record
15294b22b933Srs200217 
15304b22b933Srs200217     // Field Group 3: Transient state for Authoritative Records
15314b22b933Srs200217     mDNSu8 Acknowledged;                // Set if we've given the success callback to the client
1532*5ffb0c9bSToomas Soome     mDNSu8 ProbeRestartCount;           // Number of times we have restarted probing
15334b22b933Srs200217     mDNSu8 ProbeCount;                  // Number of probes remaining before this record is valid (kDNSRecordTypeUnique)
15344b22b933Srs200217     mDNSu8 AnnounceCount;               // Number of announcements remaining (kDNSRecordTypeShared)
15354b22b933Srs200217     mDNSu8 RequireGoodbye;              // Set if this RR has been announced on the wire and will require a goodbye packet
1536*5ffb0c9bSToomas Soome     mDNSu8 AnsweredLocalQ;              // Set if this AuthRecord has been delivered to any local question (LocalOnly or mDNSInterface_Any)
15374b22b933Srs200217     mDNSu8 IncludeInProbe;              // Set if this RR is being put into a probe right now
15384b22b933Srs200217     mDNSu8 ImmedUnicast;                // Set if we may send our response directly via unicast to the requester
1539*5ffb0c9bSToomas Soome     mDNSInterfaceID SendNSECNow;        // Set if we need to generate associated NSEC data for this rrname
1540*5ffb0c9bSToomas Soome     mDNSInterfaceID ImmedAnswer;        // Someone on this interface issued a query we need to answer (all-ones for all interfaces)
15414b22b933Srs200217 #if MDNS_LOG_ANSWER_SUPPRESSION_TIMES
15424b22b933Srs200217     mDNSs32 ImmedAnswerMarkTime;
15434b22b933Srs200217 #endif
15444b22b933Srs200217     mDNSInterfaceID ImmedAdditional;    // Hint that we might want to also send this record, just to be helpful
15454b22b933Srs200217     mDNSInterfaceID SendRNow;           // The interface this query is being sent on right now
15464b22b933Srs200217     mDNSv4Addr v4Requester;             // Recent v4 query for this record, or all-ones if more than one recent query
15474b22b933Srs200217     mDNSv6Addr v6Requester;             // Recent v6 query for this record, or all-ones if more than one recent query
15484b22b933Srs200217     AuthRecord     *NextResponse;       // Link to the next element in the chain of responses to generate
15494b22b933Srs200217     const mDNSu8   *NR_AnswerTo;        // Set if this record was selected by virtue of being a direct answer to a question
15504b22b933Srs200217     AuthRecord     *NR_AdditionalTo;    // Set if this record was selected by virtue of being additional to another
15514b22b933Srs200217     mDNSs32 ThisAPInterval;             // In platform time units: Current interval for announce/probe
15524b22b933Srs200217     mDNSs32 LastAPTime;                 // In platform time units: Last time we sent announcement/probe
15534b22b933Srs200217     mDNSs32 LastMCTime;                 // Last time we multicast this record (used to guard against packet-storm attacks)
15544b22b933Srs200217     mDNSInterfaceID LastMCInterface;    // Interface this record was multicast on at the time LastMCTime was recorded
15554b22b933Srs200217     RData          *NewRData;           // Set if we are updating this record with new rdata
15564b22b933Srs200217     mDNSu16 newrdlength;                // ... and the length of the new RData
15574b22b933Srs200217     mDNSRecordUpdateCallback *UpdateCallback;
15584b22b933Srs200217     mDNSu32 UpdateCredits;              // Token-bucket rate limiting of excessive updates
15594b22b933Srs200217     mDNSs32 NextUpdateCredit;           // Time next token is added to bucket
15604b22b933Srs200217     mDNSs32 UpdateBlocked;              // Set if update delaying is in effect
15614b22b933Srs200217 
1562*5ffb0c9bSToomas Soome     // Field Group 4: Transient uDNS state for Authoritative Records
1563*5ffb0c9bSToomas Soome     regState_t state;           // Maybe combine this with resrec.RecordType state? Right now it's ambiguous and confusing.
1564*5ffb0c9bSToomas Soome                                 // e.g. rr->resrec.RecordType can be kDNSRecordTypeUnregistered,
1565*5ffb0c9bSToomas Soome                                 // and rr->state can be regState_Unregistered
1566*5ffb0c9bSToomas Soome                                 // What if we find one of those statements is true and the other false? What does that mean?
1567*5ffb0c9bSToomas Soome     mDNSBool uselease;          // dynamic update contains (should contain) lease option
1568*5ffb0c9bSToomas Soome     mDNSs32 expire;             // In platform time units: expiration of lease (-1 for static)
1569*5ffb0c9bSToomas Soome     mDNSBool Private;           // If zone is private, DNS updates may have to be encrypted to prevent eavesdropping
1570*5ffb0c9bSToomas Soome     mDNSOpaque16 updateid;      // Identifier to match update request and response -- also used when transferring records to Sleep Proxy
1571*5ffb0c9bSToomas Soome     mDNSOpaque64 updateIntID;   // Interface IDs (one bit per interface index)to which updates have been sent
1572*5ffb0c9bSToomas Soome     const domainname *zone;     // the zone that is updated
1573*5ffb0c9bSToomas Soome     ZoneData  *nta;
1574*5ffb0c9bSToomas Soome     struct tcpInfo_t *tcp;
1575*5ffb0c9bSToomas Soome     NATTraversalInfo NATinfo;
1576*5ffb0c9bSToomas Soome     mDNSBool SRVChanged;       // temporarily deregistered service because its SRV target or port changed
1577*5ffb0c9bSToomas Soome     mergeState_t mState;       // Unicast Record Registrations merge state
1578*5ffb0c9bSToomas Soome     mDNSu8 refreshCount;        // Number of refreshes to the server
1579*5ffb0c9bSToomas Soome     mStatus updateError;        // Record update resulted in Error ?
1580*5ffb0c9bSToomas Soome 
1581*5ffb0c9bSToomas Soome     // uDNS_UpdateRecord support fields
1582*5ffb0c9bSToomas Soome     // Do we really need all these in *addition* to NewRData and newrdlength above?
1583*5ffb0c9bSToomas Soome     void *UpdateContext;    // Context parameter for the update callback function
1584*5ffb0c9bSToomas Soome     mDNSu16 OrigRDLen;      // previously registered, being deleted
1585*5ffb0c9bSToomas Soome     mDNSu16 InFlightRDLen;  // currently being registered
1586*5ffb0c9bSToomas Soome     mDNSu16 QueuedRDLen;    // pending operation (re-transmitting if necessary) THEN register the queued update
1587*5ffb0c9bSToomas Soome     RData *OrigRData;
1588*5ffb0c9bSToomas Soome     RData *InFlightRData;
1589*5ffb0c9bSToomas Soome     RData *QueuedRData;
1590*5ffb0c9bSToomas Soome 
1591*5ffb0c9bSToomas Soome     // Field Group 5: Large data objects go at the end
15924b22b933Srs200217     domainname namestorage;
15934b22b933Srs200217     RData rdatastorage;                 // Normally the storage is right here, except for oversized records
15944b22b933Srs200217     // rdatastorage MUST be the last thing in the structure -- when using oversized AuthRecords, extra bytes
15954b22b933Srs200217     // are appended after the end of the AuthRecord, logically augmenting the size of the rdatastorage
15964b22b933Srs200217     // DO NOT ADD ANY MORE FIELDS HERE
15974b22b933Srs200217 };
15984b22b933Srs200217 
1599*5ffb0c9bSToomas Soome // IsLocalDomain alone is not sufficient to determine that a record is mDNS or uDNS. By default domain names within
1600*5ffb0c9bSToomas Soome // the "local" pseudo-TLD (and within the IPv4 and IPv6 link-local reverse mapping domains) are automatically treated
1601*5ffb0c9bSToomas Soome // as mDNS records, but it is also possible to force any record (even those not within one of the inherently local
1602*5ffb0c9bSToomas Soome // domains) to be handled as an mDNS record by setting the ForceMCast flag, or by setting a non-zero InterfaceID.
1603*5ffb0c9bSToomas Soome // For example, the reverse-mapping PTR record created in AdvertiseInterface sets the ForceMCast flag, since it points to
1604*5ffb0c9bSToomas Soome // a dot-local hostname, and therefore it would make no sense to register this record with a wide-area Unicast DNS server.
1605*5ffb0c9bSToomas Soome // The same applies to Sleep Proxy records, which we will answer for when queried via mDNS, but we never want to try
1606*5ffb0c9bSToomas Soome // to register them with a wide-area Unicast DNS server -- and we probably don't have the required credentials anyway.
1607*5ffb0c9bSToomas Soome // Currently we have no concept of a wide-area uDNS record scoped to a particular interface, so if the InterfaceID is
1608*5ffb0c9bSToomas Soome // nonzero we treat this the same as ForceMCast.
1609*5ffb0c9bSToomas Soome // Note: Question_uDNS(Q) is used in *only* one place -- on entry to mDNS_StartQuery_internal, to decide whether to set TargetQID.
1610*5ffb0c9bSToomas Soome // Everywhere else in the code, the determination of whether a question is unicast is made by checking to see if TargetQID is nonzero.
1611*5ffb0c9bSToomas Soome #define AuthRecord_uDNS(R) ((R)->resrec.InterfaceID == mDNSInterface_Any && !(R)->ForceMCast && !IsLocalDomain((R)->resrec.name))
1612*5ffb0c9bSToomas Soome #define Question_uDNS(Q)   ((Q)->InterfaceID == mDNSInterface_Unicast || (Q)->ProxyQuestion || \
1613*5ffb0c9bSToomas Soome                             ((Q)->InterfaceID != mDNSInterface_LocalOnly && (Q)->InterfaceID != mDNSInterface_P2P && !(Q)->ForceMCast && !IsLocalDomain(&(Q)->qname)))
1614*5ffb0c9bSToomas Soome 
1615*5ffb0c9bSToomas Soome #define RRLocalOnly(rr) ((rr)->ARType == AuthRecordLocalOnly || (rr)->ARType == AuthRecordP2P)
1616*5ffb0c9bSToomas Soome 
1617*5ffb0c9bSToomas Soome #define RRAny(rr) ((rr)->ARType == AuthRecordAny || (rr)->ARType == AuthRecordAnyIncludeP2P || (rr)->ARType == AuthRecordAnyIncludeAWDL || (rr)->ARType == AuthRecordAnyIncludeAWDLandP2P)
1618*5ffb0c9bSToomas Soome 
1619*5ffb0c9bSToomas Soome // Question (A or AAAA) that is suppressed currently because IPv4 or IPv6 address
1620*5ffb0c9bSToomas Soome // is not available locally for A or AAAA question respectively. Also, if the
1621*5ffb0c9bSToomas Soome // query is disallowed for the "pid" that we are sending on behalf of, suppress it.
1622*5ffb0c9bSToomas Soome #define QuerySuppressed(Q) (((Q)->SuppressUnusable && (Q)->SuppressQuery) || ((Q)->DisallowPID))
1623*5ffb0c9bSToomas Soome 
1624*5ffb0c9bSToomas Soome #define PrivateQuery(Q) ((Q)->AuthInfo && (Q)->AuthInfo->AutoTunnel)
1625*5ffb0c9bSToomas Soome 
1626*5ffb0c9bSToomas Soome // Normally we always lookup the cache and /etc/hosts before sending the query on the wire. For single label
1627*5ffb0c9bSToomas Soome // queries (A and AAAA) that are unqualified (indicated by AppendSearchDomains), we want to append search
1628*5ffb0c9bSToomas Soome // domains before we try them as such
1629*5ffb0c9bSToomas Soome #define ApplySearchDomainsFirst(q) ((q)->AppendSearchDomains && (CountLabels(&((q)->qname))) == 1)
1630*5ffb0c9bSToomas Soome 
16314b22b933Srs200217 // Wrapper struct for Auth Records for higher-level code that cannot use the AuthRecord's ->next pointer field
16324b22b933Srs200217 typedef struct ARListElem
16334b22b933Srs200217 {
16344b22b933Srs200217     struct ARListElem *next;
1635*5ffb0c9bSToomas Soome     AuthRecord ar;          // Note: Must be last element of structure, to accomodate oversized AuthRecords
16364b22b933Srs200217 } ARListElem;
16374b22b933Srs200217 
1638*5ffb0c9bSToomas Soome struct CacheRecord_struct
1639*5ffb0c9bSToomas Soome {
1640*5ffb0c9bSToomas Soome     CacheRecord    *next;               // Next in list; first element of structure for efficiency reasons
1641*5ffb0c9bSToomas Soome     ResourceRecord resrec;              // 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit
1642*5ffb0c9bSToomas Soome 
1643*5ffb0c9bSToomas Soome     // Transient state for Cache Records
1644*5ffb0c9bSToomas Soome     CacheRecord    *NextInKAList;       // Link to the next element in the chain of known answers to send
1645*5ffb0c9bSToomas Soome     mDNSs32 TimeRcvd;                   // In platform time units
1646*5ffb0c9bSToomas Soome     mDNSs32 DelayDelivery;              // Set if we want to defer delivery of this answer to local clients
1647*5ffb0c9bSToomas Soome     mDNSs32 NextRequiredQuery;          // In platform time units
1648*5ffb0c9bSToomas Soome     mDNSs32 LastUsed;                   // In platform time units
1649*5ffb0c9bSToomas Soome     DNSQuestion    *CRActiveQuestion;   // Points to an active question referencing this answer. Can never point to a NewQuestion.
1650*5ffb0c9bSToomas Soome     mDNSs32 LastUnansweredTime;         // In platform time units; last time we incremented UnansweredQueries
1651*5ffb0c9bSToomas Soome     mDNSu8  UnansweredQueries;          // Number of times we've issued a query for this record without getting an answer
1652*5ffb0c9bSToomas Soome     mDNSu8  CRDNSSECQuestion;           // Set to 1 if this was created in response to a DNSSEC question
1653*5ffb0c9bSToomas Soome     mDNSOpaque16 responseFlags;         // Second 16 bit in the DNS response
1654*5ffb0c9bSToomas Soome #if ENABLE_MULTI_PACKET_QUERY_SNOOPING
1655*5ffb0c9bSToomas Soome     mDNSu32 MPUnansweredQ;              // Multi-packet query handling: Number of times we've seen a query for this record
1656*5ffb0c9bSToomas Soome     mDNSs32 MPLastUnansweredQT;         // Multi-packet query handling: Last time we incremented MPUnansweredQ
1657*5ffb0c9bSToomas Soome     mDNSu32 MPUnansweredKA;             // Multi-packet query handling: Number of times we've seen this record in a KA list
1658*5ffb0c9bSToomas Soome     mDNSBool MPExpectingKA;             // Multi-packet query handling: Set when we increment MPUnansweredQ; allows one KA
1659*5ffb0c9bSToomas Soome #endif
1660*5ffb0c9bSToomas Soome     CacheRecord    *NextInCFList;       // Set if this is in the list of records we just received with the cache flush bit set
1661*5ffb0c9bSToomas Soome     CacheRecord    *nsec;               // NSEC records needed for non-existence proofs
1662*5ffb0c9bSToomas Soome     CacheRecord    *soa;                // SOA record to return for proxy questions
1663*5ffb0c9bSToomas Soome 
1664*5ffb0c9bSToomas Soome     mDNSAddr sourceAddress;             // node from which we received this record
1665*5ffb0c9bSToomas Soome     // Size to here is 76 bytes when compiling 32-bit; 104 bytes when compiling 64-bit
1666*5ffb0c9bSToomas Soome     RData_small smallrdatastorage;      // Storage for small records is right here (4 bytes header + 68 bytes data = 72 bytes)
1667*5ffb0c9bSToomas Soome };
1668*5ffb0c9bSToomas Soome 
1669*5ffb0c9bSToomas Soome // Should match the CacheGroup_struct members, except namestorage[].  Only used to calculate
1670*5ffb0c9bSToomas Soome // the size of the namestorage array in CacheGroup_struct so that
1671*5ffb0c9bSToomas Soome // sizeof(CacheGroup) == sizeof(CacheRecord)
1672*5ffb0c9bSToomas Soome struct CacheGroup_base
1673*5ffb0c9bSToomas Soome {
1674*5ffb0c9bSToomas Soome     CacheGroup     *next;
1675*5ffb0c9bSToomas Soome     mDNSu32         namehash;
1676*5ffb0c9bSToomas Soome     CacheRecord    *members;
1677*5ffb0c9bSToomas Soome     CacheRecord   **rrcache_tail;
1678*5ffb0c9bSToomas Soome     domainname     *name;
1679*5ffb0c9bSToomas Soome };
1680*5ffb0c9bSToomas Soome 
16814b22b933Srs200217 struct CacheGroup_struct                // Header object for a list of CacheRecords with the same name
16824b22b933Srs200217 {
16834b22b933Srs200217     CacheGroup     *next;               // Next CacheGroup object in this hash table bucket
16844b22b933Srs200217     mDNSu32         namehash;           // Name-based (i.e. case insensitive) hash of name
16854b22b933Srs200217     CacheRecord    *members;            // List of CacheRecords with this same name
16864b22b933Srs200217     CacheRecord   **rrcache_tail;       // Tail end of that list
16874b22b933Srs200217     domainname     *name;               // Common name for all CacheRecords in this list
1688*5ffb0c9bSToomas Soome     mDNSu8 namestorage[sizeof(CacheRecord) - sizeof(struct CacheGroup_base)];  // match sizeof(CacheRecord)
16894b22b933Srs200217 };
16904b22b933Srs200217 
16914b22b933Srs200217 // Storage sufficient to hold either a CacheGroup header or a CacheRecord
1692*5ffb0c9bSToomas Soome // -- for best efficiency (to avoid wasted unused storage) they should be the same size
16934b22b933Srs200217 typedef union CacheEntity_union CacheEntity;
16944b22b933Srs200217 union CacheEntity_union { CacheEntity *next; CacheGroup cg; CacheRecord cr; };
16954b22b933Srs200217 
16964b22b933Srs200217 typedef struct
16974b22b933Srs200217 {
16984b22b933Srs200217     CacheRecord r;
16994b22b933Srs200217     mDNSu8 _extradata[MaximumRDSize-InlineCacheRDSize];     // Glue on the necessary number of extra bytes
17004b22b933Srs200217     domainname namestorage;                                 // Needs to go *after* the extra rdata bytes
17014b22b933Srs200217 } LargeCacheRecord;
17024b22b933Srs200217 
1703*5ffb0c9bSToomas Soome typedef struct HostnameInfo
17044b22b933Srs200217 {
1705*5ffb0c9bSToomas Soome     struct HostnameInfo *next;
1706*5ffb0c9bSToomas Soome     NATTraversalInfo natinfo;
17074b22b933Srs200217     domainname fqdn;
1708*5ffb0c9bSToomas Soome     AuthRecord arv4;                          // registered IPv4 address record
1709*5ffb0c9bSToomas Soome     AuthRecord arv6;                          // registered IPv6 address record
17104b22b933Srs200217     mDNSRecordCallback *StatusCallback;       // callback to deliver success or error code to client layer
17114b22b933Srs200217     const void *StatusContext;                // Client Context
1712*5ffb0c9bSToomas Soome } HostnameInfo;
17134b22b933Srs200217 
17144b22b933Srs200217 typedef struct ExtraResourceRecord_struct ExtraResourceRecord;
17154b22b933Srs200217 struct ExtraResourceRecord_struct
17164b22b933Srs200217 {
17174b22b933Srs200217     ExtraResourceRecord *next;
17184b22b933Srs200217     mDNSu32 ClientID;  // Opaque ID field to be used by client to map an AddRecord call to a set of Extra records
17194b22b933Srs200217     AuthRecord r;
17204b22b933Srs200217     // Note: Add any additional fields *before* the AuthRecord in this structure, not at the end.
17214b22b933Srs200217     // In some cases clients can allocate larger chunks of memory and set r->rdata->MaxRDLength to indicate
17224b22b933Srs200217     // that this extra memory is available, which would result in any fields after the AuthRecord getting smashed
17234b22b933Srs200217 };
17244b22b933Srs200217 
1725*5ffb0c9bSToomas Soome // Note: Within an mDNSServiceCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
17264b22b933Srs200217 typedef void mDNSServiceCallback (mDNS *const m, ServiceRecordSet *const sr, mStatus result);
1727*5ffb0c9bSToomas Soome 
1728*5ffb0c9bSToomas Soome // A ServiceRecordSet has no special meaning to the core code of the Multicast DNS protocol engine;
1729*5ffb0c9bSToomas Soome // it is just a convenience structure to group together the records that make up a standard service
1730*5ffb0c9bSToomas Soome // registration so that they can be allocted and deallocted together as a single memory object.
1731*5ffb0c9bSToomas Soome // It contains its own ServiceCallback+ServiceContext to report aggregate results up to the next layer of software above.
1732*5ffb0c9bSToomas Soome // It also contains:
1733*5ffb0c9bSToomas Soome //  * the basic PTR/SRV/TXT triplet used to represent any DNS-SD service
1734*5ffb0c9bSToomas Soome //  * the "_services" PTR record for service enumeration
1735*5ffb0c9bSToomas Soome //  * the optional list of SubType PTR records
1736*5ffb0c9bSToomas Soome //  * the optional list of additional records attached to the service set (e.g. iChat pictures)
1737*5ffb0c9bSToomas Soome 
17384b22b933Srs200217 struct ServiceRecordSet_struct
17394b22b933Srs200217 {
1740*5ffb0c9bSToomas Soome     // These internal state fields are used internally by mDNSCore; the client layer needn't be concerned with them.
17414b22b933Srs200217     // No fields need to be set up by the client prior to calling mDNS_RegisterService();
17424b22b933Srs200217     // all required data is passed as parameters to that function.
17434b22b933Srs200217     mDNSServiceCallback *ServiceCallback;
17444b22b933Srs200217     void                *ServiceContext;
1745*5ffb0c9bSToomas Soome     mDNSBool Conflict;              // Set if this record set was forcibly deregistered because of a conflict
1746*5ffb0c9bSToomas Soome 
17474b22b933Srs200217     ExtraResourceRecord *Extras;    // Optional list of extra AuthRecords attached to this service registration
17484b22b933Srs200217     mDNSu32 NumSubTypes;
17494b22b933Srs200217     AuthRecord          *SubTypes;
1750*5ffb0c9bSToomas Soome     const mDNSu8        *AnonData;
1751*5ffb0c9bSToomas Soome     mDNSu32             flags;      // saved for subsequent calls to mDNS_RegisterService() if records
1752*5ffb0c9bSToomas Soome                                     // need to be re-registered.
17534b22b933Srs200217     AuthRecord RR_ADV;              // e.g. _services._dns-sd._udp.local. PTR _printer._tcp.local.
17544b22b933Srs200217     AuthRecord RR_PTR;              // e.g. _printer._tcp.local.        PTR Name._printer._tcp.local.
17554b22b933Srs200217     AuthRecord RR_SRV;              // e.g. Name._printer._tcp.local.   SRV 0 0 port target
17564b22b933Srs200217     AuthRecord RR_TXT;              // e.g. Name._printer._tcp.local.   TXT PrintQueueName
17574b22b933Srs200217     // Don't add any fields after AuthRecord RR_TXT.
17584b22b933Srs200217     // This is where the implicit extra space goes if we allocate a ServiceRecordSet containing an oversized RR_TXT record
17594b22b933Srs200217 };
17604b22b933Srs200217 
17614b22b933Srs200217 // ***************************************************************************
17624b22b933Srs200217 #if 0
1763*5ffb0c9bSToomas Soome #pragma mark -
17644b22b933Srs200217 #pragma mark - Question structures
17654b22b933Srs200217 #endif
17664b22b933Srs200217 
17674b22b933Srs200217 // We record the last eight instances of each duplicate query
1768*5ffb0c9bSToomas Soome // This gives us v4/v6 on each of Ethernet, AirPort and Firewire, and two free slots "for future expansion"
17694b22b933Srs200217 // If the host has more active interfaces that this it is not fatal -- duplicate question suppression will degrade gracefully.
17704b22b933Srs200217 // Since we will still remember the last eight, the busiest interfaces will still get the effective duplicate question suppression.
17714b22b933Srs200217 #define DupSuppressInfoSize 8
17724b22b933Srs200217 
17734b22b933Srs200217 typedef struct
17744b22b933Srs200217 {
17754b22b933Srs200217     mDNSs32 Time;
17764b22b933Srs200217     mDNSInterfaceID InterfaceID;
17774b22b933Srs200217     mDNSs32 Type;                           // v4 or v6?
17784b22b933Srs200217 } DupSuppressInfo;
17794b22b933Srs200217 
17804b22b933Srs200217 typedef enum
17814b22b933Srs200217 {
1782*5ffb0c9bSToomas Soome     LLQ_InitialRequest    = 1,
1783*5ffb0c9bSToomas Soome     LLQ_SecondaryRequest  = 2,
1784*5ffb0c9bSToomas Soome     LLQ_Established       = 3,
1785*5ffb0c9bSToomas Soome     LLQ_Poll              = 4
17864b22b933Srs200217 } LLQ_State;
17874b22b933Srs200217 
17884b22b933Srs200217 // LLQ constants
17894b22b933Srs200217 #define kLLQ_Vers      1
17904b22b933Srs200217 #define kLLQ_DefLease  7200 // 2 hours
17914b22b933Srs200217 #define kLLQ_MAX_TRIES 3    // retry an operation 3 times max
17924b22b933Srs200217 #define kLLQ_INIT_RESEND 2 // resend an un-ack'd packet after 2 seconds, then double for each additional
17934b22b933Srs200217 // LLQ Operation Codes
17944b22b933Srs200217 #define kLLQOp_Setup     1
17954b22b933Srs200217 #define kLLQOp_Refresh   2
17964b22b933Srs200217 #define kLLQOp_Event     3
17974b22b933Srs200217 
17984b22b933Srs200217 // LLQ Errror Codes
17994b22b933Srs200217 enum
18004b22b933Srs200217 {
18014b22b933Srs200217     LLQErr_NoError    = 0,
18024b22b933Srs200217     LLQErr_ServFull   = 1,
18034b22b933Srs200217     LLQErr_Static     = 2,
18044b22b933Srs200217     LLQErr_FormErr    = 3,
18054b22b933Srs200217     LLQErr_NoSuchLLQ  = 4,
18064b22b933Srs200217     LLQErr_BadVers    = 5,
18074b22b933Srs200217     LLQErr_UnknownErr = 6
18084b22b933Srs200217 };
18094b22b933Srs200217 
1810*5ffb0c9bSToomas Soome enum { NoAnswer_Normal = 0, NoAnswer_Suspended = 1, NoAnswer_Fail = 2 };
18114b22b933Srs200217 
1812*5ffb0c9bSToomas Soome #define HMAC_LEN    64
1813*5ffb0c9bSToomas Soome #define HMAC_IPAD   0x36
1814*5ffb0c9bSToomas Soome #define HMAC_OPAD   0x5c
1815*5ffb0c9bSToomas Soome #define MD5_LEN     16
1816*5ffb0c9bSToomas Soome 
1817*5ffb0c9bSToomas Soome #define AutoTunnelUnregistered(X) (                                               \
1818*5ffb0c9bSToomas Soome         (X)->AutoTunnelHostRecord.resrec.RecordType == kDNSRecordTypeUnregistered && \
1819*5ffb0c9bSToomas Soome         (X)->AutoTunnelTarget.resrec.RecordType == kDNSRecordTypeUnregistered && \
1820*5ffb0c9bSToomas Soome         (X)->AutoTunnelDeviceInfo.resrec.RecordType == kDNSRecordTypeUnregistered && \
1821*5ffb0c9bSToomas Soome         (X)->AutoTunnelService.resrec.RecordType == kDNSRecordTypeUnregistered && \
1822*5ffb0c9bSToomas Soome         (X)->AutoTunnel6Record.resrec.RecordType == kDNSRecordTypeUnregistered )
1823*5ffb0c9bSToomas Soome 
1824*5ffb0c9bSToomas Soome // Internal data structure to maintain authentication information
1825*5ffb0c9bSToomas Soome typedef struct DomainAuthInfo
1826*5ffb0c9bSToomas Soome {
1827*5ffb0c9bSToomas Soome     struct DomainAuthInfo *next;
1828*5ffb0c9bSToomas Soome     mDNSs32 deltime;                        // If we're planning to delete this DomainAuthInfo, the time we want it deleted
1829*5ffb0c9bSToomas Soome     mDNSBool   AutoTunnel;                  // Whether this is AutoTunnel
1830*5ffb0c9bSToomas Soome     AuthRecord AutoTunnelHostRecord;        // User-visible hostname; used as SRV target for AutoTunnel services
1831*5ffb0c9bSToomas Soome     AuthRecord AutoTunnelTarget;            // Opaque hostname of tunnel endpoint; used as SRV target for AutoTunnelService record
1832*5ffb0c9bSToomas Soome     AuthRecord AutoTunnelDeviceInfo;        // Device info of tunnel endpoint
1833*5ffb0c9bSToomas Soome     AuthRecord AutoTunnelService;           // Service record (possibly NAT-Mapped) of IKE daemon implementing tunnel endpoint
1834*5ffb0c9bSToomas Soome     AuthRecord AutoTunnel6Record;           // AutoTunnel AAAA Record obtained from awacsd
1835*5ffb0c9bSToomas Soome     mDNSBool AutoTunnelServiceStarted;         // Whether a service has been registered in this domain
1836*5ffb0c9bSToomas Soome     mDNSv6Addr AutoTunnelInnerAddress;
1837*5ffb0c9bSToomas Soome     domainname domain;
1838*5ffb0c9bSToomas Soome     domainname keyname;
1839*5ffb0c9bSToomas Soome     domainname hostname;
1840*5ffb0c9bSToomas Soome     mDNSIPPort port;
1841*5ffb0c9bSToomas Soome     char b64keydata[32];
1842*5ffb0c9bSToomas Soome     mDNSu8 keydata_ipad[HMAC_LEN];              // padded key for inner hash rounds
1843*5ffb0c9bSToomas Soome     mDNSu8 keydata_opad[HMAC_LEN];              // padded key for outer hash rounds
1844*5ffb0c9bSToomas Soome } DomainAuthInfo;
1845*5ffb0c9bSToomas Soome 
1846*5ffb0c9bSToomas Soome // Note: Within an mDNSQuestionCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
1847*5ffb0c9bSToomas Soome // Note: Any value other than QC_rmv i.e., any non-zero value will result in kDNSServiceFlagsAdd to the application
1848*5ffb0c9bSToomas Soome // layer. These values are used within mDNSResponder and not sent across to the application. QC_addnocache is for
1849*5ffb0c9bSToomas Soome // delivering a response without adding to the cache. QC_forceresponse is superset of QC_addnocache where in
1850*5ffb0c9bSToomas Soome // addition to not entering in the cache, it also forces the negative response through.
1851*5ffb0c9bSToomas Soome typedef enum { QC_rmv = 0, QC_add, QC_addnocache, QC_forceresponse, QC_dnssec , QC_nodnssec, QC_suppressed } QC_result;
1852*5ffb0c9bSToomas Soome typedef void mDNSQuestionCallback (mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord);
1853*5ffb0c9bSToomas Soome typedef void AsyncDispatchFunc(mDNS *const m, void *context);
1854*5ffb0c9bSToomas Soome typedef void DNSSECAuthInfoFreeCallback(mDNS *const m, void *context);
1855*5ffb0c9bSToomas Soome extern void mDNSPlatformDispatchAsync(mDNS *const m, void *context, AsyncDispatchFunc func);
1856*5ffb0c9bSToomas Soome 
1857*5ffb0c9bSToomas Soome #define NextQSendTime(Q)  ((Q)->LastQTime + (Q)->ThisQInterval)
1858*5ffb0c9bSToomas Soome #define ActiveQuestion(Q) ((Q)->ThisQInterval > 0 && !(Q)->DuplicateOf)
1859*5ffb0c9bSToomas Soome #define TimeToSendThisQuestion(Q,time) (ActiveQuestion(Q) && (time) - NextQSendTime(Q) >= 0)
1860*5ffb0c9bSToomas Soome 
1861*5ffb0c9bSToomas Soome // q->ValidationStatus is either DNSSECValNotRequired or DNSSECValRequired and then moves onto DNSSECValInProgress.
1862*5ffb0c9bSToomas Soome // When Validation is done, we mark all "DNSSECValInProgress" questions "DNSSECValDone". If we are answering
1863*5ffb0c9bSToomas Soome // questions from /etc/hosts, then we go straight to DNSSECValDone from the initial state.
1864*5ffb0c9bSToomas Soome typedef enum { DNSSECValNotRequired = 0, DNSSECValRequired, DNSSECValInProgress, DNSSECValDone } DNSSECValState;
1865*5ffb0c9bSToomas Soome 
1866*5ffb0c9bSToomas Soome // ValidationRequired can be set to the following values:
1867*5ffb0c9bSToomas Soome //
1868*5ffb0c9bSToomas Soome // SECURE validation is set to determine whether something is secure or bogus
1869*5ffb0c9bSToomas Soome // INSECURE validation is set internally by dnssec code to indicate that it is currently proving something
1870*5ffb0c9bSToomas Soome // is insecure
1871*5ffb0c9bSToomas Soome #define DNSSEC_VALIDATION_NONE              0x00
1872*5ffb0c9bSToomas Soome #define DNSSEC_VALIDATION_SECURE            0x01
1873*5ffb0c9bSToomas Soome #define DNSSEC_VALIDATION_SECURE_OPTIONAL   0x02
1874*5ffb0c9bSToomas Soome #define DNSSEC_VALIDATION_INSECURE          0x03
1875*5ffb0c9bSToomas Soome 
1876*5ffb0c9bSToomas Soome // For both ValidationRequired and ValidatingResponse question, we validate DNSSEC responses.
1877*5ffb0c9bSToomas Soome // For ProxyQuestion with DNSSECOK, we just receive the DNSSEC records to pass them along without
1878*5ffb0c9bSToomas Soome // validation and if the CD bit is not set, we also validate.
1879*5ffb0c9bSToomas Soome #define DNSSECQuestion(q) ((q)->ValidationRequired || (q)->ValidatingResponse || ((q)->ProxyQuestion && (q)->ProxyDNSSECOK))
1880*5ffb0c9bSToomas Soome 
1881*5ffb0c9bSToomas Soome // ValidatingQuestion is used when we need to know whether we are validating the DNSSEC responses for a question
1882*5ffb0c9bSToomas Soome #define ValidatingQuestion(q) ((q)->ValidationRequired || (q)->ValidatingResponse)
1883*5ffb0c9bSToomas Soome 
1884*5ffb0c9bSToomas Soome #define DNSSECOptionalQuestion(q) ((q)->ValidationRequired == DNSSEC_VALIDATION_SECURE_OPTIONAL)
1885*5ffb0c9bSToomas Soome 
1886*5ffb0c9bSToomas Soome // Given the resource record and the question, should we follow the CNAME ?
1887*5ffb0c9bSToomas Soome #define FollowCNAME(q, rr, AddRecord)   (AddRecord && (q)->qtype != kDNSType_CNAME && \
1888*5ffb0c9bSToomas Soome                                          (rr)->RecordType != kDNSRecordTypePacketNegative && \
1889*5ffb0c9bSToomas Soome                                          (rr)->rrtype == kDNSType_CNAME)
1890*5ffb0c9bSToomas Soome 
1891*5ffb0c9bSToomas Soome // RFC 4122 defines it to be 16 bytes
1892*5ffb0c9bSToomas Soome #define UUID_SIZE       16
1893*5ffb0c9bSToomas Soome 
18944b22b933Srs200217 struct DNSQuestion_struct
18954b22b933Srs200217 {
18964b22b933Srs200217     // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
18974b22b933Srs200217     DNSQuestion          *next;
18984b22b933Srs200217     mDNSu32 qnamehash;
18994b22b933Srs200217     mDNSs32 DelayAnswering;                 // Set if we want to defer answering this question until the cache settles
19004b22b933Srs200217     mDNSs32 LastQTime;                      // Last scheduled transmission of this Q on *all* applicable interfaces
19014b22b933Srs200217     mDNSs32 ThisQInterval;                  // LastQTime + ThisQInterval is the next scheduled transmission of this Q
19024b22b933Srs200217                                             // ThisQInterval > 0 for an active question;
19034b22b933Srs200217                                             // ThisQInterval = 0 for a suspended question that's still in the list
1904*5ffb0c9bSToomas Soome                                             // ThisQInterval = -1 for a cancelled question (should not still be in list)
1905*5ffb0c9bSToomas Soome     mDNSs32 ExpectUnicastResp;              // Set when we send a query with the kDNSQClass_UnicastResponse bit set
19064b22b933Srs200217     mDNSs32 LastAnswerPktNum;               // The sequence number of the last response packet containing an answer to this Q
19074b22b933Srs200217     mDNSu32 RecentAnswerPkts;               // Number of answers since the last time we sent this query
19084b22b933Srs200217     mDNSu32 CurrentAnswers;                 // Number of records currently in the cache that answer this question
1909*5ffb0c9bSToomas Soome     mDNSu32 BrowseThreshold;                // If we have received at least this number of answers,
1910*5ffb0c9bSToomas Soome                                             // set the next question interval to MaxQuestionInterval
19114b22b933Srs200217     mDNSu32 LargeAnswers;                   // Number of answers with rdata > 1024 bytes
19124b22b933Srs200217     mDNSu32 UniqueAnswers;                  // Number of answers received with kDNSClass_UniqueRRSet bit set
1913*5ffb0c9bSToomas Soome     mDNSInterfaceID FlappingInterface1;     // Set when an interface goes away, to flag if remove events are delivered for this Q
1914*5ffb0c9bSToomas Soome     mDNSInterfaceID FlappingInterface2;     // Set when an interface goes away, to flag if remove events are delivered for this Q
1915*5ffb0c9bSToomas Soome     DomainAuthInfo       *AuthInfo;         // Non-NULL if query is currently being done using Private DNS
19164b22b933Srs200217     DNSQuestion          *DuplicateOf;
19174b22b933Srs200217     DNSQuestion          *NextInDQList;
1918*5ffb0c9bSToomas Soome     AnonymousInfo        *AnonInfo;         // Anonymous Information
19194b22b933Srs200217     DupSuppressInfo DupSuppress[DupSuppressInfoSize];
19204b22b933Srs200217     mDNSInterfaceID SendQNow;               // The interface this query is being sent on right now
19214b22b933Srs200217     mDNSBool SendOnAll;                     // Set if we're sending this question on all active interfaces
1922*5ffb0c9bSToomas Soome     mDNSBool CachedAnswerNeedsUpdate;       // See SendQueries().  Set if we're sending this question
1923*5ffb0c9bSToomas Soome                                             // because a cached answer needs to be refreshed.
19244b22b933Srs200217     mDNSu32 RequestUnicast;                 // Non-zero if we want to send query with kDNSQClass_UnicastResponse bit set
19254b22b933Srs200217     mDNSs32 LastQTxTime;                    // Last time this Q was sent on one (but not necessarily all) interfaces
1926*5ffb0c9bSToomas Soome     mDNSu32 CNAMEReferrals;                 // Count of how many CNAME redirections we've done
1927*5ffb0c9bSToomas Soome     mDNSBool SuppressQuery;                 // This query should be suppressed and not sent on the wire
1928*5ffb0c9bSToomas Soome     mDNSu8 LOAddressAnswers;                // Number of answers from the local only auth records that are
1929*5ffb0c9bSToomas Soome                                             // answering A, AAAA, CNAME, or PTR (/etc/hosts)
1930*5ffb0c9bSToomas Soome     mDNSu8 WakeOnResolveCount;              // Number of wakes that should be sent on resolve
1931*5ffb0c9bSToomas Soome     mDNSs32 StopTime;                       // Time this question should be stopped by giving them a negative answer
1932*5ffb0c9bSToomas Soome 
1933*5ffb0c9bSToomas Soome     // DNSSEC fields
1934*5ffb0c9bSToomas Soome     DNSSECValState ValidationState;            // Current state of the Validation process
1935*5ffb0c9bSToomas Soome     DNSSECStatus ValidationStatus;             // Validation status for "ValidationRequired" questions (dnssec)
1936*5ffb0c9bSToomas Soome     mDNSu8 ValidatingResponse;                 // Question trying to validate a response (dnssec) on behalf of
1937*5ffb0c9bSToomas Soome                                                // ValidationRequired question
1938*5ffb0c9bSToomas Soome     void *DNSSECAuthInfo;
1939*5ffb0c9bSToomas Soome     DNSSECAuthInfoFreeCallback *DAIFreeCallback;
1940*5ffb0c9bSToomas Soome 
1941*5ffb0c9bSToomas Soome     // Wide Area fields. These are used internally by the uDNS core (Unicast)
1942*5ffb0c9bSToomas Soome     UDPSocket            *LocalSocket;
1943*5ffb0c9bSToomas Soome 
1944*5ffb0c9bSToomas Soome     // |-> DNS Configuration related fields used in uDNS (Subset of Wide Area/Unicast fields)
1945*5ffb0c9bSToomas Soome     DNSServer            *qDNSServer;       // Caching server for this query (in the absence of an SRV saying otherwise)
1946*5ffb0c9bSToomas Soome     mDNSOpaque64 validDNSServers;           // Valid DNSServers for this question
1947*5ffb0c9bSToomas Soome     mDNSu16 noServerResponse;               // At least one server did not respond.
1948*5ffb0c9bSToomas Soome     mDNSu16 triedAllServersOnce;            // Tried all DNS servers once
1949*5ffb0c9bSToomas Soome     mDNSu8 unansweredQueries;               // The number of unanswered queries to this server
1950*5ffb0c9bSToomas Soome 
1951*5ffb0c9bSToomas Soome     ZoneData             *nta;              // Used for getting zone data for private or LLQ query
1952*5ffb0c9bSToomas Soome     mDNSAddr servAddr;                      // Address and port learned from _dns-llq, _dns-llq-tls or _dns-query-tls SRV query
1953*5ffb0c9bSToomas Soome     mDNSIPPort servPort;
1954*5ffb0c9bSToomas Soome     struct tcpInfo_t *tcp;
1955*5ffb0c9bSToomas Soome     mDNSIPPort tcpSrcPort;                  // Local Port TCP packet received on;need this as tcp struct is disposed
1956*5ffb0c9bSToomas Soome                                             // by tcpCallback before calling into mDNSCoreReceive
1957*5ffb0c9bSToomas Soome     mDNSu8 NoAnswer;                        // Set if we want to suppress answers until tunnel setup has completed
1958*5ffb0c9bSToomas Soome     mDNSu8 Restart;                         // This question should be restarted soon
1959*5ffb0c9bSToomas Soome 
1960*5ffb0c9bSToomas Soome     // LLQ-specific fields. These fields are only meaningful when LongLived flag is set
1961*5ffb0c9bSToomas Soome     LLQ_State state;
1962*5ffb0c9bSToomas Soome     mDNSu32 ReqLease;                       // seconds (relative)
1963*5ffb0c9bSToomas Soome     mDNSs32 expire;                         // ticks (absolute)
1964*5ffb0c9bSToomas Soome     mDNSs16 ntries;                         // for UDP: the number of packets sent for this LLQ state
1965*5ffb0c9bSToomas Soome                                             // for TCP: there is some ambiguity in the use of this variable, but in general, it is
1966*5ffb0c9bSToomas Soome                                             //          the number of TCP/TLS connection attempts for this LLQ state, or
1967*5ffb0c9bSToomas Soome                                             //          the number of packets sent for this TCP/TLS connection
1968*5ffb0c9bSToomas Soome     mDNSOpaque64 id;
1969*5ffb0c9bSToomas Soome 
1970*5ffb0c9bSToomas Soome     // DNS Proxy fields
1971*5ffb0c9bSToomas Soome     mDNSOpaque16 responseFlags;             // Temporary place holder for the error we get back from the DNS server
1972*5ffb0c9bSToomas Soome                                             // till we populate in the cache
1973*5ffb0c9bSToomas Soome     mDNSBool     DisallowPID;               // Is the query allowed for the "PID" that we are sending on behalf of ?
1974*5ffb0c9bSToomas Soome     mDNSs32      ServiceID;                 // Service identifier to match against the DNS server
19754b22b933Srs200217 
19764b22b933Srs200217     // Client API fields: The client must set up these fields *before* calling mDNS_StartQuery()
19774b22b933Srs200217     mDNSInterfaceID InterfaceID;            // Non-zero if you want to issue queries only on a single specific IP interface
1978*5ffb0c9bSToomas Soome     mDNSu32  flags;                         // flags from original DNSService*() API request.
19794b22b933Srs200217     mDNSAddr Target;                        // Non-zero if you want to direct queries to a specific unicast target address
19804b22b933Srs200217     mDNSIPPort TargetPort;                  // Must be set if Target is set
19814b22b933Srs200217     mDNSOpaque16 TargetQID;                 // Must be set if Target is set
19824b22b933Srs200217     domainname qname;
19834b22b933Srs200217     mDNSu16 qtype;
19844b22b933Srs200217     mDNSu16 qclass;
19854b22b933Srs200217     mDNSBool LongLived;                     // Set by client for calls to mDNS_StartQuery to indicate LLQs to unicast layer.
19864b22b933Srs200217     mDNSBool ExpectUnique;                  // Set by client if it's expecting unique RR(s) for this question, not shared RRs
19874b22b933Srs200217     mDNSBool ForceMCast;                    // Set by client to force mDNS query, even for apparently uDNS names
1988*5ffb0c9bSToomas Soome     mDNSBool ReturnIntermed;                // Set by client to request callbacks for intermediate CNAME/NXDOMAIN results
1989*5ffb0c9bSToomas Soome     mDNSBool SuppressUnusable;              // Set by client to suppress unusable queries to be sent on the wire
1990*5ffb0c9bSToomas Soome     mDNSBool DenyOnCellInterface;           // Set by client to suppress uDNS queries on cellular interface
1991*5ffb0c9bSToomas Soome     mDNSBool DenyOnExpInterface;            // Set by client to suppress uDNS queries on expensive interface
1992*5ffb0c9bSToomas Soome     mDNSu8 RetryWithSearchDomains;          // Retry with search domains if there is no entry in the cache or AuthRecords
1993*5ffb0c9bSToomas Soome     mDNSu8 TimeoutQuestion;                 // Timeout this question if there is no reply in configured time
1994*5ffb0c9bSToomas Soome     mDNSu8 WakeOnResolve;                   // Send wakeup on resolve
1995*5ffb0c9bSToomas Soome     mDNSu8 UseBackgroundTrafficClass;       // Set by client to use background traffic class for request
1996*5ffb0c9bSToomas Soome     mDNSs8 SearchListIndex;                 // Index into SearchList; Used by the client layer but not touched by core
1997*5ffb0c9bSToomas Soome     mDNSs8 AppendSearchDomains;             // Search domains can be appended for this query
1998*5ffb0c9bSToomas Soome     mDNSs8 AppendLocalSearchDomains;        // Search domains ending in .local can be appended for this query
1999*5ffb0c9bSToomas Soome     mDNSu8 ValidationRequired;              // Requires DNSSEC validation.
2000*5ffb0c9bSToomas Soome     mDNSu8 ProxyQuestion;                   // Proxy Question
2001*5ffb0c9bSToomas Soome     mDNSu8 ProxyDNSSECOK;                   // Proxy Question with EDNS0 DNSSEC OK bit set
2002*5ffb0c9bSToomas Soome     mDNSs32 pid;                            // Process ID of the client that is requesting the question
2003*5ffb0c9bSToomas Soome     mDNSu8  uuid[UUID_SIZE];                // Unique ID of the client that is requesting the question (valid only if pid is zero)
2004*5ffb0c9bSToomas Soome     domainname           *qnameOrig;        // Copy of the original question name if it is not fully qualified
20054b22b933Srs200217     mDNSQuestionCallback *QuestionCallback;
20064b22b933Srs200217     void                 *QuestionContext;
20074b22b933Srs200217 };
20084b22b933Srs200217 
20094b22b933Srs200217 typedef struct
20104b22b933Srs200217 {
20114b22b933Srs200217     // Client API fields: The client must set up name and InterfaceID *before* calling mDNS_StartResolveService()
20124b22b933Srs200217     // When the callback is invoked, ip, port, TXTlen and TXTinfo will have been filled in with the results learned from the network.
20134b22b933Srs200217     domainname name;
20144b22b933Srs200217     mDNSInterfaceID InterfaceID;        // ID of the interface the response was received on
20154b22b933Srs200217     mDNSAddr ip;                        // Remote (destination) IP address where this service can be accessed
20164b22b933Srs200217     mDNSIPPort port;                    // Port where this service can be accessed
20174b22b933Srs200217     mDNSu16 TXTlen;
20184b22b933Srs200217     mDNSu8 TXTinfo[2048];               // Additional demultiplexing information (e.g. LPR queue name)
20194b22b933Srs200217 } ServiceInfo;
20204b22b933Srs200217 
2021*5ffb0c9bSToomas Soome // Note: Within an mDNSServiceInfoQueryCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
20224b22b933Srs200217 typedef struct ServiceInfoQuery_struct ServiceInfoQuery;
20234b22b933Srs200217 typedef void mDNSServiceInfoQueryCallback (mDNS *const m, ServiceInfoQuery *query);
20244b22b933Srs200217 struct ServiceInfoQuery_struct
20254b22b933Srs200217 {
20264b22b933Srs200217     // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
20274b22b933Srs200217     // No fields need to be set up by the client prior to calling mDNS_StartResolveService();
20284b22b933Srs200217     // all required data is passed as parameters to that function.
20294b22b933Srs200217     // The ServiceInfoQuery structure memory is working storage for mDNSCore to discover the requested information
20304b22b933Srs200217     // and place it in the ServiceInfo structure. After the client has called mDNS_StopResolveService(), it may
20314b22b933Srs200217     // dispose of the ServiceInfoQuery structure while retaining the results in the ServiceInfo structure.
20324b22b933Srs200217     DNSQuestion qSRV;
20334b22b933Srs200217     DNSQuestion qTXT;
20344b22b933Srs200217     DNSQuestion qAv4;
20354b22b933Srs200217     DNSQuestion qAv6;
20364b22b933Srs200217     mDNSu8 GotSRV;
20374b22b933Srs200217     mDNSu8 GotTXT;
20384b22b933Srs200217     mDNSu8 GotADD;
20394b22b933Srs200217     mDNSu32 Answers;
20404b22b933Srs200217     ServiceInfo                  *info;
20414b22b933Srs200217     mDNSServiceInfoQueryCallback *ServiceInfoQueryCallback;
20424b22b933Srs200217     void                         *ServiceInfoQueryContext;
20434b22b933Srs200217 };
20444b22b933Srs200217 
2045*5ffb0c9bSToomas Soome typedef enum { ZoneServiceUpdate, ZoneServiceQuery, ZoneServiceLLQ } ZoneService;
2046*5ffb0c9bSToomas Soome 
2047*5ffb0c9bSToomas Soome typedef void ZoneDataCallback (mDNS *const m, mStatus err, const ZoneData *result);
2048*5ffb0c9bSToomas Soome 
2049*5ffb0c9bSToomas Soome struct ZoneData_struct
2050*5ffb0c9bSToomas Soome {
2051*5ffb0c9bSToomas Soome     domainname ChildName;               // Name for which we're trying to find the responsible server
2052*5ffb0c9bSToomas Soome     ZoneService ZoneService;            // Which service we're seeking for this zone (update, query, or LLQ)
2053*5ffb0c9bSToomas Soome     domainname       *CurrentSOA;       // Points to somewhere within ChildName
2054*5ffb0c9bSToomas Soome     domainname ZoneName;                // Discovered result: Left-hand-side of SOA record
2055*5ffb0c9bSToomas Soome     mDNSu16 ZoneClass;                  // Discovered result: DNS Class from SOA record
2056*5ffb0c9bSToomas Soome     domainname Host;                    // Discovered result: Target host from SRV record
2057*5ffb0c9bSToomas Soome     mDNSIPPort Port;                    // Discovered result: Update port, query port, or LLQ port from SRV record
2058*5ffb0c9bSToomas Soome     mDNSAddr Addr;                      // Discovered result: Address of Target host from SRV record
2059*5ffb0c9bSToomas Soome     mDNSBool ZonePrivate;               // Discovered result: Does zone require encrypted queries?
2060*5ffb0c9bSToomas Soome     ZoneDataCallback *ZoneDataCallback; // Caller-specified function to be called upon completion
2061*5ffb0c9bSToomas Soome     void             *ZoneDataContext;
2062*5ffb0c9bSToomas Soome     DNSQuestion question;               // Storage for any active question
2063*5ffb0c9bSToomas Soome };
2064*5ffb0c9bSToomas Soome 
2065*5ffb0c9bSToomas Soome extern ZoneData *StartGetZoneData(mDNS *const m, const domainname *const name, const ZoneService target, ZoneDataCallback callback, void *callbackInfo);
2066*5ffb0c9bSToomas Soome extern void CancelGetZoneData(mDNS *const m, ZoneData *nta);
2067*5ffb0c9bSToomas Soome extern mDNSBool IsGetZoneDataQuestion(DNSQuestion *q);
2068*5ffb0c9bSToomas Soome 
2069*5ffb0c9bSToomas Soome typedef struct DNameListElem
2070*5ffb0c9bSToomas Soome {
2071*5ffb0c9bSToomas Soome     struct DNameListElem *next;
2072*5ffb0c9bSToomas Soome     mDNSu32 uid;
2073*5ffb0c9bSToomas Soome     domainname name;
2074*5ffb0c9bSToomas Soome } DNameListElem;
2075*5ffb0c9bSToomas Soome 
2076*5ffb0c9bSToomas Soome #if APPLE_OSX_mDNSResponder
2077*5ffb0c9bSToomas Soome // Different states that we go through locating the peer
2078*5ffb0c9bSToomas Soome #define TC_STATE_AAAA_PEER          0x000000001     /* Peer's BTMM IPv6 address */
2079*5ffb0c9bSToomas Soome #define TC_STATE_AAAA_PEER_RELAY    0x000000002     /* Peer's IPv6 Relay address */
2080*5ffb0c9bSToomas Soome #define TC_STATE_SRV_PEER           0x000000003     /* Peer's SRV Record corresponding to IPv4 address */
2081*5ffb0c9bSToomas Soome #define TC_STATE_ADDR_PEER          0x000000004     /* Peer's IPv4 address */
2082*5ffb0c9bSToomas Soome 
2083*5ffb0c9bSToomas Soome typedef struct ClientTunnel
2084*5ffb0c9bSToomas Soome {
2085*5ffb0c9bSToomas Soome     struct ClientTunnel *next;
2086*5ffb0c9bSToomas Soome     domainname dstname;
2087*5ffb0c9bSToomas Soome     mDNSBool MarkedForDeletion;
2088*5ffb0c9bSToomas Soome     mDNSv6Addr loc_inner;
2089*5ffb0c9bSToomas Soome     mDNSv4Addr loc_outer;
2090*5ffb0c9bSToomas Soome     mDNSv6Addr loc_outer6;
2091*5ffb0c9bSToomas Soome     mDNSv6Addr rmt_inner;
2092*5ffb0c9bSToomas Soome     mDNSv4Addr rmt_outer;
2093*5ffb0c9bSToomas Soome     mDNSv6Addr rmt_outer6;
2094*5ffb0c9bSToomas Soome     mDNSIPPort rmt_outer_port;
2095*5ffb0c9bSToomas Soome     mDNSu16 tc_state;
2096*5ffb0c9bSToomas Soome     DNSQuestion q;
2097*5ffb0c9bSToomas Soome } ClientTunnel;
20984b22b933Srs200217 #endif
20994b22b933Srs200217 
2100*5ffb0c9bSToomas Soome // ***************************************************************************
2101*5ffb0c9bSToomas Soome #if 0
2102*5ffb0c9bSToomas Soome #pragma mark -
2103*5ffb0c9bSToomas Soome #pragma mark - NetworkInterfaceInfo_struct
2104*5ffb0c9bSToomas Soome #endif
21054b22b933Srs200217 
2106*5ffb0c9bSToomas Soome typedef struct NetworkInterfaceInfo_struct NetworkInterfaceInfo;
21074b22b933Srs200217 
2108*5ffb0c9bSToomas Soome // A NetworkInterfaceInfo_struct serves two purposes:
2109*5ffb0c9bSToomas Soome // 1. It holds the address, PTR and HINFO records to advertise a given IP address on a given physical interface
2110*5ffb0c9bSToomas Soome // 2. It tells mDNSCore which physical interfaces are available; each physical interface has its own unique InterfaceID.
2111*5ffb0c9bSToomas Soome //    Since there may be multiple IP addresses on a single physical interface,
2112*5ffb0c9bSToomas Soome //    there may be multiple NetworkInterfaceInfo_structs with the same InterfaceID.
2113*5ffb0c9bSToomas Soome //    In this case, to avoid sending the same packet n times, when there's more than one
2114*5ffb0c9bSToomas Soome //    struct with the same InterfaceID, mDNSCore picks one member of the set to be the
2115*5ffb0c9bSToomas Soome //    active representative of the set; all others have the 'InterfaceActive' flag unset.
2116*5ffb0c9bSToomas Soome 
2117*5ffb0c9bSToomas Soome struct NetworkInterfaceInfo_struct
21184b22b933Srs200217 {
2119*5ffb0c9bSToomas Soome     // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
2120*5ffb0c9bSToomas Soome     NetworkInterfaceInfo *next;
2121*5ffb0c9bSToomas Soome 
2122*5ffb0c9bSToomas Soome     mDNSu8 InterfaceActive;             // Set if interface is sending & receiving packets (see comment above)
2123*5ffb0c9bSToomas Soome     mDNSu8 IPv4Available;               // If InterfaceActive, set if v4 available on this InterfaceID
2124*5ffb0c9bSToomas Soome     mDNSu8 IPv6Available;               // If InterfaceActive, set if v6 available on this InterfaceID
2125*5ffb0c9bSToomas Soome 
2126*5ffb0c9bSToomas Soome     DNSQuestion NetWakeBrowse;
2127*5ffb0c9bSToomas Soome     DNSQuestion NetWakeResolve[3];      // For fault-tolerance, we try up to three Sleep Proxies
2128*5ffb0c9bSToomas Soome     mDNSAddr SPSAddr[3];
2129*5ffb0c9bSToomas Soome     mDNSIPPort SPSPort[3];
2130*5ffb0c9bSToomas Soome     mDNSs32 NextSPSAttempt;             // -1 if we're not currently attempting to register with any Sleep Proxy
2131*5ffb0c9bSToomas Soome     mDNSs32 NextSPSAttemptTime;
2132*5ffb0c9bSToomas Soome 
2133*5ffb0c9bSToomas Soome     // Standard AuthRecords that every Responder host should have (one per active IP address)
2134*5ffb0c9bSToomas Soome     AuthRecord RR_A;                    // 'A' or 'AAAA' (address) record for our ".local" name
2135*5ffb0c9bSToomas Soome     AuthRecord RR_PTR;                  // PTR (reverse lookup) record
2136*5ffb0c9bSToomas Soome     AuthRecord RR_HINFO;
2137*5ffb0c9bSToomas Soome 
2138*5ffb0c9bSToomas Soome     // Client API fields: The client must set up these fields *before* calling mDNS_RegisterInterface()
2139*5ffb0c9bSToomas Soome     mDNSInterfaceID InterfaceID;        // Identifies physical interface; MUST NOT be 0, -1, or -2
2140*5ffb0c9bSToomas Soome     mDNSAddr ip;                        // The IPv4 or IPv6 address to advertise
2141*5ffb0c9bSToomas Soome     mDNSAddr mask;
2142*5ffb0c9bSToomas Soome     mDNSEthAddr MAC;
2143*5ffb0c9bSToomas Soome     char ifname[64];                    // Windows uses a GUID string for the interface name, which doesn't fit in 16 bytes
2144*5ffb0c9bSToomas Soome     mDNSu8 Advertise;                   // False if you are only searching on this interface
2145*5ffb0c9bSToomas Soome     mDNSu8 McastTxRx;                   // Send/Receive multicast on this { InterfaceID, address family } ?
2146*5ffb0c9bSToomas Soome     mDNSu8 NetWake;                     // Set if Wake-On-Magic-Packet is enabled on this interface
2147*5ffb0c9bSToomas Soome     mDNSu8 Loopback;                    // Set if this is the loopback interface
2148*5ffb0c9bSToomas Soome     mDNSu8 IgnoreIPv4LL;                // Set if IPv4 Link-Local addresses have to be ignored.
2149*5ffb0c9bSToomas Soome     mDNSu8 SendGoodbyes;                // Send goodbyes on this interface while sleeping
2150*5ffb0c9bSToomas Soome     mDNSBool DirectLink;                // a direct link, indicating we can skip the probe for
2151*5ffb0c9bSToomas Soome                                         // address records
21524b22b933Srs200217 };
21534b22b933Srs200217 
2154*5ffb0c9bSToomas Soome #define SLE_DELETE                      0x00000001
2155*5ffb0c9bSToomas Soome #define SLE_WAB_BROWSE_QUERY_STARTED    0x00000002
2156*5ffb0c9bSToomas Soome #define SLE_WAB_LBROWSE_QUERY_STARTED   0x00000004
2157*5ffb0c9bSToomas Soome #define SLE_WAB_REG_QUERY_STARTED       0x00000008
21584b22b933Srs200217 
2159*5ffb0c9bSToomas Soome typedef struct SearchListElem
21604b22b933Srs200217 {
2161*5ffb0c9bSToomas Soome     struct SearchListElem *next;
2162*5ffb0c9bSToomas Soome     domainname domain;
2163*5ffb0c9bSToomas Soome     int flag;
2164*5ffb0c9bSToomas Soome     mDNSInterfaceID InterfaceID;
2165*5ffb0c9bSToomas Soome     DNSQuestion BrowseQ;
2166*5ffb0c9bSToomas Soome     DNSQuestion DefBrowseQ;
2167*5ffb0c9bSToomas Soome     DNSQuestion AutomaticBrowseQ;
2168*5ffb0c9bSToomas Soome     DNSQuestion RegisterQ;
2169*5ffb0c9bSToomas Soome     DNSQuestion DefRegisterQ;
2170*5ffb0c9bSToomas Soome     int numCfAnswers;
2171*5ffb0c9bSToomas Soome     ARListElem *AuthRecs;
2172*5ffb0c9bSToomas Soome } SearchListElem;
21734b22b933Srs200217 
2174*5ffb0c9bSToomas Soome // For domain enumeration and automatic browsing
2175*5ffb0c9bSToomas Soome // This is the user's DNS search list.
2176*5ffb0c9bSToomas Soome // In each of these domains we search for our special pointer records (lb._dns-sd._udp.<domain>, etc.)
2177*5ffb0c9bSToomas Soome // to discover recommended domains for domain enumeration (browse, default browse, registration,
2178*5ffb0c9bSToomas Soome // default registration) and possibly one or more recommended automatic browsing domains.
2179*5ffb0c9bSToomas Soome extern SearchListElem *SearchList;      // This really ought to be part of mDNS_struct -- SC
21804b22b933Srs200217 
21814b22b933Srs200217 // ***************************************************************************
21824b22b933Srs200217 #if 0
2183*5ffb0c9bSToomas Soome #pragma mark -
21844b22b933Srs200217 #pragma mark - Main mDNS object, used to hold all the mDNS state
21854b22b933Srs200217 #endif
21864b22b933Srs200217 
21874b22b933Srs200217 typedef void mDNSCallback (mDNS *const m, mStatus result);
21884b22b933Srs200217 
2189*5ffb0c9bSToomas Soome #ifndef CACHE_HASH_SLOTS
21904b22b933Srs200217 #define CACHE_HASH_SLOTS 499
2191*5ffb0c9bSToomas Soome #endif
21924b22b933Srs200217 
21934b22b933Srs200217 enum
21944b22b933Srs200217 {
2195*5ffb0c9bSToomas Soome     SleepState_Awake = 0,
2196*5ffb0c9bSToomas Soome     SleepState_Transferring = 1,
2197*5ffb0c9bSToomas Soome     SleepState_Sleeping = 2
21984b22b933Srs200217 };
21994b22b933Srs200217 
2200*5ffb0c9bSToomas Soome typedef enum
2201*5ffb0c9bSToomas Soome {
2202*5ffb0c9bSToomas Soome     kStatsActionIncrement,
2203*5ffb0c9bSToomas Soome     kStatsActionDecrement,
2204*5ffb0c9bSToomas Soome     kStatsActionClear,
2205*5ffb0c9bSToomas Soome     kStatsActionSet
2206*5ffb0c9bSToomas Soome } DNSSECStatsAction;
2207*5ffb0c9bSToomas Soome 
2208*5ffb0c9bSToomas Soome typedef enum
2209*5ffb0c9bSToomas Soome {
2210*5ffb0c9bSToomas Soome     kStatsTypeMemoryUsage,
2211*5ffb0c9bSToomas Soome     kStatsTypeLatency,
2212*5ffb0c9bSToomas Soome     kStatsTypeExtraPackets,
2213*5ffb0c9bSToomas Soome     kStatsTypeStatus,
2214*5ffb0c9bSToomas Soome     kStatsTypeProbe,
2215*5ffb0c9bSToomas Soome     kStatsTypeMsgSize
2216*5ffb0c9bSToomas Soome } DNSSECStatsType;
2217*5ffb0c9bSToomas Soome 
22184b22b933Srs200217 typedef struct
22194b22b933Srs200217 {
2220*5ffb0c9bSToomas Soome     mDNSu32 TotalMemUsed;
2221*5ffb0c9bSToomas Soome     mDNSu32 Latency0;           // 0 to 4 ms
2222*5ffb0c9bSToomas Soome     mDNSu32 Latency5;           // 5 to  9 ms
2223*5ffb0c9bSToomas Soome     mDNSu32 Latency10;          // 10 to 19 ms
2224*5ffb0c9bSToomas Soome     mDNSu32 Latency20;          // 20 to 49 ms
2225*5ffb0c9bSToomas Soome     mDNSu32 Latency50;          // 50 to 99 ms
2226*5ffb0c9bSToomas Soome     mDNSu32 Latency100;         // >= 100 ms
2227*5ffb0c9bSToomas Soome     mDNSu32 ExtraPackets0;      // 0 to 2 packets
2228*5ffb0c9bSToomas Soome     mDNSu32 ExtraPackets3;      // 3 to 6 packets
2229*5ffb0c9bSToomas Soome     mDNSu32 ExtraPackets7;      // 7 to 9 packets
2230*5ffb0c9bSToomas Soome     mDNSu32 ExtraPackets10;     // >= 10 packets
2231*5ffb0c9bSToomas Soome     mDNSu32 SecureStatus;
2232*5ffb0c9bSToomas Soome     mDNSu32 InsecureStatus;
2233*5ffb0c9bSToomas Soome     mDNSu32 IndeterminateStatus;
2234*5ffb0c9bSToomas Soome     mDNSu32 BogusStatus;
2235*5ffb0c9bSToomas Soome     mDNSu32 NoResponseStatus;
2236*5ffb0c9bSToomas Soome     mDNSu32 NumProbesSent;      // Number of probes sent
2237*5ffb0c9bSToomas Soome     mDNSu32 MsgSize0;           // DNSSEC message size <= 1024
2238*5ffb0c9bSToomas Soome     mDNSu32 MsgSize1;           // DNSSEC message size <= 2048
2239*5ffb0c9bSToomas Soome     mDNSu32 MsgSize2;           // DNSSEC message size > 2048
2240*5ffb0c9bSToomas Soome } DNSSECStatistics;
2241*5ffb0c9bSToomas Soome 
2242*5ffb0c9bSToomas Soome typedef struct
2243*5ffb0c9bSToomas Soome {
2244*5ffb0c9bSToomas Soome     mDNSu32 NameConflicts;                  // Normal Name conflicts
2245*5ffb0c9bSToomas Soome     mDNSu32 KnownUniqueNameConflicts;       // Name Conflicts for KnownUnique Records
2246*5ffb0c9bSToomas Soome     mDNSu32 DupQuerySuppressions;           // Duplicate query suppressions
2247*5ffb0c9bSToomas Soome     mDNSu32 KnownAnswerSuppressions;        // Known Answer suppressions
2248*5ffb0c9bSToomas Soome     mDNSu32 KnownAnswerMultiplePkts;        // Known Answer in queries spannign multiple packets
2249*5ffb0c9bSToomas Soome     mDNSu32 PoofCacheDeletions;             // Number of times the cache was deleted due to POOF
2250*5ffb0c9bSToomas Soome     mDNSu32 UnicastBitInQueries;            // Queries with QU bit set
2251*5ffb0c9bSToomas Soome     mDNSu32 NormalQueries;                  // Queries with QU bit not set
2252*5ffb0c9bSToomas Soome     mDNSu32 MatchingAnswersForQueries;      // Queries for which we had a response
2253*5ffb0c9bSToomas Soome     mDNSu32 UnicastResponses;               // Unicast responses to queries
2254*5ffb0c9bSToomas Soome     mDNSu32 MulticastResponses;             // Multicast responses to queries
2255*5ffb0c9bSToomas Soome     mDNSu32 UnicastDemotedToMulticast;      // Number of times unicast demoted to multicast
2256*5ffb0c9bSToomas Soome     mDNSu32 Sleeps;                         // Total sleeps
2257*5ffb0c9bSToomas Soome     mDNSu32 Wakes;                          // Total wakes
2258*5ffb0c9bSToomas Soome     mDNSu32 InterfaceUp;                    // Total Interface UP events
2259*5ffb0c9bSToomas Soome     mDNSu32 InterfaceUpFlap;                // Total Interface UP events with flaps
2260*5ffb0c9bSToomas Soome     mDNSu32 InterfaceDown;                  // Total Interface Down events
2261*5ffb0c9bSToomas Soome     mDNSu32 InterfaceDownFlap;              // Total Interface Down events with flaps
2262*5ffb0c9bSToomas Soome     mDNSu32 CacheRefreshQueries;            // Number of queries that we sent for refreshing cache
2263*5ffb0c9bSToomas Soome     mDNSu32 CacheRefreshed;                 // Number of times the cache was refreshed due to a response
2264*5ffb0c9bSToomas Soome     mDNSu32 WakeOnResolves;                 // Number of times we did a wake on resolve
2265*5ffb0c9bSToomas Soome } mDNSStatistics;
2266*5ffb0c9bSToomas Soome extern void LogMDNSStatistics(mDNS *const m);
22674b22b933Srs200217 
22684b22b933Srs200217 struct mDNS_struct
22694b22b933Srs200217 {
22704b22b933Srs200217     // Internal state fields. These hold the main internal state of mDNSCore;
22714b22b933Srs200217     // the client layer needn't be concerned with them.
22724b22b933Srs200217     // No fields need to be set up by the client prior to calling mDNS_Init();
22734b22b933Srs200217     // all required data is passed as parameters to that function.
22744b22b933Srs200217 
22754b22b933Srs200217     mDNS_PlatformSupport *p;            // Pointer to platform-specific data of indeterminite size
22764b22b933Srs200217     mDNSBool CanReceiveUnicastOn5353;
22774b22b933Srs200217     mDNSBool AdvertiseLocalAddresses;
2278*5ffb0c9bSToomas Soome     mDNSBool DivertMulticastAdvertisements; // from interfaces that do not advertise local addresses to local-only
22794b22b933Srs200217     mStatus mDNSPlatformStatus;
22804b22b933Srs200217     mDNSIPPort UnicastPort4;
22814b22b933Srs200217     mDNSIPPort UnicastPort6;
2282*5ffb0c9bSToomas Soome     mDNSEthAddr PrimaryMAC;             // Used as unique host ID
22834b22b933Srs200217     mDNSCallback *MainCallback;
22844b22b933Srs200217     void         *MainContext;
22854b22b933Srs200217 
22864b22b933Srs200217     // For debugging: To catch and report locking failures
22874b22b933Srs200217     mDNSu32 mDNS_busy;                  // Incremented between mDNS_Lock/mDNS_Unlock section
22884b22b933Srs200217     mDNSu32 mDNS_reentrancy;            // Incremented when calling a client callback
22894b22b933Srs200217     mDNSu8 lock_rrcache;                // For debugging: Set at times when these lists may not be modified
22904b22b933Srs200217     mDNSu8 lock_Questions;
22914b22b933Srs200217     mDNSu8 lock_Records;
2292*5ffb0c9bSToomas Soome #ifndef MaxMsg
2293*5ffb0c9bSToomas Soome     #define MaxMsg 512
2294*5ffb0c9bSToomas Soome #endif
22954b22b933Srs200217     char MsgBuffer[MaxMsg];             // Temp storage used while building error log messages
22964b22b933Srs200217 
22974b22b933Srs200217     // Task Scheduling variables
22984b22b933Srs200217     mDNSs32 timenow_adjust;             // Correction applied if we ever discover time went backwards
22994b22b933Srs200217     mDNSs32 timenow;                    // The time that this particular activation of the mDNS code started
23004b22b933Srs200217     mDNSs32 timenow_last;               // The time the last time we ran
23014b22b933Srs200217     mDNSs32 NextScheduledEvent;         // Derived from values below
2302*5ffb0c9bSToomas Soome     mDNSs32 ShutdownTime;               // Set when we're shutting down; allows us to skip some unnecessary steps
2303*5ffb0c9bSToomas Soome     mDNSs32 SuppressSending;            // Don't send local-link mDNS packets during this time
23044b22b933Srs200217     mDNSs32 NextCacheCheck;             // Next time to refresh cache record before it expires
23054b22b933Srs200217     mDNSs32 NextScheduledQuery;         // Next time to send query in its exponential backoff sequence
23064b22b933Srs200217     mDNSs32 NextScheduledProbe;         // Next time to probe for new authoritative record
23074b22b933Srs200217     mDNSs32 NextScheduledResponse;      // Next time to send authoritative record(s) in responses
2308*5ffb0c9bSToomas Soome     mDNSs32 NextScheduledNATOp;         // Next time to send NAT-traversal packets
2309*5ffb0c9bSToomas Soome     mDNSs32 NextScheduledSPS;           // Next time to purge expiring Sleep Proxy records
2310*5ffb0c9bSToomas Soome     mDNSs32 NextScheduledKA;            // Next time to send Keepalive packets (SPS)
23114b22b933Srs200217     mDNSs32 RandomQueryDelay;           // For de-synchronization of query packets on the wire
23124b22b933Srs200217     mDNSu32 RandomReconfirmDelay;       // For de-synchronization of reconfirmation queries on the wire
23134b22b933Srs200217     mDNSs32 PktNum;                     // Unique sequence number assigned to each received packet
2314*5ffb0c9bSToomas Soome     mDNSs32 MPktNum;                    // Unique sequence number assigned to each received Multicast packet
2315*5ffb0c9bSToomas Soome     mDNSu8 LocalRemoveEvents;           // Set if we may need to deliver remove events for local-only questions and/or local-only records
2316*5ffb0c9bSToomas Soome     mDNSu8 SleepState;                  // Set if we're sleeping
2317*5ffb0c9bSToomas Soome     mDNSu8 SleepSeqNum;                 // "Epoch number" of our current period of wakefulness
2318*5ffb0c9bSToomas Soome     mDNSu8 SystemWakeOnLANEnabled;      // Set if we want to register with a Sleep Proxy before going to sleep
2319*5ffb0c9bSToomas Soome     mDNSu8 SentSleepProxyRegistration;  // Set if we registered (or tried to register) with a Sleep Proxy
2320*5ffb0c9bSToomas Soome     mDNSu8 SystemSleepOnlyIfWakeOnLAN;  // Set if we may only sleep if we managed to register with a Sleep Proxy
2321*5ffb0c9bSToomas Soome     mDNSs32 AnnounceOwner;              // After waking from sleep, include OWNER option in packets until this time
2322*5ffb0c9bSToomas Soome     mDNSs32 DelaySleep;                 // To inhibit re-sleeping too quickly right after wake
2323*5ffb0c9bSToomas Soome     mDNSs32 SleepLimit;                 // Time window to allow deregistrations, etc.,
2324*5ffb0c9bSToomas Soome                                         // during which underying platform layer should inhibit system sleep
2325*5ffb0c9bSToomas Soome     mDNSs32 TimeSlept;                  // Time we went to sleep.
2326*5ffb0c9bSToomas Soome 
2327*5ffb0c9bSToomas Soome     mDNSs32 StatStartTime;              // Time we started gathering statistics during this interval.
2328*5ffb0c9bSToomas Soome     mDNSs32 NextStatLogTime;            // Next time to log statistics.
2329*5ffb0c9bSToomas Soome     mDNSs32 ActiveStatTime;             // Total time awake/gathering statistics for this log period.
2330*5ffb0c9bSToomas Soome     mDNSs32 UnicastPacketsSent;         // Number of unicast packets sent.
2331*5ffb0c9bSToomas Soome     mDNSs32 MulticastPacketsSent;       // Number of multicast packets sent.
2332*5ffb0c9bSToomas Soome     mDNSs32 RemoteSubnet;               // Multicast packets received from outside our subnet.
2333*5ffb0c9bSToomas Soome 
2334*5ffb0c9bSToomas Soome     mDNSs32 NextScheduledSPRetry;       // Time next sleep proxy registration action is required.
2335*5ffb0c9bSToomas Soome                                         // Only valid if SleepLimit is nonzero and DelaySleep is zero.
2336*5ffb0c9bSToomas Soome 
2337*5ffb0c9bSToomas Soome     mDNSs32 NextScheduledStopTime;      // Next time to stop a question
2338*5ffb0c9bSToomas Soome 
23394b22b933Srs200217 
23404b22b933Srs200217     // These fields only required for mDNS Searcher...
23414b22b933Srs200217     DNSQuestion *Questions;             // List of all registered questions, active and inactive
23424b22b933Srs200217     DNSQuestion *NewQuestions;          // Fresh questions not yet answered from cache
23434b22b933Srs200217     DNSQuestion *CurrentQuestion;       // Next question about to be examined in AnswerLocalQuestions()
2344*5ffb0c9bSToomas Soome     DNSQuestion *LocalOnlyQuestions;    // Questions with InterfaceID set to mDNSInterface_LocalOnly or mDNSInterface_P2P
2345*5ffb0c9bSToomas Soome     DNSQuestion *NewLocalOnlyQuestions; // Fresh local-only or P2P questions not yet answered
2346*5ffb0c9bSToomas Soome     DNSQuestion *RestartQuestion;       // Questions that are being restarted (stop followed by start)
2347*5ffb0c9bSToomas Soome     DNSQuestion *ValidationQuestion;    // Questions that are being validated (dnssec)
23484b22b933Srs200217     mDNSu32 rrcache_size;               // Total number of available cache entries
23494b22b933Srs200217     mDNSu32 rrcache_totalused;          // Number of cache entries currently occupied
2350*5ffb0c9bSToomas Soome     mDNSu32 rrcache_totalused_unicast;  // Number of cache entries currently occupied by unicast
23514b22b933Srs200217     mDNSu32 rrcache_active;             // Number of cache entries currently occupied by records that answer active questions
23524b22b933Srs200217     mDNSu32 rrcache_report;
23534b22b933Srs200217     CacheEntity *rrcache_free;
23544b22b933Srs200217     CacheGroup *rrcache_hash[CACHE_HASH_SLOTS];
2355*5ffb0c9bSToomas Soome     mDNSs32 rrcache_nextcheck[CACHE_HASH_SLOTS];
2356*5ffb0c9bSToomas Soome 
2357*5ffb0c9bSToomas Soome     AuthHash rrauth;
23584b22b933Srs200217 
23594b22b933Srs200217     // Fields below only required for mDNS Responder...
23604b22b933Srs200217     domainlabel nicelabel;              // Rich text label encoded using canonically precomposed UTF-8
23614b22b933Srs200217     domainlabel hostlabel;              // Conforms to RFC 1034 "letter-digit-hyphen" ARPANET host name rules
23624b22b933Srs200217     domainname MulticastHostname;       // Fully Qualified "dot-local" Host Name, e.g. "Foo.local."
23634b22b933Srs200217     UTF8str255 HIHardware;
23644b22b933Srs200217     UTF8str255 HISoftware;
2365*5ffb0c9bSToomas Soome     AuthRecord DeviceInfo;
23664b22b933Srs200217     AuthRecord *ResourceRecords;
23674b22b933Srs200217     AuthRecord *DuplicateRecords;       // Records currently 'on hold' because they are duplicates of existing records
2368*5ffb0c9bSToomas Soome     AuthRecord *NewLocalRecords;        // Fresh AuthRecords (public) not yet delivered to our local-only questions
23694b22b933Srs200217     AuthRecord *CurrentRecord;          // Next AuthRecord about to be examined
2370*5ffb0c9bSToomas Soome     mDNSBool NewLocalOnlyRecords;       // Fresh AuthRecords (local only) not yet delivered to our local questions
23714b22b933Srs200217     NetworkInterfaceInfo *HostInterfaces;
23724b22b933Srs200217     mDNSs32 ProbeFailTime;
23734b22b933Srs200217     mDNSu32 NumFailedProbes;
23744b22b933Srs200217     mDNSs32 SuppressProbes;
2375*5ffb0c9bSToomas Soome     Platform_t mDNS_plat;
23764b22b933Srs200217 
2377*5ffb0c9bSToomas Soome     // Unicast-specific data
2378*5ffb0c9bSToomas Soome     mDNSs32 NextuDNSEvent;                  // uDNS next event
2379*5ffb0c9bSToomas Soome     mDNSs32 NextSRVUpdate;                  // Time to perform delayed update
2380*5ffb0c9bSToomas Soome 
2381*5ffb0c9bSToomas Soome     DNSServer        *DNSServers;           // list of DNS servers
2382*5ffb0c9bSToomas Soome     McastResolver    *McastResolvers;       // list of Mcast Resolvers
2383*5ffb0c9bSToomas Soome 
2384*5ffb0c9bSToomas Soome     mDNSAddr Router;
2385*5ffb0c9bSToomas Soome     mDNSAddr AdvertisedV4;                  // IPv4 address pointed to by hostname
2386*5ffb0c9bSToomas Soome     mDNSAddr AdvertisedV6;                  // IPv6 address pointed to by hostname
2387*5ffb0c9bSToomas Soome 
2388*5ffb0c9bSToomas Soome     DomainAuthInfo   *AuthInfoList;         // list of domains requiring authentication for updates
2389*5ffb0c9bSToomas Soome 
2390*5ffb0c9bSToomas Soome     DNSQuestion ReverseMap;                 // Reverse-map query to find static hostname for service target
2391*5ffb0c9bSToomas Soome     DNSQuestion AutomaticBrowseDomainQ;
2392*5ffb0c9bSToomas Soome     domainname StaticHostname;              // Current answer to reverse-map query
2393*5ffb0c9bSToomas Soome     domainname FQDN;
2394*5ffb0c9bSToomas Soome     HostnameInfo     *Hostnames;            // List of registered hostnames + hostname metadata
2395*5ffb0c9bSToomas Soome     NATTraversalInfo AutoTunnelNAT;         // Shared between all AutoTunnel DomainAuthInfo structs
2396*5ffb0c9bSToomas Soome     mDNSv6Addr AutoTunnelRelayAddr;
2397*5ffb0c9bSToomas Soome 
2398*5ffb0c9bSToomas Soome     mDNSu32 WABBrowseQueriesCount;          // Number of WAB Browse domain enumeration queries (b, db) callers
2399*5ffb0c9bSToomas Soome     mDNSu32 WABLBrowseQueriesCount;         // Number of legacy WAB Browse domain enumeration queries (lb) callers
2400*5ffb0c9bSToomas Soome     mDNSu32 WABRegQueriesCount;             // Number of WAB Registration domain enumeration queries (r, dr) callers
2401*5ffb0c9bSToomas Soome     mDNSu8 SearchDomainsHash[MD5_LEN];
2402*5ffb0c9bSToomas Soome 
2403*5ffb0c9bSToomas Soome     // NAT-Traversal fields
2404*5ffb0c9bSToomas Soome     NATTraversalInfo LLQNAT;                    // Single shared NAT Traversal to receive inbound LLQ notifications
2405*5ffb0c9bSToomas Soome     NATTraversalInfo *NATTraversals;
2406*5ffb0c9bSToomas Soome     NATTraversalInfo *CurrentNATTraversal;
2407*5ffb0c9bSToomas Soome     mDNSs32 retryIntervalGetAddr;               // delta between time sent and retry for NAT-PMP & UPnP/IGD external address request
2408*5ffb0c9bSToomas Soome     mDNSs32 retryGetAddr;                       // absolute time when we retry for NAT-PMP & UPnP/IGD external address request
2409*5ffb0c9bSToomas Soome     mDNSv4Addr ExtAddress;                      // the external address discovered via NAT-PMP or UPnP/IGD
2410*5ffb0c9bSToomas Soome     mDNSu32 PCPNonce[3];                        // the nonce if using PCP
2411*5ffb0c9bSToomas Soome 
2412*5ffb0c9bSToomas Soome     UDPSocket        *NATMcastRecvskt;          // For receiving PCP & NAT-PMP announcement multicasts from router on port 5350
2413*5ffb0c9bSToomas Soome     mDNSu32 LastNATupseconds;                   // NAT engine uptime in seconds, from most recent NAT packet
2414*5ffb0c9bSToomas Soome     mDNSs32 LastNATReplyLocalTime;              // Local time in ticks when most recent NAT packet was received
2415*5ffb0c9bSToomas Soome     mDNSu16 LastNATMapResultCode;               // Most recent error code for mappings
2416*5ffb0c9bSToomas Soome 
2417*5ffb0c9bSToomas Soome     tcpLNTInfo tcpAddrInfo;                     // legacy NAT traversal TCP connection info for external address
2418*5ffb0c9bSToomas Soome     tcpLNTInfo tcpDeviceInfo;                   // legacy NAT traversal TCP connection info for device info
2419*5ffb0c9bSToomas Soome     tcpLNTInfo       *tcpInfoUnmapList;         // list of pending unmap requests
2420*5ffb0c9bSToomas Soome     mDNSInterfaceID UPnPInterfaceID;
2421*5ffb0c9bSToomas Soome     UDPSocket        *SSDPSocket;               // For SSDP request/response
2422*5ffb0c9bSToomas Soome     mDNSBool SSDPWANPPPConnection;              // whether we should send the SSDP query for WANIPConnection or WANPPPConnection
2423*5ffb0c9bSToomas Soome     mDNSIPPort UPnPRouterPort;                  // port we send discovery messages to
2424*5ffb0c9bSToomas Soome     mDNSIPPort UPnPSOAPPort;                    // port we send SOAP messages to
2425*5ffb0c9bSToomas Soome     mDNSu8           *UPnPRouterURL;            // router's URL string
2426*5ffb0c9bSToomas Soome     mDNSBool UPnPWANPPPConnection;              // whether we're using WANIPConnection or WANPPPConnection
2427*5ffb0c9bSToomas Soome     mDNSu8           *UPnPSOAPURL;              // router's SOAP control URL string
2428*5ffb0c9bSToomas Soome     mDNSu8           *UPnPRouterAddressString;  // holds both the router's address and port
2429*5ffb0c9bSToomas Soome     mDNSu8           *UPnPSOAPAddressString;    // holds both address and port for SOAP messages
2430*5ffb0c9bSToomas Soome 
2431*5ffb0c9bSToomas Soome     // Sleep Proxy client fields
2432*5ffb0c9bSToomas Soome     AuthRecord *SPSRRSet;                       // To help the client keep track of the records registered with the sleep proxy
2433*5ffb0c9bSToomas Soome 
2434*5ffb0c9bSToomas Soome     // Sleep Proxy Server fields
2435*5ffb0c9bSToomas Soome     mDNSu8 SPSType;                             // 0 = off, 10-99 encodes desirability metric
2436*5ffb0c9bSToomas Soome     mDNSu8 SPSPortability;                      // 10-99
2437*5ffb0c9bSToomas Soome     mDNSu8 SPSMarginalPower;                    // 10-99
2438*5ffb0c9bSToomas Soome     mDNSu8 SPSTotalPower;                       // 10-99
2439*5ffb0c9bSToomas Soome     mDNSu8 SPSFeatureFlags;                     // Features supported. Currently 1 = TCP KeepAlive supported.
2440*5ffb0c9bSToomas Soome     mDNSu8 SPSState;                            // 0 = off, 1 = running, 2 = shutting down, 3 = suspended during sleep
2441*5ffb0c9bSToomas Soome     mDNSInterfaceID SPSProxyListChanged;
2442*5ffb0c9bSToomas Soome     UDPSocket        *SPSSocket;
2443*5ffb0c9bSToomas Soome #ifndef SPC_DISABLED
2444*5ffb0c9bSToomas Soome     ServiceRecordSet SPSRecords;
2445*5ffb0c9bSToomas Soome #endif
2446*5ffb0c9bSToomas Soome     mDNSQuestionCallback *SPSBrowseCallback;    // So the platform layer can do something useful with SPS browse results
2447*5ffb0c9bSToomas Soome     int ProxyRecords;                           // Total number of records we're holding as proxy
2448*5ffb0c9bSToomas Soome     #define           MAX_PROXY_RECORDS 10000   /* DOS protection: 400 machines at 25 records each */
2449*5ffb0c9bSToomas Soome 
2450*5ffb0c9bSToomas Soome #if APPLE_OSX_mDNSResponder
2451*5ffb0c9bSToomas Soome     ClientTunnel     *TunnelClients;
2452*5ffb0c9bSToomas Soome     uuid_t asl_uuid;                            // uuid for ASL logging
2453*5ffb0c9bSToomas Soome     void            *WCF;
2454*5ffb0c9bSToomas Soome #endif
2455*5ffb0c9bSToomas Soome     // DNS Proxy fields
2456*5ffb0c9bSToomas Soome     mDNSu32 dp_ipintf[MaxIp];                   // input interface index list from the DNS Proxy Client
2457*5ffb0c9bSToomas Soome     mDNSu32 dp_opintf;                          // output interface index from the DNS Proxy Client
2458*5ffb0c9bSToomas Soome 
2459*5ffb0c9bSToomas Soome     TrustAnchor     *TrustAnchors;
2460*5ffb0c9bSToomas Soome     int             notifyToken;
2461*5ffb0c9bSToomas Soome     int             uds_listener_skt;           // Listening socket for incoming UDS clients
2462*5ffb0c9bSToomas Soome     mDNSBool        mDNSOppCaching;             // Opportunistic Caching
2463*5ffb0c9bSToomas Soome     mDNSu32         AutoTargetServices;         // # of services that have AutoTarget set
2464*5ffb0c9bSToomas Soome     DNSSECStatistics DNSSECStats;
2465*5ffb0c9bSToomas Soome     mDNSStatistics   mDNSStats;
24664b22b933Srs200217 
24674b22b933Srs200217     // Fixed storage, to avoid creating large objects on the stack
2468*5ffb0c9bSToomas Soome     // The imsg is declared as a union with a pointer type to enforce CPU-appropriate alignment
2469*5ffb0c9bSToomas Soome     union { DNSMessage m; void *p; } imsg;  // Incoming message received from wire
24704b22b933Srs200217     DNSMessage omsg;                        // Outgoing message we're building
24714b22b933Srs200217     LargeCacheRecord rec;                   // Resource Record extracted from received message
24724b22b933Srs200217 };
24734b22b933Srs200217 
24744b22b933Srs200217 #define FORALL_CACHERECORDS(SLOT,CG,CR)                           \
24754b22b933Srs200217     for ((SLOT) = 0; (SLOT) < CACHE_HASH_SLOTS; (SLOT)++)                                                                   \
24764b22b933Srs200217         for ((CG)=m->rrcache_hash[(SLOT)]; (CG); (CG)=(CG)->next)                                                                   \
24774b22b933Srs200217             for ((CR) = (CG)->members; (CR); (CR)=(CR)->next)
24784b22b933Srs200217 
24794b22b933Srs200217 // ***************************************************************************
24804b22b933Srs200217 #if 0
2481*5ffb0c9bSToomas Soome #pragma mark -
24824b22b933Srs200217 #pragma mark - Useful Static Constants
24834b22b933Srs200217 #endif
24844b22b933Srs200217 
2485*5ffb0c9bSToomas Soome extern const mDNSInterfaceID mDNSInterface_Any;             // Zero
2486*5ffb0c9bSToomas Soome extern const mDNSInterfaceID mDNSInterface_LocalOnly;       // Special value
2487*5ffb0c9bSToomas Soome extern const mDNSInterfaceID mDNSInterface_Unicast;         // Special value
2488*5ffb0c9bSToomas Soome extern const mDNSInterfaceID mDNSInterfaceMark;             // Special value
2489*5ffb0c9bSToomas Soome extern const mDNSInterfaceID mDNSInterface_P2P;             // Special value
2490*5ffb0c9bSToomas Soome extern const mDNSInterfaceID uDNSInterfaceMark;             // Special value
2491*5ffb0c9bSToomas Soome 
2492*5ffb0c9bSToomas Soome extern const mDNSIPPort DiscardPort;
2493*5ffb0c9bSToomas Soome extern const mDNSIPPort SSHPort;
2494*5ffb0c9bSToomas Soome extern const mDNSIPPort UnicastDNSPort;
2495*5ffb0c9bSToomas Soome extern const mDNSIPPort SSDPPort;
2496*5ffb0c9bSToomas Soome extern const mDNSIPPort IPSECPort;
2497*5ffb0c9bSToomas Soome extern const mDNSIPPort NSIPCPort;
2498*5ffb0c9bSToomas Soome extern const mDNSIPPort NATPMPAnnouncementPort;
2499*5ffb0c9bSToomas Soome extern const mDNSIPPort NATPMPPort;
2500*5ffb0c9bSToomas Soome extern const mDNSIPPort DNSEXTPort;
2501*5ffb0c9bSToomas Soome extern const mDNSIPPort MulticastDNSPort;
2502*5ffb0c9bSToomas Soome extern const mDNSIPPort LoopbackIPCPort;
2503*5ffb0c9bSToomas Soome extern const mDNSIPPort PrivateDNSPort;
2504*5ffb0c9bSToomas Soome 
2505*5ffb0c9bSToomas Soome extern const OwnerOptData zeroOwner;
2506*5ffb0c9bSToomas Soome 
25074b22b933Srs200217 extern const mDNSIPPort zeroIPPort;
25084b22b933Srs200217 extern const mDNSv4Addr zerov4Addr;
25094b22b933Srs200217 extern const mDNSv6Addr zerov6Addr;
25104b22b933Srs200217 extern const mDNSEthAddr zeroEthAddr;
25114b22b933Srs200217 extern const mDNSv4Addr onesIPv4Addr;
25124b22b933Srs200217 extern const mDNSv6Addr onesIPv6Addr;
2513*5ffb0c9bSToomas Soome extern const mDNSEthAddr onesEthAddr;
25144b22b933Srs200217 extern const mDNSAddr zeroAddr;
25154b22b933Srs200217 
25164b22b933Srs200217 extern const mDNSv4Addr AllDNSAdminGroup;
2517*5ffb0c9bSToomas Soome extern const mDNSv4Addr AllHosts_v4;
2518*5ffb0c9bSToomas Soome extern const mDNSv6Addr AllHosts_v6;
2519*5ffb0c9bSToomas Soome extern const mDNSv6Addr NDP_prefix;
2520*5ffb0c9bSToomas Soome extern const mDNSEthAddr AllHosts_v6_Eth;
25214b22b933Srs200217 extern const mDNSAddr AllDNSLinkGroup_v4;
25224b22b933Srs200217 extern const mDNSAddr AllDNSLinkGroup_v6;
25234b22b933Srs200217 
25244b22b933Srs200217 extern const mDNSOpaque16 zeroID;
2525*5ffb0c9bSToomas Soome extern const mDNSOpaque16 onesID;
25264b22b933Srs200217 extern const mDNSOpaque16 QueryFlags;
25274b22b933Srs200217 extern const mDNSOpaque16 uQueryFlags;
2528*5ffb0c9bSToomas Soome extern const mDNSOpaque16 DNSSecQFlags;
25294b22b933Srs200217 extern const mDNSOpaque16 ResponseFlags;
25304b22b933Srs200217 extern const mDNSOpaque16 UpdateReqFlags;
25314b22b933Srs200217 extern const mDNSOpaque16 UpdateRespFlags;
25324b22b933Srs200217 
2533*5ffb0c9bSToomas Soome extern const mDNSOpaque64 zeroOpaque64;
2534*5ffb0c9bSToomas Soome 
2535*5ffb0c9bSToomas Soome extern mDNSBool StrictUnicastOrdering;
2536*5ffb0c9bSToomas Soome extern mDNSu8 NumUnicastDNSServers;
2537*5ffb0c9bSToomas Soome 
25384b22b933Srs200217 #define localdomain           (*(const domainname *)"\x5" "local")
2539*5ffb0c9bSToomas Soome #define DeviceInfoName        (*(const domainname *)"\xC" "_device-info" "\x4" "_tcp")
2540*5ffb0c9bSToomas Soome #define LocalDeviceInfoName   (*(const domainname *)"\xC" "_device-info" "\x4" "_tcp" "\x5" "local")
2541*5ffb0c9bSToomas Soome #define SleepProxyServiceType (*(const domainname *)"\xC" "_sleep-proxy" "\x4" "_udp")
25424b22b933Srs200217 
25434b22b933Srs200217 // ***************************************************************************
25444b22b933Srs200217 #if 0
2545*5ffb0c9bSToomas Soome #pragma mark -
25464b22b933Srs200217 #pragma mark - Inline functions
25474b22b933Srs200217 #endif
25484b22b933Srs200217 
25494b22b933Srs200217 #if (defined(_MSC_VER))
25504b22b933Srs200217     #define mDNSinline static __inline
25514b22b933Srs200217 #elif ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9)))
25524b22b933Srs200217     #define mDNSinline static inline
2553*5ffb0c9bSToomas Soome #else
2554*5ffb0c9bSToomas Soome     #define mDNSinline static inline
25554b22b933Srs200217 #endif
25564b22b933Srs200217 
25574b22b933Srs200217 // If we're not doing inline functions, then this header needs to have the extern declarations
25584b22b933Srs200217 #if !defined(mDNSinline)
25594b22b933Srs200217 extern mDNSs32      NonZeroTime(mDNSs32 t);
25604b22b933Srs200217 extern mDNSu16      mDNSVal16(mDNSOpaque16 x);
25614b22b933Srs200217 extern mDNSOpaque16 mDNSOpaque16fromIntVal(mDNSu16 v);
25624b22b933Srs200217 #endif
25634b22b933Srs200217 
25644b22b933Srs200217 // If we're compiling the particular C file that instantiates our inlines, then we
25654b22b933Srs200217 // define "mDNSinline" (to empty string) so that we generate code in the following section
25664b22b933Srs200217 #if (!defined(mDNSinline) && mDNS_InstantiateInlines)
25674b22b933Srs200217 #define mDNSinline
25684b22b933Srs200217 #endif
25694b22b933Srs200217 
25704b22b933Srs200217 #ifdef mDNSinline
25714b22b933Srs200217 
25724b22b933Srs200217 mDNSinline mDNSs32 NonZeroTime(mDNSs32 t) { if (t) return(t);else return(1);}
25734b22b933Srs200217 
25744b22b933Srs200217 mDNSinline mDNSu16 mDNSVal16(mDNSOpaque16 x) { return((mDNSu16)((mDNSu16)x.b[0] <<  8 | (mDNSu16)x.b[1])); }
25754b22b933Srs200217 
25764b22b933Srs200217 mDNSinline mDNSOpaque16 mDNSOpaque16fromIntVal(mDNSu16 v)
25774b22b933Srs200217 {
25784b22b933Srs200217     mDNSOpaque16 x;
25794b22b933Srs200217     x.b[0] = (mDNSu8)(v >> 8);
25804b22b933Srs200217     x.b[1] = (mDNSu8)(v & 0xFF);
25814b22b933Srs200217     return(x);
25824b22b933Srs200217 }
25834b22b933Srs200217 
25844b22b933Srs200217 #endif
25854b22b933Srs200217 
25864b22b933Srs200217 // ***************************************************************************
25874b22b933Srs200217 #if 0
2588*5ffb0c9bSToomas Soome #pragma mark -
25894b22b933Srs200217 #pragma mark - Main Client Functions
25904b22b933Srs200217 #endif
25914b22b933Srs200217 
25924b22b933Srs200217 // Every client should call mDNS_Init, passing in storage for the mDNS object and the mDNS_PlatformSupport object.
25934b22b933Srs200217 //
25944b22b933Srs200217 // Clients that are only advertising services should use mDNS_Init_NoCache and mDNS_Init_ZeroCacheSize.
25954b22b933Srs200217 // Clients that plan to perform queries (mDNS_StartQuery, mDNS_StartBrowse, mDNS_StartResolveService, etc.)
25964b22b933Srs200217 // need to provide storage for the resource record cache, or the query calls will return 'mStatus_NoCache'.
25974b22b933Srs200217 // The rrcachestorage parameter is the address of memory for the resource record cache, and
25984b22b933Srs200217 // the rrcachesize parameter is the number of entries in the CacheRecord array passed in.
25994b22b933Srs200217 // (i.e. the size of the cache memory needs to be sizeof(CacheRecord) * rrcachesize).
26004b22b933Srs200217 // OS X 10.3 Panther uses an initial cache size of 64 entries, and then mDNSCore sends an
26014b22b933Srs200217 // mStatus_GrowCache message if it needs more.
26024b22b933Srs200217 //
26034b22b933Srs200217 // Most clients should use mDNS_Init_AdvertiseLocalAddresses. This causes mDNSCore to automatically
26044b22b933Srs200217 // create the correct address records for all the hosts interfaces. If you plan to advertise
26054b22b933Srs200217 // services being offered by the local machine, this is almost always what you want.
26064b22b933Srs200217 // There are two cases where you might use mDNS_Init_DontAdvertiseLocalAddresses:
26074b22b933Srs200217 // 1. A client-only device, that browses for services but doesn't advertise any of its own.
26084b22b933Srs200217 // 2. A proxy-registration service, that advertises services being offered by other machines, and takes
26094b22b933Srs200217 //    the appropriate steps to manually create the correct address records for those other machines.
26104b22b933Srs200217 // In principle, a proxy-like registration service could manually create address records for its own machine too,
26114b22b933Srs200217 // but this would be pointless extra effort when using mDNS_Init_AdvertiseLocalAddresses does that for you.
26124b22b933Srs200217 //
2613*5ffb0c9bSToomas Soome // Note that a client-only device that wishes to prohibit multicast advertisements (e.g. from
2614*5ffb0c9bSToomas Soome // higher-layer API calls) must also set DivertMulticastAdvertisements in the mDNS structure and
2615*5ffb0c9bSToomas Soome // advertise local address(es) on a loopback interface.
2616*5ffb0c9bSToomas Soome //
26174b22b933Srs200217 // When mDNS has finished setting up the client's callback is called
26184b22b933Srs200217 // A client can also spin and poll the mDNSPlatformStatus field to see when it changes from mStatus_Waiting to mStatus_NoError
26194b22b933Srs200217 //
2620*5ffb0c9bSToomas Soome // Call mDNS_StartExit to tidy up before exiting
2621*5ffb0c9bSToomas Soome // Because exiting may be an asynchronous process (e.g. if unicast records need to be deregistered)
2622*5ffb0c9bSToomas Soome // client layer may choose to wait until mDNS_ExitNow() returns true before calling mDNS_FinalExit().
26234b22b933Srs200217 //
26244b22b933Srs200217 // Call mDNS_Register with a completed AuthRecord object to register a resource record
26254b22b933Srs200217 // If the resource record type is kDNSRecordTypeUnique (or kDNSknownunique) then if a conflicting resource record is discovered,
26264b22b933Srs200217 // the resource record's mDNSRecordCallback will be called with error code mStatus_NameConflict. The callback should deregister
26274b22b933Srs200217 // the record, and may then try registering the record again after picking a new name (e.g. by automatically appending a number).
26284b22b933Srs200217 // Following deregistration, the RecordCallback will be called with result mStatus_MemFree to signal that it is safe to deallocate
26294b22b933Srs200217 // the record's storage (memory must be freed asynchronously to allow for goodbye packets and dynamic update deregistration).
26304b22b933Srs200217 //
26314b22b933Srs200217 // Call mDNS_StartQuery to initiate a query. mDNS will proceed to issue Multicast DNS query packets, and any time a response
26324b22b933Srs200217 // is received containing a record which matches the question, the DNSQuestion's mDNSAnswerCallback function will be called
26334b22b933Srs200217 // Call mDNS_StopQuery when no more answers are required
26344b22b933Srs200217 //
26354b22b933Srs200217 // Care should be taken on multi-threaded or interrupt-driven environments.
26364b22b933Srs200217 // The main mDNS routines call mDNSPlatformLock() on entry and mDNSPlatformUnlock() on exit;
26374b22b933Srs200217 // each platform layer needs to implement these appropriately for its respective platform.
26384b22b933Srs200217 // For example, if the support code on a particular platform implements timer callbacks at interrupt time, then
26394b22b933Srs200217 // mDNSPlatformLock/Unlock need to disable interrupts or do similar concurrency control to ensure that the mDNS
26404b22b933Srs200217 // code is not entered by an interrupt-time timer callback while in the middle of processing a client call.
26414b22b933Srs200217 
26424b22b933Srs200217 extern mStatus mDNS_Init      (mDNS *const m, mDNS_PlatformSupport *const p,
26434b22b933Srs200217                                CacheEntity *rrcachestorage, mDNSu32 rrcachesize,
26444b22b933Srs200217                                mDNSBool AdvertiseLocalAddresses,
26454b22b933Srs200217                                mDNSCallback *Callback, void *Context);
26464b22b933Srs200217 // See notes above on use of NoCache/ZeroCacheSize
26474b22b933Srs200217 #define mDNS_Init_NoCache                     mDNSNULL
26484b22b933Srs200217 #define mDNS_Init_ZeroCacheSize               0
26494b22b933Srs200217 // See notes above on use of Advertise/DontAdvertiseLocalAddresses
26504b22b933Srs200217 #define mDNS_Init_AdvertiseLocalAddresses     mDNStrue
26514b22b933Srs200217 #define mDNS_Init_DontAdvertiseLocalAddresses mDNSfalse
26524b22b933Srs200217 #define mDNS_Init_NoInitCallback              mDNSNULL
26534b22b933Srs200217 #define mDNS_Init_NoInitCallbackContext       mDNSNULL
26544b22b933Srs200217 
2655*5ffb0c9bSToomas Soome extern void    mDNS_ConfigChanged(mDNS *const m);
26564b22b933Srs200217 extern void    mDNS_GrowCache (mDNS *const m, CacheEntity *storage, mDNSu32 numrecords);
2657*5ffb0c9bSToomas Soome extern void    mDNS_GrowAuth (mDNS *const m, AuthEntity *storage, mDNSu32 numrecords);
2658*5ffb0c9bSToomas Soome extern void    mDNS_StartExit (mDNS *const m);
2659*5ffb0c9bSToomas Soome extern void    mDNS_FinalExit (mDNS *const m);
2660*5ffb0c9bSToomas Soome #define mDNS_Close(m) do { mDNS_StartExit(m); mDNS_FinalExit(m); } while(0)
2661*5ffb0c9bSToomas Soome #define mDNS_ExitNow(m, now) ((now) - (m)->ShutdownTime >= 0 || (!(m)->ResourceRecords))
2662*5ffb0c9bSToomas Soome 
26634b22b933Srs200217 extern mDNSs32 mDNS_Execute   (mDNS *const m);
26644b22b933Srs200217 
26654b22b933Srs200217 extern mStatus mDNS_Register  (mDNS *const m, AuthRecord *const rr);
26664b22b933Srs200217 extern mStatus mDNS_Update    (mDNS *const m, AuthRecord *const rr, mDNSu32 newttl,
26674b22b933Srs200217                                const mDNSu16 newrdlength, RData *const newrdata, mDNSRecordUpdateCallback *Callback);
26684b22b933Srs200217 extern mStatus mDNS_Deregister(mDNS *const m, AuthRecord *const rr);
26694b22b933Srs200217 
26704b22b933Srs200217 extern mStatus mDNS_StartQuery(mDNS *const m, DNSQuestion *const question);
26714b22b933Srs200217 extern mStatus mDNS_StopQuery (mDNS *const m, DNSQuestion *const question);
2672*5ffb0c9bSToomas Soome extern mStatus mDNS_StopQueryWithRemoves(mDNS *const m, DNSQuestion *const question);
26734b22b933Srs200217 extern mStatus mDNS_Reconfirm (mDNS *const m, CacheRecord *const cacherr);
2674*5ffb0c9bSToomas Soome extern mStatus mDNS_Reconfirm_internal(mDNS *const m, CacheRecord *const rr, mDNSu32 interval);
26754b22b933Srs200217 extern mStatus mDNS_ReconfirmByValue(mDNS *const m, ResourceRecord *const rr);
2676*5ffb0c9bSToomas Soome extern void    mDNS_PurgeCacheResourceRecord(mDNS *const m, CacheRecord *rr);
26774b22b933Srs200217 extern mDNSs32 mDNS_TimeNow(const mDNS *const m);
26784b22b933Srs200217 
2679*5ffb0c9bSToomas Soome extern mStatus mDNS_StartNATOperation(mDNS *const m, NATTraversalInfo *traversal);
2680*5ffb0c9bSToomas Soome extern mStatus mDNS_StopNATOperation(mDNS *const m, NATTraversalInfo *traversal);
2681*5ffb0c9bSToomas Soome extern mStatus mDNS_StopNATOperation_internal(mDNS *m, NATTraversalInfo *traversal);
2682*5ffb0c9bSToomas Soome 
2683*5ffb0c9bSToomas Soome extern DomainAuthInfo *GetAuthInfoForName(mDNS *m, const domainname *const name);
2684*5ffb0c9bSToomas Soome 
2685*5ffb0c9bSToomas Soome extern void    mDNS_UpdateAllowSleep(mDNS *const m);
2686*5ffb0c9bSToomas Soome 
26874b22b933Srs200217 // ***************************************************************************
26884b22b933Srs200217 #if 0
2689*5ffb0c9bSToomas Soome #pragma mark -
26904b22b933Srs200217 #pragma mark - Platform support functions that are accessible to the client layer too
26914b22b933Srs200217 #endif
26924b22b933Srs200217 
26934b22b933Srs200217 extern mDNSs32 mDNSPlatformOneSecond;
26944b22b933Srs200217 
26954b22b933Srs200217 // ***************************************************************************
26964b22b933Srs200217 #if 0
2697*5ffb0c9bSToomas Soome #pragma mark -
26984b22b933Srs200217 #pragma mark - General utility and helper functions
26994b22b933Srs200217 #endif
27004b22b933Srs200217 
2701*5ffb0c9bSToomas Soome // mDNS_Dereg_normal is used for most calls to mDNS_Deregister_internal
2702*5ffb0c9bSToomas Soome // mDNS_Dereg_rapid is used to send one goodbye instead of three, when we want the memory available for reuse sooner
2703*5ffb0c9bSToomas Soome // mDNS_Dereg_conflict is used to indicate that this record is being forcibly deregistered because of a conflict
2704*5ffb0c9bSToomas Soome // mDNS_Dereg_repeat is used when cleaning up, for records that may have already been forcibly deregistered
2705*5ffb0c9bSToomas Soome typedef enum { mDNS_Dereg_normal, mDNS_Dereg_rapid, mDNS_Dereg_conflict, mDNS_Dereg_repeat } mDNS_Dereg_type;
2706*5ffb0c9bSToomas Soome 
27074b22b933Srs200217 // mDNS_RegisterService is a single call to register the set of resource records associated with a given named service.
27084b22b933Srs200217 //
27094b22b933Srs200217 // mDNS_StartResolveService is single call which is equivalent to multiple calls to mDNS_StartQuery,
27104b22b933Srs200217 // to find the IP address, port number, and demultiplexing information for a given named service.
27114b22b933Srs200217 // As with mDNS_StartQuery, it executes asynchronously, and calls the ServiceInfoQueryCallback when the answer is
27124b22b933Srs200217 // found. After the service is resolved, the client should call mDNS_StopResolveService to complete the transaction.
27134b22b933Srs200217 // The client can also call mDNS_StopResolveService at any time to abort the transaction.
27144b22b933Srs200217 //
27154b22b933Srs200217 // mDNS_AddRecordToService adds an additional record to a Service Record Set.  This record may be deregistered
27164b22b933Srs200217 // via mDNS_RemoveRecordFromService, or by deregistering the service.  mDNS_RemoveRecordFromService is passed a
27174b22b933Srs200217 // callback to free the memory associated with the extra RR when it is safe to do so.  The ExtraResourceRecord
27184b22b933Srs200217 // object can be found in the record's context pointer.
27194b22b933Srs200217 
27204b22b933Srs200217 // mDNS_GetBrowseDomains is a special case of the mDNS_StartQuery call, where the resulting answers
27214b22b933Srs200217 // are a list of PTR records indicating (in the rdata) domains that are recommended for browsing.
27224b22b933Srs200217 // After getting the list of domains to browse, call mDNS_StopQuery to end the search.
27234b22b933Srs200217 // mDNS_GetDefaultBrowseDomain returns the name of the domain that should be highlighted by default.
27244b22b933Srs200217 //
27254b22b933Srs200217 // mDNS_GetRegistrationDomains and mDNS_GetDefaultRegistrationDomain are the equivalent calls to get the list
27264b22b933Srs200217 // of one or more domains that should be offered to the user as choices for where they may register their service,
27274b22b933Srs200217 // and the default domain in which to register in the case where the user has made no selection.
27284b22b933Srs200217 
27294b22b933Srs200217 extern void    mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mDNSInterfaceID InterfaceID,
2730*5ffb0c9bSToomas Soome                                         mDNSu16 rrtype, mDNSu32 ttl, mDNSu8 RecordType, AuthRecType artype, mDNSRecordCallback Callback, void *Context);
2731*5ffb0c9bSToomas Soome 
2732*5ffb0c9bSToomas Soome // mDNS_RegisterService() flags parameter bit definitions.
2733*5ffb0c9bSToomas Soome // Note these are only defined to transfer the corresponding DNSServiceFlags settings into mDNSCore routines,
2734*5ffb0c9bSToomas Soome // since code in mDNSCore does not include the DNSServiceFlags definitions in dns_sd.h.
2735*5ffb0c9bSToomas Soome enum
2736*5ffb0c9bSToomas Soome {
2737*5ffb0c9bSToomas Soome     coreFlagIncludeP2P   = 0x1,     // include P2P interfaces when using mDNSInterface_Any
2738*5ffb0c9bSToomas Soome     coreFlagIncludeAWDL  = 0x2,     // include AWDL interface when using mDNSInterface_Any
2739*5ffb0c9bSToomas Soome     coreFlagKnownUnique  = 0x4,     // client guarantees that SRV and TXT record names are unique
2740*5ffb0c9bSToomas Soome     coreFlagWakeOnly     = 0x8      // Service won't be registered with sleep proxy
2741*5ffb0c9bSToomas Soome };
27424b22b933Srs200217 
27434b22b933Srs200217 extern mStatus mDNS_RegisterService  (mDNS *const m, ServiceRecordSet *sr,
27444b22b933Srs200217                                       const domainlabel *const name, const domainname *const type, const domainname *const domain,
27454b22b933Srs200217                                       const domainname *const host, mDNSIPPort port, const mDNSu8 txtinfo[], mDNSu16 txtlen,
27464b22b933Srs200217                                       AuthRecord *SubTypes, mDNSu32 NumSubTypes,
2747*5ffb0c9bSToomas Soome                                       mDNSInterfaceID InterfaceID, mDNSServiceCallback Callback, void *Context, mDNSu32 flags);
2748*5ffb0c9bSToomas Soome extern mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra, RData *rdata, mDNSu32 ttl,  mDNSu32 flags);
27494b22b933Srs200217 extern mStatus mDNS_RemoveRecordFromService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra, mDNSRecordCallback MemFreeCallback, void *Context);
27504b22b933Srs200217 extern mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordSet *const sr, const domainlabel *newname);
2751*5ffb0c9bSToomas Soome extern mStatus mDNS_DeregisterService_drt(mDNS *const m, ServiceRecordSet *sr, mDNS_Dereg_type drt);
2752*5ffb0c9bSToomas Soome #define mDNS_DeregisterService(M,S) mDNS_DeregisterService_drt((M), (S), mDNS_Dereg_normal)
27534b22b933Srs200217 
27544b22b933Srs200217 extern mStatus mDNS_RegisterNoSuchService(mDNS *const m, AuthRecord *const rr,
27554b22b933Srs200217                                           const domainlabel *const name, const domainname *const type, const domainname *const domain,
27564b22b933Srs200217                                           const domainname *const host,
2757*5ffb0c9bSToomas Soome                                           const mDNSInterfaceID InterfaceID, mDNSRecordCallback Callback, void *Context, mDNSu32 flags);
27584b22b933Srs200217 #define        mDNS_DeregisterNoSuchService mDNS_Deregister
27594b22b933Srs200217 
2760*5ffb0c9bSToomas Soome extern void mDNS_SetupQuestion(DNSQuestion *const q, const mDNSInterfaceID InterfaceID, const domainname *const name,
2761*5ffb0c9bSToomas Soome                                const mDNSu16 qtype, mDNSQuestionCallback *const callback, void *const context);
2762*5ffb0c9bSToomas Soome 
27634b22b933Srs200217 extern mStatus mDNS_StartBrowse(mDNS *const m, DNSQuestion *const question,
2764*5ffb0c9bSToomas Soome                                 const domainname *const srv, const domainname *const domain, const mDNSu8 *anondata,
2765*5ffb0c9bSToomas Soome                                 const mDNSInterfaceID InterfaceID, mDNSu32 flags,
2766*5ffb0c9bSToomas Soome                                 mDNSBool ForceMCast, mDNSBool useBackgroundTrafficClass,
2767*5ffb0c9bSToomas Soome                                 mDNSQuestionCallback *Callback, void *Context);
27684b22b933Srs200217 #define        mDNS_StopBrowse mDNS_StopQuery
27694b22b933Srs200217 
27704b22b933Srs200217 extern mStatus mDNS_StartResolveService(mDNS *const m, ServiceInfoQuery *query, ServiceInfo *info, mDNSServiceInfoQueryCallback *Callback, void *Context);
27714b22b933Srs200217 extern void    mDNS_StopResolveService (mDNS *const m, ServiceInfoQuery *query);
27724b22b933Srs200217 
27734b22b933Srs200217 typedef enum
27744b22b933Srs200217 {
27754b22b933Srs200217     mDNS_DomainTypeBrowse              = 0,
27764b22b933Srs200217     mDNS_DomainTypeBrowseDefault       = 1,
2777*5ffb0c9bSToomas Soome     mDNS_DomainTypeBrowseAutomatic     = 2,
27784b22b933Srs200217     mDNS_DomainTypeRegistration        = 3,
27794b22b933Srs200217     mDNS_DomainTypeRegistrationDefault = 4,
27804b22b933Srs200217 
27814b22b933Srs200217     mDNS_DomainTypeMax = 4
27824b22b933Srs200217 } mDNS_DomainType;
27834b22b933Srs200217 
27844b22b933Srs200217 extern const char *const mDNS_DomainTypeNames[];
27854b22b933Srs200217 
27864b22b933Srs200217 extern mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, mDNS_DomainType DomainType, const domainname *dom,
27874b22b933Srs200217                                const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *Callback, void *Context);
27884b22b933Srs200217 #define        mDNS_StopGetDomains mDNS_StopQuery
27894b22b933Srs200217 extern mStatus mDNS_AdvertiseDomains(mDNS *const m, AuthRecord *rr, mDNS_DomainType DomainType, const mDNSInterfaceID InterfaceID, char *domname);
27904b22b933Srs200217 #define        mDNS_StopAdvertiseDomains mDNS_Deregister
27914b22b933Srs200217 
2792*5ffb0c9bSToomas Soome extern mDNSOpaque16 mDNS_NewMessageID(mDNS *const m);
2793*5ffb0c9bSToomas Soome extern mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr, mDNSBool *myself);
2794*5ffb0c9bSToomas Soome 
2795*5ffb0c9bSToomas Soome extern DNSServer *GetServerForQuestion(mDNS *m, DNSQuestion *question);
2796*5ffb0c9bSToomas Soome extern mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question);
2797*5ffb0c9bSToomas Soome 
27984b22b933Srs200217 // ***************************************************************************
27994b22b933Srs200217 #if 0
2800*5ffb0c9bSToomas Soome #pragma mark -
28014b22b933Srs200217 #pragma mark - DNS name utility functions
28024b22b933Srs200217 #endif
28034b22b933Srs200217 
28044b22b933Srs200217 // In order to expose the full capabilities of the DNS protocol (which allows any arbitrary eight-bit values
28054b22b933Srs200217 // in domain name labels, including unlikely characters like ascii nulls and even dots) all the mDNS APIs
28064b22b933Srs200217 // work with DNS's native length-prefixed strings. For convenience in C, the following utility functions
28074b22b933Srs200217 // are provided for converting between C's null-terminated strings and DNS's length-prefixed strings.
28084b22b933Srs200217 
28094b22b933Srs200217 // Assignment
28104b22b933Srs200217 // A simple C structure assignment of a domainname can cause a protection fault by accessing unmapped memory,
28114b22b933Srs200217 // because that object is defined to be 256 bytes long, but not all domainname objects are truly the full size.
28124b22b933Srs200217 // This macro uses mDNSPlatformMemCopy() to make sure it only touches the actual bytes that are valid.
2813*5ffb0c9bSToomas Soome #define AssignDomainName(DST, SRC) do { mDNSu16 len__ = DomainNameLength((SRC)); \
2814*5ffb0c9bSToomas Soome                                         if (len__ <= MAX_DOMAIN_NAME) mDNSPlatformMemCopy((DST)->c, (SRC)->c, len__);else (DST)->c[0] = 0;} while(0)
28154b22b933Srs200217 
28164b22b933Srs200217 // Comparison functions
2817*5ffb0c9bSToomas Soome #define SameDomainLabelCS(A,B) ((A)[0] == (B)[0] && mDNSPlatformMemSame((A)+1, (B)+1, (A)[0]))
28184b22b933Srs200217 extern mDNSBool SameDomainLabel(const mDNSu8 *a, const mDNSu8 *b);
28194b22b933Srs200217 extern mDNSBool SameDomainName(const domainname *const d1, const domainname *const d2);
2820*5ffb0c9bSToomas Soome extern mDNSBool SameDomainNameCS(const domainname *const d1, const domainname *const d2);
2821*5ffb0c9bSToomas Soome typedef mDNSBool DomainNameComparisonFn (const domainname *const d1, const domainname *const d2);
28224b22b933Srs200217 extern mDNSBool IsLocalDomain(const domainname *d);     // returns true for domains that by default should be looked up using link-local multicast
28234b22b933Srs200217 
2824*5ffb0c9bSToomas Soome #define StripFirstLabel(X) ((const domainname *)& (X)->c[(X)->c[0] ? 1 + (X)->c[0] : 0])
2825*5ffb0c9bSToomas Soome 
2826*5ffb0c9bSToomas Soome #define FirstLabel(X)  ((const domainlabel *)(X))
2827*5ffb0c9bSToomas Soome #define SecondLabel(X) ((const domainlabel *)StripFirstLabel(X))
2828*5ffb0c9bSToomas Soome #define ThirdLabel(X)  ((const domainlabel *)StripFirstLabel(StripFirstLabel(X)))
2829*5ffb0c9bSToomas Soome 
2830*5ffb0c9bSToomas Soome extern const mDNSu8 *LastLabel(const domainname *d);
2831*5ffb0c9bSToomas Soome 
28324b22b933Srs200217 // Get total length of domain name, in native DNS format, including terminal root label
28334b22b933Srs200217 //   (e.g. length of "com." is 5 (length byte, three data bytes, final zero)
2834*5ffb0c9bSToomas Soome extern mDNSu16  DomainNameLengthLimit(const domainname *const name, const mDNSu8 *limit);
2835*5ffb0c9bSToomas Soome #define DomainNameLength(name) DomainNameLengthLimit((name), (name)->c + MAX_DOMAIN_NAME)
28364b22b933Srs200217 
28374b22b933Srs200217 // Append functions to append one or more labels to an existing native format domain name:
28384b22b933Srs200217 //   AppendLiteralLabelString adds a single label from a literal C string, with no escape character interpretation.
28394b22b933Srs200217 //   AppendDNSNameString      adds zero or more labels from a C string using conventional DNS dots-and-escaping interpretation
28404b22b933Srs200217 //   AppendDomainLabel        adds a single label from a native format domainlabel
28414b22b933Srs200217 //   AppendDomainName         adds zero or more labels from a native format domainname
28424b22b933Srs200217 extern mDNSu8  *AppendLiteralLabelString(domainname *const name, const char *cstr);
28434b22b933Srs200217 extern mDNSu8  *AppendDNSNameString     (domainname *const name, const char *cstr);
28444b22b933Srs200217 extern mDNSu8  *AppendDomainLabel       (domainname *const name, const domainlabel *const label);
28454b22b933Srs200217 extern mDNSu8  *AppendDomainName        (domainname *const name, const domainname *const append);
28464b22b933Srs200217 
28474b22b933Srs200217 // Convert from null-terminated string to native DNS format:
28484b22b933Srs200217 //   The DomainLabel form makes a single label from a literal C string, with no escape character interpretation.
28494b22b933Srs200217 //   The DomainName form makes native format domain name from a C string using conventional DNS interpretation:
28504b22b933Srs200217 //     dots separate labels, and within each label, '\.' represents a literal dot, '\\' represents a literal
28514b22b933Srs200217 //     backslash and backslash with three decimal digits (e.g. \000) represents an arbitrary byte value.
28524b22b933Srs200217 extern mDNSBool MakeDomainLabelFromLiteralString(domainlabel *const label, const char *cstr);
28534b22b933Srs200217 extern mDNSu8  *MakeDomainNameFromDNSNameString (domainname  *const name,  const char *cstr);
28544b22b933Srs200217 
28554b22b933Srs200217 // Convert native format domainlabel or domainname back to C string format
28564b22b933Srs200217 // IMPORTANT:
28574b22b933Srs200217 // When using ConvertDomainLabelToCString, the target buffer must be MAX_ESCAPED_DOMAIN_LABEL (254) bytes long
28584b22b933Srs200217 // to guarantee there will be no buffer overrun. It is only safe to use a buffer shorter than this in rare cases
28594b22b933Srs200217 // where the label is known to be constrained somehow (for example, if the label is known to be either "_tcp" or "_udp").
2860*5ffb0c9bSToomas Soome // Similarly, when using ConvertDomainNameToCString, the target buffer must be MAX_ESCAPED_DOMAIN_NAME (1009) bytes long.
28614b22b933Srs200217 // See definitions of MAX_ESCAPED_DOMAIN_LABEL and MAX_ESCAPED_DOMAIN_NAME for more detailed explanation.
28624b22b933Srs200217 extern char    *ConvertDomainLabelToCString_withescape(const domainlabel *const name, char *cstr, char esc);
28634b22b933Srs200217 #define         ConvertDomainLabelToCString_unescaped(D,C) ConvertDomainLabelToCString_withescape((D), (C), 0)
28644b22b933Srs200217 #define         ConvertDomainLabelToCString(D,C)           ConvertDomainLabelToCString_withescape((D), (C), '\\')
28654b22b933Srs200217 extern char    *ConvertDomainNameToCString_withescape(const domainname *const name, char *cstr, char esc);
28664b22b933Srs200217 #define         ConvertDomainNameToCString_unescaped(D,C) ConvertDomainNameToCString_withescape((D), (C), 0)
28674b22b933Srs200217 #define         ConvertDomainNameToCString(D,C)           ConvertDomainNameToCString_withescape((D), (C), '\\')
28684b22b933Srs200217 
28694b22b933Srs200217 extern void     ConvertUTF8PstringToRFC1034HostLabel(const mDNSu8 UTF8Name[], domainlabel *const hostlabel);
28704b22b933Srs200217 
28714b22b933Srs200217 extern mDNSu8  *ConstructServiceName(domainname *const fqdn, const domainlabel *name, const domainname *type, const domainname *const domain);
28724b22b933Srs200217 extern mDNSBool DeconstructServiceName(const domainname *const fqdn, domainlabel *const name, domainname *const type, domainname *const domain);
28734b22b933Srs200217 
28744b22b933Srs200217 // Note: Some old functions have been replaced by more sensibly-named versions.
28754b22b933Srs200217 // You can uncomment the hash-defines below if you don't want to have to change your source code right away.
28764b22b933Srs200217 // When updating your code, note that (unlike the old versions) *all* the new routines take the target object
28774b22b933Srs200217 // as their first parameter.
28784b22b933Srs200217 //#define ConvertCStringToDomainName(SRC,DST)  MakeDomainNameFromDNSNameString((DST),(SRC))
28794b22b933Srs200217 //#define ConvertCStringToDomainLabel(SRC,DST) MakeDomainLabelFromLiteralString((DST),(SRC))
28804b22b933Srs200217 //#define AppendStringLabelToName(DST,SRC)     AppendLiteralLabelString((DST),(SRC))
28814b22b933Srs200217 //#define AppendStringNameToName(DST,SRC)      AppendDNSNameString((DST),(SRC))
28824b22b933Srs200217 //#define AppendDomainLabelToName(DST,SRC)     AppendDomainLabel((DST),(SRC))
28834b22b933Srs200217 //#define AppendDomainNameToName(DST,SRC)      AppendDomainName((DST),(SRC))
28844b22b933Srs200217 
28854b22b933Srs200217 // ***************************************************************************
28864b22b933Srs200217 #if 0
2887*5ffb0c9bSToomas Soome #pragma mark -
28884b22b933Srs200217 #pragma mark - Other utility functions and macros
28894b22b933Srs200217 #endif
28904b22b933Srs200217 
28914b22b933Srs200217 // mDNS_vsnprintf/snprintf return the number of characters written, excluding the final terminating null.
28924b22b933Srs200217 // The output is always null-terminated: for example, if the output turns out to be exactly buflen long,
28934b22b933Srs200217 // then the output will be truncated by one character to allow space for the terminating null.
28944b22b933Srs200217 // Unlike standard C vsnprintf/snprintf, they return the number of characters *actually* written,
28954b22b933Srs200217 // not the number of characters that *would* have been printed were buflen unlimited.
28964b22b933Srs200217 extern mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, va_list arg);
28974b22b933Srs200217 extern mDNSu32 mDNS_snprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, ...) IS_A_PRINTF_STYLE_FUNCTION(3,4);
28984b22b933Srs200217 extern mDNSu32 NumCacheRecordsForInterfaceID(const mDNS *const m, mDNSInterfaceID id);
28994b22b933Srs200217 extern char *DNSTypeName(mDNSu16 rrtype);
2900*5ffb0c9bSToomas Soome extern char *GetRRDisplayString_rdb(const ResourceRecord *const rr, const RDataBody *const rd1, char *const buffer);
29014b22b933Srs200217 #define RRDisplayString(m, rr) GetRRDisplayString_rdb(rr, &(rr)->rdata->u, (m)->MsgBuffer)
29024b22b933Srs200217 #define ARDisplayString(m, rr) GetRRDisplayString_rdb(&(rr)->resrec, &(rr)->resrec.rdata->u, (m)->MsgBuffer)
29034b22b933Srs200217 #define CRDisplayString(m, rr) GetRRDisplayString_rdb(&(rr)->resrec, &(rr)->resrec.rdata->u, (m)->MsgBuffer)
29044b22b933Srs200217 extern mDNSBool mDNSSameAddress(const mDNSAddr *ip1, const mDNSAddr *ip2);
29054b22b933Srs200217 extern void IncrementLabelSuffix(domainlabel *name, mDNSBool RichText);
2906*5ffb0c9bSToomas Soome extern mDNSBool mDNSv4AddrIsRFC1918(const mDNSv4Addr * const addr);  // returns true for RFC1918 private addresses
2907*5ffb0c9bSToomas Soome #define mDNSAddrIsRFC1918(X) ((X)->type == mDNSAddrType_IPv4 && mDNSv4AddrIsRFC1918(&(X)->ip.v4))
2908*5ffb0c9bSToomas Soome 
2909*5ffb0c9bSToomas Soome // For PCP
2910*5ffb0c9bSToomas Soome extern void mDNSAddrMapIPv4toIPv6(mDNSv4Addr* in, mDNSv6Addr* out);
2911*5ffb0c9bSToomas Soome extern mDNSBool mDNSAddrIPv4FromMappedIPv6(mDNSv6Addr *in, mDNSv4Addr *out);
2912*5ffb0c9bSToomas Soome 
2913*5ffb0c9bSToomas Soome #define mDNSSameIPPort(A,B)      ((A).NotAnInteger == (B).NotAnInteger)
2914*5ffb0c9bSToomas Soome #define mDNSSameOpaque16(A,B)    ((A).NotAnInteger == (B).NotAnInteger)
2915*5ffb0c9bSToomas Soome #define mDNSSameOpaque32(A,B)    ((A).NotAnInteger == (B).NotAnInteger)
2916*5ffb0c9bSToomas Soome #define mDNSSameOpaque64(A,B)    ((A)->l[0] == (B)->l[0] && (A)->l[1] == (B)->l[1])
29174b22b933Srs200217 
29184b22b933Srs200217 #define mDNSSameIPv4Address(A,B) ((A).NotAnInteger == (B).NotAnInteger)
29194b22b933Srs200217 #define mDNSSameIPv6Address(A,B) ((A).l[0] == (B).l[0] && (A).l[1] == (B).l[1] && (A).l[2] == (B).l[2] && (A).l[3] == (B).l[3])
2920*5ffb0c9bSToomas Soome #define mDNSSameIPv6NetworkPart(A,B) ((A).l[0] == (B).l[0] && (A).l[1] == (B).l[1])
29214b22b933Srs200217 #define mDNSSameEthAddress(A,B)  ((A)->w[0] == (B)->w[0] && (A)->w[1] == (B)->w[1] && (A)->w[2] == (B)->w[2])
29224b22b933Srs200217 
2923*5ffb0c9bSToomas Soome #define mDNSIPPortIsZero(A)      ((A).NotAnInteger                            == 0)
2924*5ffb0c9bSToomas Soome #define mDNSOpaque16IsZero(A)    ((A).NotAnInteger                            == 0)
2925*5ffb0c9bSToomas Soome #define mDNSOpaque64IsZero(A)    (((A)->l[0] | (A)->l[1]                    ) == 0)
2926*5ffb0c9bSToomas Soome #define mDNSIPv4AddressIsZero(A) ((A).NotAnInteger                            == 0)
2927*5ffb0c9bSToomas Soome #define mDNSIPv6AddressIsZero(A) (((A).l[0] | (A).l[1] | (A).l[2] | (A).l[3]) == 0)
2928*5ffb0c9bSToomas Soome #define mDNSEthAddressIsZero(A)  (((A).w[0] | (A).w[1] | (A).w[2]           ) == 0)
29294b22b933Srs200217 
2930*5ffb0c9bSToomas Soome #define mDNSIPv4AddressIsOnes(A) ((A).NotAnInteger == 0xFFFFFFFF)
2931*5ffb0c9bSToomas Soome #define mDNSIPv6AddressIsOnes(A) (((A).l[0] & (A).l[1] & (A).l[2] & (A).l[3]) == 0xFFFFFFFF)
29324b22b933Srs200217 
29334b22b933Srs200217 #define mDNSAddressIsAllDNSLinkGroup(X) (                                                            \
2934*5ffb0c9bSToomas Soome         ((X)->type == mDNSAddrType_IPv4 && mDNSSameIPv4Address((X)->ip.v4, AllDNSLinkGroup_v4.ip.v4)) || \
2935*5ffb0c9bSToomas Soome         ((X)->type == mDNSAddrType_IPv6 && mDNSSameIPv6Address((X)->ip.v6, AllDNSLinkGroup_v6.ip.v6))    )
29364b22b933Srs200217 
29374b22b933Srs200217 #define mDNSAddressIsZero(X) (                                                \
29384b22b933Srs200217         ((X)->type == mDNSAddrType_IPv4 && mDNSIPv4AddressIsZero((X)->ip.v4))  || \
29394b22b933Srs200217         ((X)->type == mDNSAddrType_IPv6 && mDNSIPv6AddressIsZero((X)->ip.v6))     )
29404b22b933Srs200217 
29414b22b933Srs200217 #define mDNSAddressIsValidNonZero(X) (                                        \
29424b22b933Srs200217         ((X)->type == mDNSAddrType_IPv4 && !mDNSIPv4AddressIsZero((X)->ip.v4)) || \
29434b22b933Srs200217         ((X)->type == mDNSAddrType_IPv6 && !mDNSIPv6AddressIsZero((X)->ip.v6))    )
29444b22b933Srs200217 
29454b22b933Srs200217 #define mDNSAddressIsOnes(X) (                                                \
29464b22b933Srs200217         ((X)->type == mDNSAddrType_IPv4 && mDNSIPv4AddressIsOnes((X)->ip.v4))  || \
29474b22b933Srs200217         ((X)->type == mDNSAddrType_IPv6 && mDNSIPv6AddressIsOnes((X)->ip.v6))     )
29484b22b933Srs200217 
29494b22b933Srs200217 #define mDNSAddressIsValid(X) (                                                                                             \
29504b22b933Srs200217         ((X)->type == mDNSAddrType_IPv4) ? !(mDNSIPv4AddressIsZero((X)->ip.v4) || mDNSIPv4AddressIsOnes((X)->ip.v4)) :          \
29514b22b933Srs200217         ((X)->type == mDNSAddrType_IPv6) ? !(mDNSIPv6AddressIsZero((X)->ip.v6) || mDNSIPv6AddressIsOnes((X)->ip.v6)) : mDNSfalse)
29524b22b933Srs200217 
2953*5ffb0c9bSToomas Soome #define mDNSv4AddressIsLinkLocal(X) ((X)->b[0] ==  169 &&  (X)->b[1]         ==  254)
2954*5ffb0c9bSToomas Soome #define mDNSv6AddressIsLinkLocal(X) ((X)->b[0] == 0xFE && ((X)->b[1] & 0xC0) == 0x80)
2955*5ffb0c9bSToomas Soome 
2956*5ffb0c9bSToomas Soome #define mDNSAddressIsLinkLocal(X)  (                                                    \
2957*5ffb0c9bSToomas Soome         ((X)->type == mDNSAddrType_IPv4) ? mDNSv4AddressIsLinkLocal(&(X)->ip.v4) :          \
2958*5ffb0c9bSToomas Soome         ((X)->type == mDNSAddrType_IPv6) ? mDNSv6AddressIsLinkLocal(&(X)->ip.v6) : mDNSfalse)
2959*5ffb0c9bSToomas Soome 
2960*5ffb0c9bSToomas Soome #define mDNSv4AddressIsLoopback(X) ((X)->b[0] == 127 && (X)->b[1] == 0 && (X)->b[2] == 0 && (X)->b[3] == 1)
2961*5ffb0c9bSToomas Soome #define mDNSv6AddressIsLoopback(X) ((((X)->l[0] | (X)->l[1] | (X)->l[2]) == 0) && ((X)->b[12] == 0 && (X)->b[13] == 0 && (X)->b[14] == 0 && (X)->b[15] == 1))
2962*5ffb0c9bSToomas Soome 
2963*5ffb0c9bSToomas Soome #define mDNSAddressIsLoopback(X)  (                                                         \
2964*5ffb0c9bSToomas Soome         ((X)->type == mDNSAddrType_IPv4) ? mDNSv4AddressIsLoopback(&(X)->ip.v4) :           \
2965*5ffb0c9bSToomas Soome         ((X)->type == mDNSAddrType_IPv6) ? mDNSv6AddressIsLoopback(&(X)->ip.v6) : mDNSfalse)
29664b22b933Srs200217 
29674b22b933Srs200217 // ***************************************************************************
29684b22b933Srs200217 #if 0
2969*5ffb0c9bSToomas Soome #pragma mark -
29704b22b933Srs200217 #pragma mark - Authentication Support
29714b22b933Srs200217 #endif
29724b22b933Srs200217 
29734b22b933Srs200217 // Unicast DNS and Dynamic Update specific Client Calls
29744b22b933Srs200217 //
2975*5ffb0c9bSToomas Soome // mDNS_SetSecretForDomain tells the core to authenticate (via TSIG with an HMAC_MD5 hash of the shared secret)
29764b22b933Srs200217 // when dynamically updating a given zone (and its subdomains).  The key used in authentication must be in
29774b22b933Srs200217 // domain name format.  The shared secret must be a null-terminated base64 encoded string.  A minimum size of
29784b22b933Srs200217 // 16 bytes (128 bits) is recommended for an MD5 hash as per RFC 2485.
29794b22b933Srs200217 // Calling this routine multiple times for a zone replaces previously entered values.  Call with a NULL key
2980*5ffb0c9bSToomas Soome // to disable authentication for the zone.  A non-NULL autoTunnelPrefix means this is an AutoTunnel domain,
2981*5ffb0c9bSToomas Soome // and the value is prepended to the IPSec identifier (used for key lookup)
29824b22b933Srs200217 
2983*5ffb0c9bSToomas Soome extern mStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info,
2984*5ffb0c9bSToomas Soome                                        const domainname *domain, const domainname *keyname, const char *b64keydata, const domainname *hostname, mDNSIPPort *port, mDNSBool autoTunnel);
2985*5ffb0c9bSToomas Soome 
2986*5ffb0c9bSToomas Soome extern void RecreateNATMappings(mDNS *const m, const mDNSu32 waitTicks);
29874b22b933Srs200217 
29884b22b933Srs200217 // Hostname/Unicast Interface Configuration
29894b22b933Srs200217 
29904b22b933Srs200217 // All hostnames advertised point to one IPv4 address and/or one IPv6 address, set via SetPrimaryInterfaceInfo.  Invoking this routine
29914b22b933Srs200217 // updates all existing hostnames to point to the new address.
29924b22b933Srs200217 
29934b22b933Srs200217 // A hostname is added via AddDynDNSHostName, which points to the primary interface's v4 and/or v6 addresss
29944b22b933Srs200217 
29954b22b933Srs200217 // The status callback is invoked to convey success or failure codes - the callback should not modify the AuthRecord or free memory.
29964b22b933Srs200217 // Added hostnames may be removed (deregistered) via mDNS_RemoveDynDNSHostName.
29974b22b933Srs200217 
29984b22b933Srs200217 // Host domains added prior to specification of the primary interface address and computer name will be deferred until
29994b22b933Srs200217 // these values are initialized.
30004b22b933Srs200217 
3001*5ffb0c9bSToomas Soome // DNS servers used to resolve unicast queries are specified by mDNS_AddDNSServer.
30024b22b933Srs200217 // For "split" DNS configurations, in which queries for different domains are sent to different servers (e.g. VPN and external),
30034b22b933Srs200217 // a domain may be associated with a DNS server.  For standard configurations, specify the root label (".") or NULL.
30044b22b933Srs200217 
30054b22b933Srs200217 extern void mDNS_AddDynDNSHostName(mDNS *m, const domainname *fqdn, mDNSRecordCallback *StatusCallback, const void *StatusContext);
30064b22b933Srs200217 extern void mDNS_RemoveDynDNSHostName(mDNS *m, const domainname *fqdn);
30074b22b933Srs200217 extern void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr,  const mDNSAddr *v6addr, const mDNSAddr *router);
3008*5ffb0c9bSToomas Soome extern DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, mDNSs32 serviceID, const mDNSAddr *addr,
3009*5ffb0c9bSToomas Soome                                     const mDNSIPPort port, mDNSu32 scoped, mDNSu32 timeout, mDNSBool cellIntf, mDNSu16 resGroupID, mDNSBool reqA,
3010*5ffb0c9bSToomas Soome                                     mDNSBool reqAAAA, mDNSBool reqDO);
3011*5ffb0c9bSToomas Soome extern void PenalizeDNSServer(mDNS *const m, DNSQuestion *q, mDNSOpaque16 responseFlags);
3012*5ffb0c9bSToomas Soome extern void mDNS_AddSearchDomain(const domainname *const domain, mDNSInterfaceID InterfaceID);
3013*5ffb0c9bSToomas Soome 
3014*5ffb0c9bSToomas Soome extern McastResolver *mDNS_AddMcastResolver(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, mDNSu32 timeout);
3015*5ffb0c9bSToomas Soome 
3016*5ffb0c9bSToomas Soome // We use ((void *)0) here instead of mDNSNULL to avoid compile warnings on gcc 4.2
3017*5ffb0c9bSToomas Soome #define mDNS_AddSearchDomain_CString(X, I) \
3018*5ffb0c9bSToomas Soome     do { domainname d__; if (((X) != (void*)0) && MakeDomainNameFromDNSNameString(&d__, (X)) && d__.c[0]) mDNS_AddSearchDomain(&d__, I);} while(0)
30194b22b933Srs200217 
30204b22b933Srs200217 // Routines called by the core, exported by DNSDigest.c
30214b22b933Srs200217 
3022*5ffb0c9bSToomas Soome // Convert an arbitrary base64 encoded key key into an HMAC key (stored in AuthInfo struct)
3023*5ffb0c9bSToomas Soome extern mDNSs32 DNSDigest_ConstructHMACKeyfromBase64(DomainAuthInfo *info, const char *b64key);
30244b22b933Srs200217 
3025*5ffb0c9bSToomas Soome // sign a DNS message.  The message must be complete, with all values in network byte order.  end points to the end
30264b22b933Srs200217 // of the message, and is modified by this routine.  numAdditionals is a pointer to the number of additional
30274b22b933Srs200217 // records in HOST byte order, which is incremented upon successful completion of this routine.  The function returns
30284b22b933Srs200217 // the new end pointer on success, and NULL on failure.
3029*5ffb0c9bSToomas Soome extern void DNSDigest_SignMessage(DNSMessage *msg, mDNSu8 **end, DomainAuthInfo *info, mDNSu16 tcode);
3030*5ffb0c9bSToomas Soome 
3031*5ffb0c9bSToomas Soome #define SwapDNSHeaderBytes(M) do { \
3032*5ffb0c9bSToomas Soome     (M)->h.numQuestions   = (mDNSu16)((mDNSu8 *)&(M)->h.numQuestions  )[0] << 8 | ((mDNSu8 *)&(M)->h.numQuestions  )[1]; \
3033*5ffb0c9bSToomas Soome     (M)->h.numAnswers     = (mDNSu16)((mDNSu8 *)&(M)->h.numAnswers    )[0] << 8 | ((mDNSu8 *)&(M)->h.numAnswers    )[1]; \
3034*5ffb0c9bSToomas Soome     (M)->h.numAuthorities = (mDNSu16)((mDNSu8 *)&(M)->h.numAuthorities)[0] << 8 | ((mDNSu8 *)&(M)->h.numAuthorities)[1]; \
3035*5ffb0c9bSToomas Soome     (M)->h.numAdditionals = (mDNSu16)((mDNSu8 *)&(M)->h.numAdditionals)[0] << 8 | ((mDNSu8 *)&(M)->h.numAdditionals)[1]; \
3036*5ffb0c9bSToomas Soome } while (0)
3037*5ffb0c9bSToomas Soome 
3038*5ffb0c9bSToomas Soome #define DNSDigest_SignMessageHostByteOrder(M,E,INFO) \
3039*5ffb0c9bSToomas Soome     do { SwapDNSHeaderBytes(M); DNSDigest_SignMessage((M), (E), (INFO), 0); SwapDNSHeaderBytes(M); } while (0)
3040*5ffb0c9bSToomas Soome 
3041*5ffb0c9bSToomas Soome // verify a DNS message.  The message must be complete, with all values in network byte order.  end points to the
3042*5ffb0c9bSToomas Soome // end of the record.  tsig is a pointer to the resource record that contains the TSIG OPT record.  info is
3043*5ffb0c9bSToomas Soome // the matching key to use for verifying the message.  This function expects that the additionals member
3044*5ffb0c9bSToomas Soome // of the DNS message header has already had one subtracted from it.
3045*5ffb0c9bSToomas Soome extern mDNSBool DNSDigest_VerifyMessage(DNSMessage *msg, mDNSu8 *end, LargeCacheRecord *tsig, DomainAuthInfo *info, mDNSu16 *rcode, mDNSu16 *tcode);
30464b22b933Srs200217 
30474b22b933Srs200217 // ***************************************************************************
30484b22b933Srs200217 #if 0
3049*5ffb0c9bSToomas Soome #pragma mark -
30504b22b933Srs200217 #pragma mark - PlatformSupport interface
30514b22b933Srs200217 #endif
30524b22b933Srs200217 
30534b22b933Srs200217 // This section defines the interface to the Platform Support layer.
30544b22b933Srs200217 // Normal client code should not use any of types defined here, or directly call any of the functions defined here.
30554b22b933Srs200217 // The definitions are placed here because sometimes clients do use these calls indirectly, via other supported client operations.
30564b22b933Srs200217 // For example, AssignDomainName is a macro defined using mDNSPlatformMemCopy()
30574b22b933Srs200217 
30584b22b933Srs200217 // Every platform support module must provide the following functions.
30594b22b933Srs200217 // mDNSPlatformInit() typically opens a communication endpoint, and starts listening for mDNS packets.
30604b22b933Srs200217 // When Setup is complete, the platform support layer calls mDNSCoreInitComplete().
30614b22b933Srs200217 // mDNSPlatformSendUDP() sends one UDP packet
30624b22b933Srs200217 // When a packet is received, the PlatformSupport code calls mDNSCoreReceive()
30634b22b933Srs200217 // mDNSPlatformClose() tidies up on exit
30644b22b933Srs200217 //
30654b22b933Srs200217 // Note: mDNSPlatformMemAllocate/mDNSPlatformMemFree are only required for handling oversized resource records and unicast DNS.
30664b22b933Srs200217 // If your target platform has a well-defined specialized application, and you know that all the records it uses
30674b22b933Srs200217 // are InlineCacheRDSize or less, then you can just make a simple mDNSPlatformMemAllocate() stub that always returns
3068*5ffb0c9bSToomas Soome // NULL. InlineCacheRDSize is a compile-time constant, which is set by default to 68. If you need to handle records
30694b22b933Srs200217 // a little larger than this and you don't want to have to implement run-time allocation and freeing, then you
30704b22b933Srs200217 // can raise the value of this constant to a suitable value (at the expense of increased memory usage).
30714b22b933Srs200217 //
30724b22b933Srs200217 // USE CAUTION WHEN CALLING mDNSPlatformRawTime: The m->timenow_adjust correction factor needs to be added
30734b22b933Srs200217 // Generally speaking:
30744b22b933Srs200217 // Code that's protected by the main mDNS lock should just use the m->timenow value
30754b22b933Srs200217 // Code outside the main mDNS lock should use mDNS_TimeNow(m) to get properly adjusted time
30764b22b933Srs200217 // In certain cases there may be reasons why it's necessary to get the time without taking the lock first
30774b22b933Srs200217 // (e.g. inside the routines that are doing the locking and unlocking, where a call to get the lock would result in a
30784b22b933Srs200217 // recursive loop); in these cases use mDNS_TimeNow_NoLock(m) to get mDNSPlatformRawTime with the proper correction factor added.
30794b22b933Srs200217 //
30804b22b933Srs200217 // mDNSPlatformUTC returns the time, in seconds, since Jan 1st 1970 UTC and is required for generating TSIG records
30814b22b933Srs200217 
30824b22b933Srs200217 extern mStatus  mDNSPlatformInit        (mDNS *const m);
30834b22b933Srs200217 extern void     mDNSPlatformClose       (mDNS *const m);
30844b22b933Srs200217 extern mStatus  mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end,
3085*5ffb0c9bSToomas Soome                                     mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst,
3086*5ffb0c9bSToomas Soome                                     mDNSIPPort dstport, mDNSBool useBackgroundTrafficClass);
30874b22b933Srs200217 
3088*5ffb0c9bSToomas Soome extern mDNSBool mDNSPlatformPeekUDP     (mDNS *const m, UDPSocket *src);
30894b22b933Srs200217 extern void     mDNSPlatformLock        (const mDNS *const m);
30904b22b933Srs200217 extern void     mDNSPlatformUnlock      (const mDNS *const m);
30914b22b933Srs200217 
3092*5ffb0c9bSToomas Soome extern void     mDNSPlatformStrCopy     (      void *dst, const void *src);
30934b22b933Srs200217 extern mDNSu32  mDNSPlatformStrLen      (                 const void *src);
3094*5ffb0c9bSToomas Soome extern void     mDNSPlatformMemCopy     (      void *dst, const void *src, mDNSu32 len);
3095*5ffb0c9bSToomas Soome extern mDNSBool mDNSPlatformMemSame     (const void *dst, const void *src, mDNSu32 len);
3096*5ffb0c9bSToomas Soome extern int      mDNSPlatformMemCmp      (const void *dst, const void *src, mDNSu32 len);
30974b22b933Srs200217 extern void     mDNSPlatformMemZero     (      void *dst,                  mDNSu32 len);
3098*5ffb0c9bSToomas Soome extern void mDNSPlatformQsort       (void *base, int nel, int width, int (*compar)(const void *, const void *));
3099*5ffb0c9bSToomas Soome #if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING
3100*5ffb0c9bSToomas Soome #define         mDNSPlatformMemAllocate(X) mallocL(# X, X)
3101*5ffb0c9bSToomas Soome #else
31024b22b933Srs200217 extern void *   mDNSPlatformMemAllocate (mDNSu32 len);
3103*5ffb0c9bSToomas Soome #endif
31044b22b933Srs200217 extern void     mDNSPlatformMemFree     (void *mem);
3105*5ffb0c9bSToomas Soome 
3106*5ffb0c9bSToomas Soome // If the platform doesn't have a strong PRNG, we define a naive multiply-and-add based on a seed
3107*5ffb0c9bSToomas Soome // from the platform layer.  Long-term, we should embed an arc4 implementation, but the strength
3108*5ffb0c9bSToomas Soome // will still depend on the randomness of the seed.
3109*5ffb0c9bSToomas Soome #if !defined(_PLATFORM_HAS_STRONG_PRNG_) && (_BUILDING_XCODE_PROJECT_ || defined(_WIN32))
3110*5ffb0c9bSToomas Soome #define _PLATFORM_HAS_STRONG_PRNG_ 1
3111*5ffb0c9bSToomas Soome #endif
3112*5ffb0c9bSToomas Soome #if _PLATFORM_HAS_STRONG_PRNG_
3113*5ffb0c9bSToomas Soome extern mDNSu32  mDNSPlatformRandomNumber(void);
3114*5ffb0c9bSToomas Soome #else
31154b22b933Srs200217 extern mDNSu32  mDNSPlatformRandomSeed  (void);
3116*5ffb0c9bSToomas Soome #endif // _PLATFORM_HAS_STRONG_PRNG_
3117*5ffb0c9bSToomas Soome 
31184b22b933Srs200217 extern mStatus  mDNSPlatformTimeInit    (void);
31194b22b933Srs200217 extern mDNSs32  mDNSPlatformRawTime     (void);
31204b22b933Srs200217 extern mDNSs32  mDNSPlatformUTC         (void);
3121*5ffb0c9bSToomas Soome #define mDNS_TimeNow_NoLock(m) (mDNSPlatformRawTime() + (m)->timenow_adjust)
3122*5ffb0c9bSToomas Soome 
3123*5ffb0c9bSToomas Soome #if MDNS_DEBUGMSGS
3124*5ffb0c9bSToomas Soome extern void mDNSPlatformWriteDebugMsg(const char *msg);
3125*5ffb0c9bSToomas Soome #endif
3126*5ffb0c9bSToomas Soome extern void mDNSPlatformWriteLogMsg(const char *ident, const char *msg, mDNSLogLevel_t loglevel);
3127*5ffb0c9bSToomas Soome 
3128*5ffb0c9bSToomas Soome #if APPLE_OSX_mDNSResponder
3129*5ffb0c9bSToomas Soome // Utility function for ASL logging
3130*5ffb0c9bSToomas Soome mDNSexport void mDNSASLLog(uuid_t *uuid, const char *subdomain, const char *result, const char *signature, const char *fmt, ...);
3131*5ffb0c9bSToomas Soome 
3132*5ffb0c9bSToomas Soome // Log unicast and multicast traffic statistics once a day. Also used for DNSSEC statistics.
3133*5ffb0c9bSToomas Soome #define kDefaultNextStatsticsLogTime (24 * 60 * 60)
3134*5ffb0c9bSToomas Soome 
3135*5ffb0c9bSToomas Soome extern void mDNSLogStatistics(mDNS *const m);
3136*5ffb0c9bSToomas Soome 
3137*5ffb0c9bSToomas Soome #endif // APPLE_OSX_mDNSResponder
31384b22b933Srs200217 
31394b22b933Srs200217 // Platform support modules should provide the following functions to map between opaque interface IDs
31404b22b933Srs200217 // and interface indexes in order to support the DNS-SD API. If your target platform does not support
31414b22b933Srs200217 // multiple interfaces and/or does not support the DNS-SD API, these functions can be empty.
3142*5ffb0c9bSToomas Soome extern mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 ifindex);
3143*5ffb0c9bSToomas Soome extern mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id, mDNSBool suppressNetworkChange);
31444b22b933Srs200217 
31454b22b933Srs200217 // Every platform support module must provide the following functions if it is to support unicast DNS
31464b22b933Srs200217 // and Dynamic Update.
31474b22b933Srs200217 // All TCP socket operations implemented by the platform layer MUST NOT BLOCK.
31484b22b933Srs200217 // mDNSPlatformTCPConnect initiates a TCP connection with a peer, adding the socket descriptor to the
31494b22b933Srs200217 // main event loop.  The return value indicates whether the connection succeeded, failed, or is pending
31504b22b933Srs200217 // (i.e. the call would block.)  On return, the descriptor parameter is set to point to the connected socket.
31514b22b933Srs200217 // The TCPConnectionCallback is subsequently invoked when the connection
31524b22b933Srs200217 // completes (in which case the ConnectionEstablished parameter is true), or data is available for
31534b22b933Srs200217 // reading on the socket (indicated by the ConnectionEstablished parameter being false.)  If the connection
31544b22b933Srs200217 // asynchronously fails, the TCPConnectionCallback should be invoked as usual, with the error being
31554b22b933Srs200217 // returned in subsequent calls to PlatformReadTCP or PlatformWriteTCP.  (This allows for platforms
31564b22b933Srs200217 // with limited asynchronous error detection capabilities.)  PlatformReadTCP and PlatformWriteTCP must
3157*5ffb0c9bSToomas Soome // return the number of bytes read/written, 0 if the call would block, and -1 if an error.  PlatformReadTCP
3158*5ffb0c9bSToomas Soome // should set the closed argument if the socket has been closed.
31594b22b933Srs200217 // PlatformTCPCloseConnection must close the connection to the peer and remove the descriptor from the
31604b22b933Srs200217 // event loop.  CloseConnectin may be called at any time, including in a ConnectionCallback.
31614b22b933Srs200217 
3162*5ffb0c9bSToomas Soome typedef enum
3163*5ffb0c9bSToomas Soome {
3164*5ffb0c9bSToomas Soome     kTCPSocketFlags_Zero   = 0,
3165*5ffb0c9bSToomas Soome     kTCPSocketFlags_UseTLS = (1 << 0)
3166*5ffb0c9bSToomas Soome } TCPSocketFlags;
3167*5ffb0c9bSToomas Soome 
3168*5ffb0c9bSToomas Soome typedef void (*TCPConnectionCallback)(TCPSocket *sock, void *context, mDNSBool ConnectionEstablished, mStatus err);
3169*5ffb0c9bSToomas Soome extern TCPSocket *mDNSPlatformTCPSocket(mDNS *const m, TCPSocketFlags flags, mDNSIPPort *port, mDNSBool useBackgroundTrafficClass); // creates a TCP socket
3170*5ffb0c9bSToomas Soome extern TCPSocket *mDNSPlatformTCPAccept(TCPSocketFlags flags, int sd);
3171*5ffb0c9bSToomas Soome extern int        mDNSPlatformTCPGetFD(TCPSocket *sock);
3172*5ffb0c9bSToomas Soome extern mStatus    mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, mDNSOpaque16 dstport, domainname *hostname,
3173*5ffb0c9bSToomas Soome                                          mDNSInterfaceID InterfaceID, TCPConnectionCallback callback, void *context);
3174*5ffb0c9bSToomas Soome extern void       mDNSPlatformTCPCloseConnection(TCPSocket *sock);
3175*5ffb0c9bSToomas Soome extern long       mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool *closed);
3176*5ffb0c9bSToomas Soome extern long       mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned long len);
3177*5ffb0c9bSToomas Soome extern UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requestedport);
3178*5ffb0c9bSToomas Soome extern mDNSu16    mDNSPlatformGetUDPPort(UDPSocket *sock);
3179*5ffb0c9bSToomas Soome extern void       mDNSPlatformUDPClose(UDPSocket *sock);
3180*5ffb0c9bSToomas Soome extern void       mDNSPlatformReceiveBPF_fd(mDNS *const m, int fd);
3181*5ffb0c9bSToomas Soome extern void       mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID);
3182*5ffb0c9bSToomas Soome extern void       mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID);
3183*5ffb0c9bSToomas Soome extern void       mDNSPlatformSetLocalAddressCacheEntry(mDNS *const m, const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID);
3184*5ffb0c9bSToomas Soome extern void       mDNSPlatformSourceAddrForDest(mDNSAddr *const src, const mDNSAddr *const dst);
3185*5ffb0c9bSToomas Soome extern void       mDNSPlatformSendKeepalive(mDNSAddr *sadd, mDNSAddr *dadd, mDNSIPPort *lport, mDNSIPPort *rport, mDNSu32 seq, mDNSu32 ack, mDNSu16 win);
3186*5ffb0c9bSToomas Soome extern mStatus    mDNSPlatformRetrieveTCPInfo(mDNS *const m, mDNSAddr *laddr, mDNSIPPort *lport, mDNSAddr *raddr,  mDNSIPPort *rport, mDNSTCPInfo *mti);
3187*5ffb0c9bSToomas Soome extern mStatus    mDNSPlatformGetRemoteMacAddr(mDNS *const m, mDNSAddr *raddr);
3188*5ffb0c9bSToomas Soome extern mStatus    mDNSPlatformStoreSPSMACAddr(mDNSAddr *spsaddr, char *ifname);
3189*5ffb0c9bSToomas Soome extern mStatus    mDNSPlatformClearSPSMACAddr(void);
3190*5ffb0c9bSToomas Soome 
3191*5ffb0c9bSToomas Soome // mDNSPlatformTLSSetupCerts/mDNSPlatformTLSTearDownCerts used by dnsextd
3192*5ffb0c9bSToomas Soome extern mStatus    mDNSPlatformTLSSetupCerts(void);
3193*5ffb0c9bSToomas Soome extern void       mDNSPlatformTLSTearDownCerts(void);
31944b22b933Srs200217 
31954b22b933Srs200217 // Platforms that support unicast browsing and dynamic update registration for clients who do not specify a domain
31964b22b933Srs200217 // in browse/registration calls must implement these routines to get the "default" browse/registration list.
31974b22b933Srs200217 
3198*5ffb0c9bSToomas Soome extern mDNSBool   mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **RegDomains,
3199*5ffb0c9bSToomas Soome                         DNameListElem **BrowseDomains, mDNSBool ackConfig);
3200*5ffb0c9bSToomas Soome extern mStatus    mDNSPlatformGetPrimaryInterface(mDNS *const m, mDNSAddr *v4, mDNSAddr *v6, mDNSAddr *router);
3201*5ffb0c9bSToomas Soome extern void       mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status);
32024b22b933Srs200217 
3203*5ffb0c9bSToomas Soome extern void       mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep, const char *reason);
3204*5ffb0c9bSToomas Soome extern void       mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration);
32054b22b933Srs200217 
3206*5ffb0c9bSToomas Soome extern mDNSBool   mDNSPlatformInterfaceIsD2D(mDNSInterfaceID InterfaceID);
3207*5ffb0c9bSToomas Soome extern mDNSBool   mDNSPlatformInterfaceIsAWDL(const NetworkInterfaceInfo *intf);
3208*5ffb0c9bSToomas Soome extern mDNSBool   mDNSPlatformValidRecordForQuestion(const ResourceRecord *const rr, const DNSQuestion *const q);
3209*5ffb0c9bSToomas Soome extern mDNSBool   mDNSPlatformValidRecordForInterface(AuthRecord *rr, const NetworkInterfaceInfo *intf);
3210*5ffb0c9bSToomas Soome extern mDNSBool   mDNSPlatformValidQuestionForInterface(DNSQuestion *q, const NetworkInterfaceInfo *intf);
3211*5ffb0c9bSToomas Soome 
3212*5ffb0c9bSToomas Soome extern void mDNSPlatformFormatTime(unsigned long t, mDNSu8 *buf, int bufsize);
32134b22b933Srs200217 
32144b22b933Srs200217 #ifdef _LEGACY_NAT_TRAVERSAL_
32154b22b933Srs200217 // Support for legacy NAT traversal protocols, implemented by the platform layer and callable by the core.
3216*5ffb0c9bSToomas Soome extern void     LNT_SendDiscoveryMsg(mDNS *m);
3217*5ffb0c9bSToomas Soome extern void     LNT_ConfigureRouterInfo(mDNS *m, const mDNSInterfaceID InterfaceID, const mDNSu8 *const data, const mDNSu16 len);
3218*5ffb0c9bSToomas Soome extern mStatus  LNT_GetExternalAddress(mDNS *m);
3219*5ffb0c9bSToomas Soome extern mStatus  LNT_MapPort(mDNS *m, NATTraversalInfo *const n);
3220*5ffb0c9bSToomas Soome extern mStatus  LNT_UnmapPort(mDNS *m, NATTraversalInfo *const n);
3221*5ffb0c9bSToomas Soome extern void     LNT_ClearState(mDNS *const m);
32224b22b933Srs200217 #endif // _LEGACY_NAT_TRAVERSAL_
32234b22b933Srs200217 
32244b22b933Srs200217 // The core mDNS code provides these functions, for the platform support code to call at appropriate times
32254b22b933Srs200217 //
32264b22b933Srs200217 // mDNS_SetFQDN() is called once on startup (typically from mDNSPlatformInit())
32274b22b933Srs200217 // and then again on each subsequent change of the host name.
32284b22b933Srs200217 //
32294b22b933Srs200217 // mDNS_RegisterInterface() is used by the platform support layer to inform mDNSCore of what
32304b22b933Srs200217 // physical and/or logical interfaces are available for sending and receiving packets.
32314b22b933Srs200217 // Typically it is called on startup for each available interface, but register/deregister may be
32324b22b933Srs200217 // called again later, on multiple occasions, to inform the core of interface configuration changes.
32334b22b933Srs200217 // If set->Advertise is set non-zero, then mDNS_RegisterInterface() also registers the standard
32344b22b933Srs200217 // resource records that should be associated with every publicised IP address/interface:
32354b22b933Srs200217 // -- Name-to-address records (A/AAAA)
32364b22b933Srs200217 // -- Address-to-name records (PTR)
32374b22b933Srs200217 // -- Host information (HINFO)
32384b22b933Srs200217 // IMPORTANT: The specified mDNSInterfaceID MUST NOT be 0, -1, or -2; these values have special meaning
32394b22b933Srs200217 // mDNS_RegisterInterface does not result in the registration of global hostnames via dynamic update -
32404b22b933Srs200217 // see mDNS_SetPrimaryInterfaceInfo, mDNS_AddDynDNSHostName, etc. for this purpose.
32414b22b933Srs200217 // Note that the set may be deallocated immediately after it is deregistered via mDNS_DeegisterInterface.
32424b22b933Srs200217 //
32434b22b933Srs200217 // mDNS_RegisterDNS() is used by the platform support layer to provide the core with the addresses of
32444b22b933Srs200217 // available domain name servers for unicast queries/updates.  RegisterDNS() should be called once for
32454b22b933Srs200217 // each name server, typically at startup, or when a new name server becomes available.  DeregiterDNS()
32464b22b933Srs200217 // must be called whenever a registered name server becomes unavailable.  DeregisterDNSList deregisters
32474b22b933Srs200217 // all registered servers.  mDNS_DNSRegistered() returns true if one or more servers are registered in the core.
32484b22b933Srs200217 //
32494b22b933Srs200217 // mDNSCoreInitComplete() is called when the platform support layer is finished.
32504b22b933Srs200217 // Typically this is at the end of mDNSPlatformInit(), but may be later
32514b22b933Srs200217 // (on platforms like OT that allow asynchronous initialization of the networking stack).
32524b22b933Srs200217 //
32534b22b933Srs200217 // mDNSCoreReceive() is called when a UDP packet is received
32544b22b933Srs200217 //
32554b22b933Srs200217 // mDNSCoreMachineSleep() is called when the machine sleeps or wakes
32564b22b933Srs200217 // (This refers to heavyweight laptop-style sleep/wake that disables network access,
32574b22b933Srs200217 // not lightweight second-by-second CPU power management modes.)
32584b22b933Srs200217 
32594b22b933Srs200217 extern void     mDNS_SetFQDN(mDNS *const m);
3260*5ffb0c9bSToomas Soome extern void     mDNS_ActivateNetWake_internal  (mDNS *const m, NetworkInterfaceInfo *set);
3261*5ffb0c9bSToomas Soome extern void     mDNS_DeactivateNetWake_internal(mDNS *const m, NetworkInterfaceInfo *set);
32624b22b933Srs200217 extern mStatus  mDNS_RegisterInterface  (mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping);
32634b22b933Srs200217 extern void     mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping);
32644b22b933Srs200217 extern void     mDNSCoreInitComplete(mDNS *const m, mStatus result);
32654b22b933Srs200217 extern void     mDNSCoreReceive(mDNS *const m, void *const msg, const mDNSu8 *const end,
32664b22b933Srs200217                                 const mDNSAddr *const srcaddr, const mDNSIPPort srcport,
3267*5ffb0c9bSToomas Soome                                 const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID);
3268*5ffb0c9bSToomas Soome extern void     mDNSCoreRestartQueries(mDNS *const m);
3269*5ffb0c9bSToomas Soome extern void     mDNSCoreRestartQuestion(mDNS *const m, DNSQuestion *q);
3270*5ffb0c9bSToomas Soome extern void     mDNSCoreRestartRegistration(mDNS *const m, AuthRecord  *rr, int announceCount);
3271*5ffb0c9bSToomas Soome typedef void (*FlushCache)(mDNS *const m);
3272*5ffb0c9bSToomas Soome typedef void (*CallbackBeforeStartQuery)(mDNS *const m, void *context);
3273*5ffb0c9bSToomas Soome extern void     mDNSCoreRestartAddressQueries(mDNS *const m, mDNSBool SearchDomainsChanged, FlushCache flushCacheRecords,
3274*5ffb0c9bSToomas Soome                                               CallbackBeforeStartQuery beforeQueryStart, void *context);
3275*5ffb0c9bSToomas Soome extern mDNSBool mDNSCoreHaveAdvertisedMulticastServices(mDNS *const m);
32764b22b933Srs200217 extern void     mDNSCoreMachineSleep(mDNS *const m, mDNSBool wake);
3277*5ffb0c9bSToomas Soome extern mDNSBool mDNSCoreReadyForSleep(mDNS *m, mDNSs32 now);
3278*5ffb0c9bSToomas Soome extern mDNSs32  mDNSCoreIntervalToNextWake(mDNS *const m, mDNSs32 now);
3279*5ffb0c9bSToomas Soome 
3280*5ffb0c9bSToomas Soome extern void     mDNSCoreReceiveRawPacket  (mDNS *const m, const mDNSu8 *const p, const mDNSu8 *const end, const mDNSInterfaceID InterfaceID);
32814b22b933Srs200217 
32824b22b933Srs200217 extern mDNSBool mDNSAddrIsDNSMulticast(const mDNSAddr *ip);
32834b22b933Srs200217 
3284*5ffb0c9bSToomas Soome extern CacheRecord *CreateNewCacheEntry(mDNS *const m, const mDNSu32 slot, CacheGroup *cg, mDNSs32 delay, mDNSBool Add, const mDNSAddr *sourceAddress);
3285*5ffb0c9bSToomas Soome extern CacheGroup *CacheGroupForName(const mDNS *const m, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name);
3286*5ffb0c9bSToomas Soome extern void ReleaseCacheRecord(mDNS *const m, CacheRecord *r);
3287*5ffb0c9bSToomas Soome extern void ScheduleNextCacheCheckTime(mDNS *const m, const mDNSu32 slot, const mDNSs32 event);
3288*5ffb0c9bSToomas Soome extern void SetNextCacheCheckTimeForRecord(mDNS *const m, CacheRecord *const rr);
3289*5ffb0c9bSToomas Soome extern void GrantCacheExtensions(mDNS *const m, DNSQuestion *q, mDNSu32 lease);
3290*5ffb0c9bSToomas Soome extern void MakeNegativeCacheRecord(mDNS *const m, CacheRecord *const cr,
3291*5ffb0c9bSToomas Soome                                     const domainname *const name, const mDNSu32 namehash, const mDNSu16 rrtype, const mDNSu16 rrclass, mDNSu32 ttl_seconds,
3292*5ffb0c9bSToomas Soome                                     mDNSInterfaceID InterfaceID, DNSServer *dnsserver);
3293*5ffb0c9bSToomas Soome extern void CompleteDeregistration(mDNS *const m, AuthRecord *rr);
3294*5ffb0c9bSToomas Soome extern void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheRecord *const rr, const QC_result AddRecord);
3295*5ffb0c9bSToomas Soome extern void AnswerQuestionByFollowingCNAME(mDNS *const m, DNSQuestion *q, ResourceRecord *rr);
3296*5ffb0c9bSToomas Soome extern char *InterfaceNameForID(mDNS *const m, const mDNSInterfaceID InterfaceID);
3297*5ffb0c9bSToomas Soome extern void DNSServerChangeForQuestion(mDNS *const m, DNSQuestion *q, DNSServer *newServer);
3298*5ffb0c9bSToomas Soome extern void ActivateUnicastRegistration(mDNS *const m, AuthRecord *const rr);
3299*5ffb0c9bSToomas Soome extern void CheckSuppressUnusableQuestions(mDNS *const m);
3300*5ffb0c9bSToomas Soome extern void RetrySearchDomainQuestions(mDNS *const m);
3301*5ffb0c9bSToomas Soome extern mDNSBool DomainEnumQuery(const domainname *qname);
3302*5ffb0c9bSToomas Soome extern mStatus UpdateKeepaliveRData(mDNS *const m, AuthRecord *rr, NetworkInterfaceInfo *const intf, mDNSBool updateMac, char *ethAddr);
3303*5ffb0c9bSToomas Soome extern void  UpdateKeepaliveRMACAsync(mDNS *const m, void *context);
3304*5ffb0c9bSToomas Soome extern void UpdateRMACCallback(mDNS *const m, void *context);
3305*5ffb0c9bSToomas Soome 
3306*5ffb0c9bSToomas Soome // Used only in logging to restrict the number of /etc/hosts entries printed
3307*5ffb0c9bSToomas Soome extern void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result);
3308*5ffb0c9bSToomas Soome // exported for using the hash for /etc/hosts AuthRecords
3309*5ffb0c9bSToomas Soome extern AuthGroup *AuthGroupForName(AuthHash *r, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name);
3310*5ffb0c9bSToomas Soome extern AuthGroup *AuthGroupForRecord(AuthHash *r, const mDNSu32 slot, const ResourceRecord *const rr);
3311*5ffb0c9bSToomas Soome extern AuthGroup *InsertAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr);
3312*5ffb0c9bSToomas Soome extern AuthGroup *RemoveAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr);
3313*5ffb0c9bSToomas Soome extern mDNSBool mDNS_CheckForCacheRecord(mDNS *const m, DNSQuestion *q, mDNSu16 qtype);
3314*5ffb0c9bSToomas Soome 
3315*5ffb0c9bSToomas Soome // For now this AutoTunnel stuff is specific to Mac OS X.
3316*5ffb0c9bSToomas Soome // In the future, if there's demand, we may see if we can abstract it out cleanly into the platform layer
3317*5ffb0c9bSToomas Soome #if APPLE_OSX_mDNSResponder
3318*5ffb0c9bSToomas Soome extern void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord);
3319*5ffb0c9bSToomas Soome extern void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q);
3320*5ffb0c9bSToomas Soome extern void StartServerTunnel(mDNS *const m, DomainAuthInfo *const info);
3321*5ffb0c9bSToomas Soome extern void UpdateAutoTunnelDomainStatuses(const mDNS *const m);
3322*5ffb0c9bSToomas Soome extern void RemoveAutoTunnel6Record(mDNS *const m);
3323*5ffb0c9bSToomas Soome extern mDNSBool RecordReadyForSleep(mDNS *const m, AuthRecord *rr);
3324*5ffb0c9bSToomas Soome // For now this LocalSleepProxy stuff is specific to Mac OS X.
3325*5ffb0c9bSToomas Soome // In the future, if there's demand, we may see if we can abstract it out cleanly into the platform layer
3326*5ffb0c9bSToomas Soome extern mStatus ActivateLocalProxy(mDNS *const m, NetworkInterfaceInfo *const intf);
3327*5ffb0c9bSToomas Soome extern void mDNSPlatformUpdateDNSStatus(mDNS *const m, DNSQuestion *q);
3328*5ffb0c9bSToomas Soome extern void mDNSPlatformTriggerDNSRetry(mDNS *const m, DNSQuestion *v4q, DNSQuestion *v6q);
3329*5ffb0c9bSToomas Soome extern void mDNSPlatformLogToFile(int log_level, const char *buffer);
3330*5ffb0c9bSToomas Soome extern mDNSBool SupportsInNICProxy(NetworkInterfaceInfo *const intf);
3331*5ffb0c9bSToomas Soome #endif
3332*5ffb0c9bSToomas Soome 
3333*5ffb0c9bSToomas Soome typedef void ProxyCallback (mDNS *const m, void *socket, void *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr,
3334*5ffb0c9bSToomas Soome     const mDNSIPPort srcport, const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, void *context);
3335*5ffb0c9bSToomas Soome extern void mDNSPlatformInitDNSProxySkts(mDNS *const m, ProxyCallback *UDPCallback, ProxyCallback *TCPCallback);
3336*5ffb0c9bSToomas Soome extern void mDNSPlatformCloseDNSProxySkts(mDNS *const m);
3337*5ffb0c9bSToomas Soome extern void mDNSPlatformDisposeProxyContext(void *context);
3338*5ffb0c9bSToomas Soome extern mDNSu8 *DNSProxySetAttributes(DNSQuestion *q, DNSMessageHeader *h, DNSMessage *msg, mDNSu8 *start, mDNSu8 *limit);
3339*5ffb0c9bSToomas Soome 
3340*5ffb0c9bSToomas Soome // Sleep Assertions are specific to Mac OS X
3341*5ffb0c9bSToomas Soome #if APPLE_OSX_mDNSResponder
3342*5ffb0c9bSToomas Soome extern void mDNSPlatformSleepAssertion(mDNS *const m, double timeout);
3343*5ffb0c9bSToomas Soome #endif
3344*5ffb0c9bSToomas Soome 
3345*5ffb0c9bSToomas Soome extern mDNSBool mDNSPlatformAllowPID(mDNS *const m, DNSQuestion *q);
3346*5ffb0c9bSToomas Soome extern mDNSs32 mDNSPlatformGetServiceID(mDNS *const m, DNSQuestion *q);
3347*5ffb0c9bSToomas Soome extern void mDNSPlatformSetuDNSSocktOpt(UDPSocket *src, const mDNSAddr *dst, DNSQuestion *q);
3348*5ffb0c9bSToomas Soome extern mDNSs32 mDNSPlatformGetPID(void);
3349*5ffb0c9bSToomas Soome 
33504b22b933Srs200217 // ***************************************************************************
33514b22b933Srs200217 #if 0
3352*5ffb0c9bSToomas Soome #pragma mark -
3353*5ffb0c9bSToomas Soome #pragma mark - Sleep Proxy
3354*5ffb0c9bSToomas Soome #endif
3355*5ffb0c9bSToomas Soome 
3356*5ffb0c9bSToomas Soome // Sleep Proxy Server Property Encoding
3357*5ffb0c9bSToomas Soome //
3358*5ffb0c9bSToomas Soome // Sleep Proxy Servers are advertised using a structured service name, consisting of four
3359*5ffb0c9bSToomas Soome // metrics followed by a human-readable name. The metrics assist clients in deciding which
3360*5ffb0c9bSToomas Soome // Sleep Proxy Server(s) to use when multiple are available on the network. Each metric
3361*5ffb0c9bSToomas Soome // is a two-digit decimal number in the range 10-99. Lower metrics are generally better.
3362*5ffb0c9bSToomas Soome //
3363*5ffb0c9bSToomas Soome //   AA-BB-CC-DD.FF Name
3364*5ffb0c9bSToomas Soome //
3365*5ffb0c9bSToomas Soome // Metrics:
3366*5ffb0c9bSToomas Soome //
3367*5ffb0c9bSToomas Soome // AA = Intent
3368*5ffb0c9bSToomas Soome // BB = Portability
3369*5ffb0c9bSToomas Soome // CC = Marginal Power
3370*5ffb0c9bSToomas Soome // DD = Total Power
3371*5ffb0c9bSToomas Soome // FF = Features Supported (Currently TCP Keepalive only)
3372*5ffb0c9bSToomas Soome //
3373*5ffb0c9bSToomas Soome //
3374*5ffb0c9bSToomas Soome // ** Intent Metric **
3375*5ffb0c9bSToomas Soome //
3376*5ffb0c9bSToomas Soome // 20 = Dedicated Sleep Proxy Server -- a device, permanently powered on,
3377*5ffb0c9bSToomas Soome //      installed for the express purpose of providing Sleep Proxy Service.
3378*5ffb0c9bSToomas Soome //
3379*5ffb0c9bSToomas Soome // 30 = Primary Network Infrastructure Hardware -- a router, DHCP server, NAT gateway,
3380*5ffb0c9bSToomas Soome //      or similar permanently installed device which is permanently powered on.
3381*5ffb0c9bSToomas Soome //      This is hardware designed for the express purpose of being network
3382*5ffb0c9bSToomas Soome //      infrastructure, and for most home users is typically a single point
3383*5ffb0c9bSToomas Soome //      of failure for the local network -- e.g. most home users only have
3384*5ffb0c9bSToomas Soome //      a single NAT gateway / DHCP server. Even though in principle the
3385*5ffb0c9bSToomas Soome //      hardware might technically be capable of running different software,
3386*5ffb0c9bSToomas Soome //      a typical user is unlikely to do that. e.g. AirPort base station.
3387*5ffb0c9bSToomas Soome //
3388*5ffb0c9bSToomas Soome // 40 = Primary Network Infrastructure Software -- a general-purpose computer
3389*5ffb0c9bSToomas Soome //      (e.g. Mac, Windows, Linux, etc.) which is currently running DHCP server
3390*5ffb0c9bSToomas Soome //      or NAT gateway software, but the user could choose to turn that off
3391*5ffb0c9bSToomas Soome //      fairly easily. e.g. iMac running Internet Sharing
3392*5ffb0c9bSToomas Soome //
3393*5ffb0c9bSToomas Soome // 50 = Secondary Network Infrastructure Hardware -- like primary infrastructure
3394*5ffb0c9bSToomas Soome //      hardware, except not a single point of failure for the entire local network.
3395*5ffb0c9bSToomas Soome //      For example, an AirPort base station in bridge mode. This may have clients
3396*5ffb0c9bSToomas Soome //      associated with it, and if it goes away those clients will be inconvenienced,
3397*5ffb0c9bSToomas Soome //      but unlike the NAT gateway / DHCP server, the entire local network is not
3398*5ffb0c9bSToomas Soome //      dependent on it.
3399*5ffb0c9bSToomas Soome //
3400*5ffb0c9bSToomas Soome // 60 = Secondary Network Infrastructure Software -- like 50, but in a general-
3401*5ffb0c9bSToomas Soome //      purpose CPU.
3402*5ffb0c9bSToomas Soome //
3403*5ffb0c9bSToomas Soome // 70 = Incidentally Available Hardware -- a device which has no power switch
3404*5ffb0c9bSToomas Soome //      and is generally left powered on all the time. Even though it is not a
3405*5ffb0c9bSToomas Soome //      part of what we conventionally consider network infrastructure (router,
3406*5ffb0c9bSToomas Soome //      DHCP, NAT, DNS, etc.), and the rest of the network can operate fine
3407*5ffb0c9bSToomas Soome //      without it, since it's available and unlikely to be turned off, it is a
3408*5ffb0c9bSToomas Soome //      reasonable candidate for providing Sleep Proxy Service e.g. Apple TV,
3409*5ffb0c9bSToomas Soome //      or an AirPort base station in client mode, associated with an existing
3410*5ffb0c9bSToomas Soome //      wireless network (e.g. AirPort Express connected to a music system, or
3411*5ffb0c9bSToomas Soome //      being used to share a USB printer).
3412*5ffb0c9bSToomas Soome //
3413*5ffb0c9bSToomas Soome // 80 = Incidentally Available Software -- a general-purpose computer which
3414*5ffb0c9bSToomas Soome //      happens at this time to be set to "never sleep", and as such could be
3415*5ffb0c9bSToomas Soome //      useful as a Sleep Proxy Server, but has not been intentionally provided
3416*5ffb0c9bSToomas Soome //      for this purpose. Of all the Intent Metric categories this is the
3417*5ffb0c9bSToomas Soome //      one most likely to be shut down or put to sleep without warning.
3418*5ffb0c9bSToomas Soome //      However, if nothing else is availalable, it may be better than nothing.
3419*5ffb0c9bSToomas Soome //      e.g. Office computer in the workplace which has been set to "never sleep"
3420*5ffb0c9bSToomas Soome //
3421*5ffb0c9bSToomas Soome //
3422*5ffb0c9bSToomas Soome // ** Portability Metric **
3423*5ffb0c9bSToomas Soome //
3424*5ffb0c9bSToomas Soome // Inversely related to mass of device, on the basis that, all other things
3425*5ffb0c9bSToomas Soome // being equal, heavier devices are less likely to be moved than lighter devices.
3426*5ffb0c9bSToomas Soome // E.g. A MacBook running Internet Sharing is probably more likely to be
3427*5ffb0c9bSToomas Soome // put to sleep and taken away than a Mac Pro running Internet Sharing.
3428*5ffb0c9bSToomas Soome // The Portability Metric is a logarithmic decibel scale, computed by taking the
3429*5ffb0c9bSToomas Soome // (approximate) mass of the device in milligrammes, taking the base 10 logarithm
3430*5ffb0c9bSToomas Soome // of that, multiplying by 10, and subtracting the result from 100:
3431*5ffb0c9bSToomas Soome //
3432*5ffb0c9bSToomas Soome //   Portability Metric = 100 - (log10(mg) * 10)
3433*5ffb0c9bSToomas Soome //
3434*5ffb0c9bSToomas Soome // The Portability Metric is not necessarily computed literally from the actual
3435*5ffb0c9bSToomas Soome // mass of the device; the intent is just that lower numbers indicate more
3436*5ffb0c9bSToomas Soome // permanent devices, and higher numbers indicate devices more likely to be
3437*5ffb0c9bSToomas Soome // removed from the network, e.g., in order of increasing portability:
3438*5ffb0c9bSToomas Soome //
3439*5ffb0c9bSToomas Soome // Mac Pro < iMac < Laptop < iPhone
3440*5ffb0c9bSToomas Soome //
3441*5ffb0c9bSToomas Soome // Example values:
3442*5ffb0c9bSToomas Soome //
3443*5ffb0c9bSToomas Soome // 10 = 1 metric tonne
3444*5ffb0c9bSToomas Soome // 40 = 1kg
3445*5ffb0c9bSToomas Soome // 70 = 1g
3446*5ffb0c9bSToomas Soome // 90 = 10mg
3447*5ffb0c9bSToomas Soome //
3448*5ffb0c9bSToomas Soome //
3449*5ffb0c9bSToomas Soome // ** Marginal Power and Total Power Metrics **
3450*5ffb0c9bSToomas Soome //
3451*5ffb0c9bSToomas Soome // The Marginal Power Metric is the power difference between sleeping and staying awake
3452*5ffb0c9bSToomas Soome // to be a Sleep Proxy Server.
3453*5ffb0c9bSToomas Soome //
3454*5ffb0c9bSToomas Soome // The Total Power Metric is the total power consumption when being Sleep Proxy Server.
3455*5ffb0c9bSToomas Soome //
3456*5ffb0c9bSToomas Soome // The Power Metrics use a logarithmic decibel scale, computed as ten times the
3457*5ffb0c9bSToomas Soome // base 10 logarithm of the (approximate) power in microwatts:
3458*5ffb0c9bSToomas Soome //
3459*5ffb0c9bSToomas Soome //   Power Metric = log10(uW) * 10
3460*5ffb0c9bSToomas Soome //
3461*5ffb0c9bSToomas Soome // Higher values indicate higher power consumption. Example values:
3462*5ffb0c9bSToomas Soome //
3463*5ffb0c9bSToomas Soome // 10 =  10 uW
3464*5ffb0c9bSToomas Soome // 20 = 100 uW
3465*5ffb0c9bSToomas Soome // 30 =   1 mW
3466*5ffb0c9bSToomas Soome // 60 =   1 W
3467*5ffb0c9bSToomas Soome // 90 =   1 kW
3468*5ffb0c9bSToomas Soome 
3469*5ffb0c9bSToomas Soome typedef enum
3470*5ffb0c9bSToomas Soome {
3471*5ffb0c9bSToomas Soome     mDNSSleepProxyMetric_Dedicated          = 20,
3472*5ffb0c9bSToomas Soome     mDNSSleepProxyMetric_PrimaryHardware    = 30,
3473*5ffb0c9bSToomas Soome     mDNSSleepProxyMetric_PrimarySoftware    = 40,
3474*5ffb0c9bSToomas Soome     mDNSSleepProxyMetric_SecondaryHardware  = 50,
3475*5ffb0c9bSToomas Soome     mDNSSleepProxyMetric_SecondarySoftware  = 60,
3476*5ffb0c9bSToomas Soome     mDNSSleepProxyMetric_IncidentalHardware = 70,
3477*5ffb0c9bSToomas Soome     mDNSSleepProxyMetric_IncidentalSoftware = 80
3478*5ffb0c9bSToomas Soome } mDNSSleepProxyMetric;
3479*5ffb0c9bSToomas Soome 
3480*5ffb0c9bSToomas Soome typedef enum
3481*5ffb0c9bSToomas Soome {
3482*5ffb0c9bSToomas Soome     mDNS_NoWake        = 0, // System does not support Wake on LAN
3483*5ffb0c9bSToomas Soome     mDNS_WakeOnAC      = 1, // System supports Wake on LAN when connected to AC power only
3484*5ffb0c9bSToomas Soome     mDNS_WakeOnBattery = 2  // System supports Wake on LAN on battery
3485*5ffb0c9bSToomas Soome } mDNSWakeForNetworkAccess;
3486*5ffb0c9bSToomas Soome 
3487*5ffb0c9bSToomas Soome extern void mDNSCoreBeSleepProxyServer_internal(mDNS *const m, mDNSu8 sps, mDNSu8 port, mDNSu8 marginalpower, mDNSu8 totpower, mDNSu8 features);
3488*5ffb0c9bSToomas Soome #define mDNSCoreBeSleepProxyServer(M,S,P,MP,TP,F)                       \
3489*5ffb0c9bSToomas Soome     do { mDNS_Lock(m); mDNSCoreBeSleepProxyServer_internal((M),(S),(P),(MP),(TP),(F)); mDNS_Unlock(m); } while(0)
3490*5ffb0c9bSToomas Soome 
3491*5ffb0c9bSToomas Soome extern void FindSPSInCache(mDNS *const m, const DNSQuestion *const q, const CacheRecord *sps[3]);
3492*5ffb0c9bSToomas Soome #define PrototypeSPSName(X) ((X)[0] >= 11 && (X)[3] == '-' && (X)[ 4] == '9' && (X)[ 5] == '9' && \
3493*5ffb0c9bSToomas Soome                              (X)[6] == '-' && (X)[ 7] == '9' && (X)[ 8] == '9' && \
3494*5ffb0c9bSToomas Soome                              (X)[9] == '-' && (X)[10] == '9' && (X)[11] == '9'    )
3495*5ffb0c9bSToomas Soome #define ValidSPSName(X) ((X)[0] >= 5 && mDNSIsDigit((X)[1]) && mDNSIsDigit((X)[2]) && mDNSIsDigit((X)[4]) && mDNSIsDigit((X)[5]))
3496*5ffb0c9bSToomas Soome #define SPSMetric(X) (!ValidSPSName(X) || PrototypeSPSName(X) ? 1000000 : \
3497*5ffb0c9bSToomas Soome                       ((X)[1]-'0') * 100000 + ((X)[2]-'0') * 10000 + ((X)[4]-'0') * 1000 + ((X)[5]-'0') * 100 + ((X)[7]-'0') * 10 + ((X)[8]-'0'))
3498*5ffb0c9bSToomas Soome #define LocalSPSMetric(X) ( (X)->SPSType * 10000 + (X)->SPSPortability * 100 + (X)->SPSMarginalPower)
3499*5ffb0c9bSToomas Soome #define SPSFeatures(X) ((X)[0] >= 13 && (X)[12] =='.' ? ((X)[13]-'0') : 0 )
3500*5ffb0c9bSToomas Soome 
3501*5ffb0c9bSToomas Soome #define MD5_DIGEST_LENGTH   16          /* digest length in bytes */
3502*5ffb0c9bSToomas Soome #define MD5_BLOCK_BYTES     64          /* block size in bytes */
3503*5ffb0c9bSToomas Soome #define MD5_BLOCK_LONG       (MD5_BLOCK_BYTES / sizeof(mDNSu32))
3504*5ffb0c9bSToomas Soome 
3505*5ffb0c9bSToomas Soome typedef struct MD5state_st
3506*5ffb0c9bSToomas Soome {
3507*5ffb0c9bSToomas Soome     mDNSu32 A,B,C,D;
3508*5ffb0c9bSToomas Soome     mDNSu32 Nl,Nh;
3509*5ffb0c9bSToomas Soome     mDNSu32 data[MD5_BLOCK_LONG];
3510*5ffb0c9bSToomas Soome     int num;
3511*5ffb0c9bSToomas Soome } MD5_CTX;
3512*5ffb0c9bSToomas Soome 
3513*5ffb0c9bSToomas Soome extern int MD5_Init(MD5_CTX *c);
3514*5ffb0c9bSToomas Soome extern int MD5_Update(MD5_CTX *c, const void *data, unsigned long len);
3515*5ffb0c9bSToomas Soome extern int MD5_Final(unsigned char *md, MD5_CTX *c);
3516*5ffb0c9bSToomas Soome 
3517*5ffb0c9bSToomas Soome // ***************************************************************************
3518*5ffb0c9bSToomas Soome #if 0
3519*5ffb0c9bSToomas Soome #pragma mark -
35204b22b933Srs200217 #pragma mark - Compile-Time assertion checks
35214b22b933Srs200217 #endif
35224b22b933Srs200217 
35234b22b933Srs200217 // Some C compiler cleverness. We can make the compiler check certain things for
35244b22b933Srs200217 // us, and report compile-time errors if anything is wrong. The usual way to do
35254b22b933Srs200217 // this would be to use a run-time "if" statement, but then you don't find out
35264b22b933Srs200217 // what's wrong until you run the software. This way, if the assertion condition
35274b22b933Srs200217 // is false, the array size is negative, and the complier complains immediately.
35284b22b933Srs200217 
3529*5ffb0c9bSToomas Soome struct CompileTimeAssertionChecks_mDNS
35304b22b933Srs200217 {
35314b22b933Srs200217     // Check that the compiler generated our on-the-wire packet format structure definitions
35324b22b933Srs200217     // properly packed, without adding padding bytes to align fields on 32-bit or 64-bit boundaries.
35334b22b933Srs200217     char assert0[(sizeof(rdataSRV)         == 262                          ) ? 1 : -1];
35344b22b933Srs200217     char assert1[(sizeof(DNSMessageHeader) ==  12                          ) ? 1 : -1];
35354b22b933Srs200217     char assert2[(sizeof(DNSMessage)       ==  12+AbsoluteMaxDNSMessageData) ? 1 : -1];
35364b22b933Srs200217     char assert3[(sizeof(mDNSs8)           ==   1                          ) ? 1 : -1];
35374b22b933Srs200217     char assert4[(sizeof(mDNSu8)           ==   1                          ) ? 1 : -1];
35384b22b933Srs200217     char assert5[(sizeof(mDNSs16)          ==   2                          ) ? 1 : -1];
35394b22b933Srs200217     char assert6[(sizeof(mDNSu16)          ==   2                          ) ? 1 : -1];
35404b22b933Srs200217     char assert7[(sizeof(mDNSs32)          ==   4                          ) ? 1 : -1];
35414b22b933Srs200217     char assert8[(sizeof(mDNSu32)          ==   4                          ) ? 1 : -1];
35424b22b933Srs200217     char assert9[(sizeof(mDNSOpaque16)     ==   2                          ) ? 1 : -1];
35434b22b933Srs200217     char assertA[(sizeof(mDNSOpaque32)     ==   4                          ) ? 1 : -1];
35444b22b933Srs200217     char assertB[(sizeof(mDNSOpaque128)    ==  16                          ) ? 1 : -1];
3545*5ffb0c9bSToomas Soome     char assertC[(sizeof(CacheRecord  )    ==  sizeof(CacheGroup)          ) ? 1 : -1];
35464b22b933Srs200217     char assertD[(sizeof(int)              >=  4                           ) ? 1 : -1];
3547*5ffb0c9bSToomas Soome     char assertE[(StandardAuthRDSize       >=  256                         ) ? 1 : -1];
3548*5ffb0c9bSToomas Soome     char assertF[(sizeof(EthernetHeader)   ==   14                         ) ? 1 : -1];
3549*5ffb0c9bSToomas Soome     char assertG[(sizeof(ARP_EthIP     )   ==   28                         ) ? 1 : -1];
3550*5ffb0c9bSToomas Soome     char assertH[(sizeof(IPv4Header    )   ==   20                         ) ? 1 : -1];
3551*5ffb0c9bSToomas Soome     char assertI[(sizeof(IPv6Header    )   ==   40                         ) ? 1 : -1];
3552*5ffb0c9bSToomas Soome     char assertJ[(sizeof(IPv6NDP       )   ==   24                         ) ? 1 : -1];
3553*5ffb0c9bSToomas Soome     char assertK[(sizeof(UDPHeader     )   ==    8                         ) ? 1 : -1];
3554*5ffb0c9bSToomas Soome     char assertL[(sizeof(IKEHeader     )   ==   28                         ) ? 1 : -1];
3555*5ffb0c9bSToomas Soome     char assertM[(sizeof(TCPHeader     )   ==   20                         ) ? 1 : -1];
3556*5ffb0c9bSToomas Soome 
3557*5ffb0c9bSToomas Soome     // Check our structures are reasonable sizes. Including overly-large buffers, or embedding
3558*5ffb0c9bSToomas Soome     // other overly-large structures instead of having a pointer to them, can inadvertently
3559*5ffb0c9bSToomas Soome     // cause structure sizes (and therefore memory usage) to balloon unreasonably.
3560*5ffb0c9bSToomas Soome     char sizecheck_RDataBody           [(sizeof(RDataBody)            ==   264) ? 1 : -1];
3561*5ffb0c9bSToomas Soome     char sizecheck_ResourceRecord      [(sizeof(ResourceRecord)       <=    72) ? 1 : -1];
3562*5ffb0c9bSToomas Soome     char sizecheck_AuthRecord          [(sizeof(AuthRecord)           <=  1208) ? 1 : -1];
3563*5ffb0c9bSToomas Soome     char sizecheck_CacheRecord         [(sizeof(CacheRecord)          <=   232) ? 1 : -1];
3564*5ffb0c9bSToomas Soome     char sizecheck_CacheGroup          [(sizeof(CacheGroup)           <=   232) ? 1 : -1];
3565*5ffb0c9bSToomas Soome     char sizecheck_DNSQuestion         [(sizeof(DNSQuestion)          <=   832) ? 1 : -1];
3566*5ffb0c9bSToomas Soome 
3567*5ffb0c9bSToomas Soome // Checks commented out when sizeof(DNSQuestion) change cascaded into having to change yet another
3568*5ffb0c9bSToomas Soome // set of hardcoded size values because these structures contain one or more DNSQuestion
3569*5ffb0c9bSToomas Soome // instances.
3570*5ffb0c9bSToomas Soome //     char sizecheck_ZoneData            [(sizeof(ZoneData)             <=  1648) ? 1 : -1];
3571*5ffb0c9bSToomas Soome     char sizecheck_NATTraversalInfo    [(sizeof(NATTraversalInfo)     <=   200) ? 1 : -1];
3572*5ffb0c9bSToomas Soome     char sizecheck_HostnameInfo        [(sizeof(HostnameInfo)         <=  3050) ? 1 : -1];
3573*5ffb0c9bSToomas Soome     char sizecheck_DNSServer           [(sizeof(DNSServer)            <=   340) ? 1 : -1];
3574*5ffb0c9bSToomas Soome //    char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <=  6988) ? 1 : -1];
3575*5ffb0c9bSToomas Soome     char sizecheck_ServiceRecordSet    [(sizeof(ServiceRecordSet)     <=  5540) ? 1 : -1];
3576*5ffb0c9bSToomas Soome     char sizecheck_DomainAuthInfo      [(sizeof(DomainAuthInfo)       <=  7888) ? 1 : -1];
3577*5ffb0c9bSToomas Soome //    char sizecheck_ServiceInfoQuery    [(sizeof(ServiceInfoQuery)     <=  3302) ? 1 : -1];
3578*5ffb0c9bSToomas Soome #if APPLE_OSX_mDNSResponder
3579*5ffb0c9bSToomas Soome //    char sizecheck_ClientTunnel        [(sizeof(ClientTunnel)         <=  1160) ? 1 : -1];
3580*5ffb0c9bSToomas Soome #endif
35814b22b933Srs200217 };
35824b22b933Srs200217 
3583*5ffb0c9bSToomas Soome // Routine to initialize device-info TXT record contents
3584*5ffb0c9bSToomas Soome mDNSu32 initializeDeviceInfoTXT(mDNS *m, mDNSu8 *ptr);
3585*5ffb0c9bSToomas Soome 
3586*5ffb0c9bSToomas Soome #if APPLE_OSX_mDNSResponder
3587*5ffb0c9bSToomas Soome extern void D2D_start_advertising_interface(NetworkInterfaceInfo *interface);
3588*5ffb0c9bSToomas Soome extern void D2D_stop_advertising_interface(NetworkInterfaceInfo *interface);
3589*5ffb0c9bSToomas Soome #endif
3590*5ffb0c9bSToomas Soome 
35914b22b933Srs200217 // ***************************************************************************
35924b22b933Srs200217 
35934b22b933Srs200217 #ifdef __cplusplus
35944b22b933Srs200217 }
35954b22b933Srs200217 #endif
35964b22b933Srs200217 
35974b22b933Srs200217 #endif
3598