14b22b93rs/* -*- Mode: C; tab-width: 4 -*-
24b22b93rs *
33b436d0Toomas Soome * Copyright (c) 2002-2018 Apple Inc. All rights reserved.
44b22b93rs *
54b22b93rs * Licensed under the Apache License, Version 2.0 (the "License");
64b22b93rs * you may not use this file except in compliance with the License.
74b22b93rs * You may obtain a copy of the License at
85ffb0c9Toomas Soome *
94b22b93rs *     http://www.apache.org/licenses/LICENSE-2.0
105ffb0c9Toomas Soome *
114b22b93rs * Unless required by applicable law or agreed to in writing, software
124b22b93rs * distributed under the License is distributed on an "AS IS" BASIS,
134b22b93rs * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
144b22b93rs * See the License for the specific language governing permissions and
154b22b93rs * limitations under the License.
164b22b93rs
174b22b93rs   NOTE:
184b22b93rs   If you're building an application that uses DNS Service Discovery
194b22b93rs   this is probably NOT the header file you're looking for.
204b22b93rs   In most cases you will want to use /usr/include/dns_sd.h instead.
214b22b93rs
224b22b93rs   This header file defines the lowest level raw interface to mDNSCore,
234b22b93rs   which is appropriate *only* on tiny embedded systems where everything
244b22b93rs   runs in a single address space and memory is extremely constrained.
254b22b93rs   All the APIs here are malloc-free, which means that the caller is
264b22b93rs   responsible for passing in a pointer to the relevant storage that
274b22b93rs   will be used in the execution of that call, and (when called with
284b22b93rs   correct parameters) all the calls are guaranteed to succeed. There
294b22b93rs   is never a case where a call can suffer intermittent failures because
304b22b93rs   the implementation calls malloc() and sometimes malloc() returns NULL
314b22b93rs   because memory is so limited that no more is available.
324b22b93rs   This is primarily for devices that need to have precisely known fixed
334b22b93rs   memory requirements, with absolutely no uncertainty or run-time variation,
344b22b93rs   but that certainty comes at a cost of more difficult programming.
355ffb0c9Toomas Soome
364b22b93rs   For applications running on general-purpose desktop operating systems
374b22b93rs   (Mac OS, Linux, Solaris, Windows, etc.) the API you should use is
384b22b93rs   /usr/include/dns_sd.h, which defines the API by which multiple
394b22b93rs   independent client processes communicate their DNS Service Discovery
404b22b93rs   requests to a single "mdnsd" daemon running in the background.
415ffb0c9Toomas Soome
424b22b93rs   Even on platforms that don't run multiple independent processes in
434b22b93rs   multiple independent address spaces, you can still use the preferred
444b22b93rs   dns_sd.h APIs by linking in "dnssd_clientshim.c", which implements
454b22b93rs   the standard "dns_sd.h" API calls, allocates any required storage
464b22b93rs   using malloc(), and then calls through to the low-level malloc-free
474b22b93rs   mDNSCore routines defined here. This has the benefit that even though
484b22b93rs   you're running on a small embedded system with a single address space,
494b22b93rs   you can still use the exact same client C code as you'd use on a
504b22b93rs   general-purpose desktop system.
514b22b93rs
525ffb0c9Toomas Soome */
534b22b93rs
545ffb0c9Toomas Soome#ifndef __mDNSEmbeddedAPI_h
555ffb0c9Toomas Soome#define __mDNSEmbeddedAPI_h
564b22b93rs
575ffb0c9Toomas Soome#if defined(EFI32) || defined(EFI64) || defined(EFIX64)
585ffb0c9Toomas Soome// EFI doesn't have stdarg.h unless it's building with GCC.
595ffb0c9Toomas Soome#include "Tiano.h"
605ffb0c9Toomas Soome#if !defined(__GNUC__)
615ffb0c9Toomas Soome#define va_list         VA_LIST
625ffb0c9Toomas Soome#define va_start(a, b)  VA_START(a, b)
635ffb0c9Toomas Soome#define va_end(a)       VA_END(a)
645ffb0c9Toomas Soome#define va_arg(a, b)    VA_ARG(a, b)
655ffb0c9Toomas Soome#endif
665ffb0c9Toomas Soome#else
675ffb0c9Toomas Soome#include <stdarg.h>     // stdarg.h is required for for va_list support for the mDNS_vsnprintf declaration
685ffb0c9Toomas Soome#endif
694b22b93rs
705ffb0c9Toomas Soome#include "mDNSDebug.h"
715ffb0c9Toomas Soome#if APPLE_OSX_mDNSResponder
725ffb0c9Toomas Soome#include <uuid/uuid.h>
73cda73f6Toomas Soome#include <TargetConditionals.h>
745ffb0c9Toomas Soome#endif
754b22b93rs
765ffb0c9Toomas Soome#ifdef __cplusplus
775ffb0c9Toomas Soomeextern "C" {
785ffb0c9Toomas Soome#endif
794b22b93rs
805ffb0c9Toomas Soome// ***************************************************************************
815ffb0c9Toomas Soome// Feature removal compile options & limited resource targets
824b22b93rs
835ffb0c9Toomas Soome// The following compile options are responsible for removing certain features from mDNSCore to reduce the
845ffb0c9Toomas Soome// memory footprint for use in embedded systems with limited resources.
854b22b93rs
865ffb0c9Toomas Soome// UNICAST_DISABLED - disables unicast DNS functionality, including Wide Area Bonjour
875ffb0c9Toomas Soome// ANONYMOUS_DISABLED - disables anonymous functionality
885ffb0c9Toomas Soome// DNSSEC_DISABLED - disables DNSSEC functionality
895ffb0c9Toomas Soome// SPC_DISABLED - disables Bonjour Sleep Proxy client
905ffb0c9Toomas Soome// IDLESLEEPCONTROL_DISABLED - disables sleep control for Bonjour Sleep Proxy clients
914b22b93rs
925ffb0c9Toomas Soome// In order to disable the above features pass the option to your compiler, e.g. -D UNICAST_DISABLED
934b22b93rs
94cda73f6Toomas Soome// Additionally, the LIMITED_RESOURCES_TARGET compile option will reduce the maximum DNS message sizes.
954b22b93rs
965ffb0c9Toomas Soome#ifdef LIMITED_RESOURCES_TARGET
975ffb0c9Toomas Soome// Don't support jumbo frames
98cda73f6Toomas Soome// 40 (IPv6 header) + 8 (UDP header) + 12 (DNS message header) + 1440 (DNS message body) = 1500 total
99c65ebfcToomas Soome#define AbsoluteMaxDNSMessageData   1440
1005ffb0c9Toomas Soome// StandardAuthRDSize is 264 (256+8), which is large enough to hold a maximum-sized SRV record (6 + 256 bytes)
101c65ebfcToomas Soome#define MaximumRDSize               264
1024b22b93rs#endif
1034b22b93rs
1043b436d0Toomas Soome#if !defined(MDNSRESPONDER_BTMM_SUPPORT)
1053b436d0Toomas Soome#define MDNSRESPONDER_BTMM_SUPPORT 0
1063b436d0Toomas Soome#endif
1073b436d0Toomas Soome
1084b22b93rs// ***************************************************************************
1094b22b93rs// Function scope indicators
1104b22b93rs
1114b22b93rs// If you see "mDNSlocal" before a function name in a C file, it means the function is not callable outside this file
1124b22b93rs#ifndef mDNSlocal
1134b22b93rs#define mDNSlocal static
1144b22b93rs#endif
1154b22b93rs// If you see "mDNSexport" before a symbol in a C file, it means the symbol is exported for use by clients
1164b22b93rs// For every "mDNSexport" in a C file, there needs to be a corresponding "extern" declaration in some header file
1174b22b93rs// (When a C file #includes a header file, the "extern" declarations tell the compiler:
1184b22b93rs// "This symbol exists -- but not necessarily in this C file.")
1194b22b93rs#ifndef mDNSexport
1204b22b93rs#define mDNSexport
1214b22b93rs#endif
1224b22b93rs
1234b22b93rs// Explanation: These local/export markers are a little habit of mine for signaling the programmers' intentions.
1244b22b93rs// When "mDNSlocal" is just a synonym for "static", and "mDNSexport" is a complete no-op, you could be
1254b22b93rs// forgiven for asking what purpose they serve. The idea is that if you see "mDNSexport" in front of a
1264b22b93rs// function definition it means the programmer intended it to be exported and callable from other files
1274b22b93rs// in the project. If you see "mDNSlocal" in front of a function definition it means the programmer
1284b22b93rs// intended it to be private to that file. If you see neither in front of a function definition it
1294b22b93rs// means the programmer forgot (so you should work out which it is supposed to be, and fix it).
1304b22b93rs// Using "mDNSlocal" instead of "static" makes it easier to do a textual searches for one or the other.
1314b22b93rs// For example you can do a search for "static" to find if any functions declare any local variables as "static"
1324b22b93rs// (generally a bad idea unless it's also "const", because static storage usually risks being non-thread-safe)
1334b22b93rs// without the results being cluttered with hundreds of matches for functions declared static.
1344b22b93rs// - Stuart Cheshire
1354b22b93rs
1364b22b93rs// ***************************************************************************
1374b22b93rs// Structure packing macro
1384b22b93rs
1394b22b93rs// If we're not using GNUC, it's not fatal.
1404b22b93rs// Most compilers naturally pack the on-the-wire structures correctly anyway, so a plain "struct" is usually fine.
1414b22b93rs// In the event that structures are not packed correctly, mDNS_Init() will detect this and report an error, so the
1424b22b93rs// developer will know what's wrong, and can investigate what needs to be done on that compiler to provide proper packing.
1434b22b93rs#ifndef packedstruct
1444b22b93rs #if ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9)))
1454b22b93rs  #define packedstruct struct __attribute__((__packed__))
1464b22b93rs  #define packedunion  union  __attribute__((__packed__))
1474b22b93rs #else
1484b22b93rs  #define packedstruct struct
1494b22b93rs  #define packedunion  union
1504b22b93rs #endif
1514b22b93rs#endif
1524b22b93rs
1534b22b93rs// ***************************************************************************
1544b22b93rs#if 0
1554b22b93rs#pragma mark - DNS Resource Record class and type constants
1564b22b93rs#endif
1574b22b93rs
1585ffb0c9Toomas Soometypedef enum                            // From RFC 1035
1595ffb0c9Toomas Soome{
1605ffb0c9Toomas Soome    kDNSClass_IN               = 1,     // Internet
1615ffb0c9Toomas Soome    kDNSClass_CS               = 2,     // CSNET
1625ffb0c9Toomas Soome    kDNSClass_CH               = 3,     // CHAOS
1635ffb0c9Toomas Soome    kDNSClass_HS               = 4,     // Hesiod
1645ffb0c9Toomas Soome    kDNSClass_NONE             = 254,   // Used in DNS UPDATE [RFC 2136]
1655ffb0c9Toomas Soome
1665ffb0c9Toomas Soome    kDNSClass_Mask             = 0x7FFF, // Multicast DNS uses the bottom 15 bits to identify the record class...
1675ffb0c9Toomas Soome    kDNSClass_UniqueRRSet      = 0x8000, // ... and the top bit indicates that all other cached records are now invalid
1685ffb0c9Toomas Soome
1695ffb0c9Toomas Soome    kDNSQClass_ANY             = 255,   // Not a DNS class, but a DNS query class, meaning "all classes"
1705ffb0c9Toomas Soome    kDNSQClass_UnicastResponse = 0x8000 // Top bit set in a question means "unicast response acceptable"
1715ffb0c9Toomas Soome} DNS_ClassValues;
1725ffb0c9Toomas Soome
1735ffb0c9Toomas Soometypedef enum                // From RFC 1035
1745ffb0c9Toomas Soome{
1755ffb0c9Toomas Soome    kDNSType_A = 1,         //  1 Address
1765ffb0c9Toomas Soome    kDNSType_NS,            //  2 Name Server
1775ffb0c9Toomas Soome    kDNSType_MD,            //  3 Mail Destination
1785ffb0c9Toomas Soome    kDNSType_MF,            //  4 Mail Forwarder
1795ffb0c9Toomas Soome    kDNSType_CNAME,         //  5 Canonical Name
1805ffb0c9Toomas Soome    kDNSType_SOA,           //  6 Start of Authority
1815ffb0c9Toomas Soome    kDNSType_MB,            //  7 Mailbox
1825ffb0c9Toomas Soome    kDNSType_MG,            //  8 Mail Group
1835ffb0c9Toomas Soome    kDNSType_MR,            //  9 Mail Rename
1845ffb0c9Toomas Soome    kDNSType_NULL,          // 10 NULL RR
1855ffb0c9Toomas Soome    kDNSType_WKS,           // 11 Well-known-service
1865ffb0c9Toomas Soome    kDNSType_PTR,           // 12 Domain name pointer
1875ffb0c9Toomas Soome    kDNSType_HINFO,         // 13 Host information
1885ffb0c9Toomas Soome    kDNSType_MINFO,         // 14 Mailbox information
1895ffb0c9Toomas Soome    kDNSType_MX,            // 15 Mail Exchanger
1905ffb0c9Toomas Soome    kDNSType_TXT,           // 16 Arbitrary text string
1915ffb0c9Toomas Soome    kDNSType_RP,            // 17 Responsible person
1925ffb0c9Toomas Soome    kDNSType_AFSDB,         // 18 AFS cell database
1935ffb0c9Toomas Soome    kDNSType_X25,           // 19 X_25 calling address
1945ffb0c9Toomas Soome    kDNSType_ISDN,          // 20 ISDN calling address
1955ffb0c9Toomas Soome    kDNSType_RT,            // 21 Router
1965ffb0c9Toomas Soome    kDNSType_NSAP,          // 22 NSAP address
1975ffb0c9Toomas Soome    kDNSType_NSAP_PTR,      // 23 Reverse NSAP lookup (deprecated)
1985ffb0c9Toomas Soome    kDNSType_SIG,           // 24 Security signature
1995ffb0c9Toomas Soome    kDNSType_KEY,           // 25 Security key
2005ffb0c9Toomas Soome    kDNSType_PX,            // 26 X.400 mail mapping
2015ffb0c9Toomas Soome    kDNSType_GPOS,          // 27 Geographical position (withdrawn)
2025ffb0c9Toomas Soome    kDNSType_AAAA,          // 28 IPv6 Address
2035ffb0c9Toomas Soome    kDNSType_LOC,           // 29 Location Information
2045ffb0c9Toomas Soome    kDNSType_NXT,           // 30 Next domain (security)
2055ffb0c9Toomas Soome    kDNSType_EID,           // 31 Endpoint identifier
2065ffb0c9Toomas Soome    kDNSType_NIMLOC,        // 32 Nimrod Locator
2075ffb0c9Toomas Soome    kDNSType_SRV,           // 33 Service record
2085ffb0c9Toomas Soome    kDNSType_ATMA,          // 34 ATM Address
2095ffb0c9Toomas Soome    kDNSType_NAPTR,         // 35 Naming Authority PoinTeR
2105ffb0c9Toomas Soome    kDNSType_KX,            // 36 Key Exchange
2115ffb0c9Toomas Soome    kDNSType_CERT,          // 37 Certification record
2125ffb0c9Toomas Soome    kDNSType_A6,            // 38 IPv6 Address (deprecated)
2135ffb0c9Toomas Soome    kDNSType_DNAME,         // 39 Non-terminal DNAME (for IPv6)
2145ffb0c9Toomas Soome    kDNSType_SINK,          // 40 Kitchen sink (experimental)
2155ffb0c9Toomas Soome    kDNSType_OPT,           // 41 EDNS0 option (meta-RR)
2165ffb0c9Toomas Soome    kDNSType_APL,           // 42 Address Prefix List
2175ffb0c9Toomas Soome    kDNSType_DS,            // 43 Delegation Signer
2185ffb0c9Toomas Soome    kDNSType_SSHFP,         // 44 SSH Key Fingerprint
2195ffb0c9Toomas Soome    kDNSType_IPSECKEY,      // 45 IPSECKEY
2205ffb0c9Toomas Soome    kDNSType_RRSIG,         // 46 RRSIG
2215ffb0c9Toomas Soome    kDNSType_NSEC,          // 47 Denial of Existence
2225ffb0c9Toomas Soome    kDNSType_DNSKEY,        // 48 DNSKEY
2235ffb0c9Toomas Soome    kDNSType_DHCID,         // 49 DHCP Client Identifier
2245ffb0c9Toomas Soome    kDNSType_NSEC3,         // 50 Hashed Authenticated Denial of Existence
2255ffb0c9Toomas Soome    kDNSType_NSEC3PARAM,    // 51 Hashed Authenticated Denial of Existence
2265ffb0c9Toomas Soome
2275ffb0c9Toomas Soome    kDNSType_HIP = 55,      // 55 Host Identity Protocol
2285ffb0c9Toomas Soome
2295ffb0c9Toomas Soome    kDNSType_SPF = 99,      // 99 Sender Policy Framework for E-Mail
2305ffb0c9Toomas Soome    kDNSType_UINFO,         // 100 IANA-Reserved
2315ffb0c9Toomas Soome    kDNSType_UID,           // 101 IANA-Reserved
2325ffb0c9Toomas Soome    kDNSType_GID,           // 102 IANA-Reserved
2335ffb0c9Toomas Soome    kDNSType_UNSPEC,        // 103 IANA-Reserved
2345ffb0c9Toomas Soome
2355ffb0c9Toomas Soome    kDNSType_TKEY = 249,    // 249 Transaction key
2365ffb0c9Toomas Soome    kDNSType_TSIG,          // 250 Transaction signature
2375ffb0c9Toomas Soome    kDNSType_IXFR,          // 251 Incremental zone transfer
2385ffb0c9Toomas Soome    kDNSType_AXFR,          // 252 Transfer zone of authority
2395ffb0c9Toomas Soome    kDNSType_MAILB,         // 253 Transfer mailbox records
2405ffb0c9Toomas Soome    kDNSType_MAILA,         // 254 Transfer mail agent records
2415ffb0c9Toomas Soome    kDNSQType_ANY           // Not a DNS type, but a DNS query type, meaning "all types"
2425ffb0c9Toomas Soome} DNS_TypeValues;
2434b22b93rs
2444b22b93rs// ***************************************************************************
2454b22b93rs#if 0
2465ffb0c9Toomas Soome#pragma mark -
2474b22b93rs#pragma mark - Simple types
2484b22b93rs#endif
2494b22b93rs
2504b22b93rs// mDNS defines its own names for these common types to simplify portability across
2514b22b93rs// multiple platforms that may each have their own (different) names for these types.
2525ffb0c9Toomas Soometypedef unsigned char mDNSBool;
2535ffb0c9Toomas Soometypedef   signed char mDNSs8;
2545ffb0c9Toomas Soometypedef unsigned char mDNSu8;
2554b22b93rstypedef   signed short mDNSs16;
2564b22b93rstypedef unsigned short mDNSu16;
2574b22b93rs
2585ffb0c9Toomas Soome// Source: http://www.unix.org/version2/whatsnew/lp64_wp.html
2595ffb0c9Toomas Soome// http://software.intel.com/sites/products/documentation/hpc/mkl/lin/MKL_UG_structure/Support_for_ILP64_Programming.htm
2605ffb0c9Toomas Soome// It can be safely assumed that int is 32bits on the platform
2614b22b93rs#if defined(_ILP64) || defined(__ILP64__)
2624b22b93rstypedef   signed int32 mDNSs32;
2634b22b93rstypedef unsigned int32 mDNSu32;
2644b22b93rs#else
2655ffb0c9Toomas Soometypedef   signed int mDNSs32;
2665ffb0c9Toomas Soometypedef unsigned int mDNSu32;
2674b22b93rs#endif
2684b22b93rs
2694b22b93rs// To enforce useful type checking, we make mDNSInterfaceID be a pointer to a dummy struct
2704b22b93rs// This way, mDNSInterfaceIDs can be assigned, and compared with each other, but not with other types
2714b22b93rs// Declaring the type to be the typical generic "void *" would lack this type checking
2724b22b93rstypedef struct mDNSInterfaceID_dummystruct { void *dummy; } *mDNSInterfaceID;
2734b22b93rs
2744b22b93rs// These types are for opaque two- and four-byte identifiers.
2754b22b93rs// The "NotAnInteger" fields of the unions allow the value to be conveniently passed around in a
2764b22b93rs// register for the sake of efficiency, and compared for equality or inequality, but don't forget --
2774b22b93rs// just because it is in a register doesn't mean it is an integer. Operations like greater than,
2784b22b93rs// less than, add, multiply, increment, decrement, etc., are undefined for opaque identifiers,
2794b22b93rs// and if you make the mistake of trying to do those using the NotAnInteger field, then you'll
2804b22b93rs// find you get code that doesn't work consistently on big-endian and little-endian machines.
2815ffb0c9Toomas Soome#if defined(_WIN32)
2825ffb0c9Toomas Soome #pragma pack(push,2)
2833b436d0Toomas Soome#elif !defined(__GNUC__)
2843b436d0Toomas Soome #pragma pack(1)
2855ffb0c9Toomas Soome#endif
2865ffb0c9Toomas Soometypedef       union { mDNSu8 b[ 2]; mDNSu16 NotAnInteger; } mDNSOpaque16;
2875ffb0c9Toomas Soometypedef       union { mDNSu8 b[ 4]; mDNSu32 NotAnInteger; } mDNSOpaque32;
2884b22b93rstypedef packedunion { mDNSu8 b[ 6]; mDNSu16 w[3]; mDNSu32 l[1]; } mDNSOpaque48;
2895ffb0c9Toomas Soometypedef       union { mDNSu8 b[ 8]; mDNSu16 w[4]; mDNSu32 l[2]; } mDNSOpaque64;
2905ffb0c9Toomas Soometypedef       union { mDNSu8 b[16]; mDNSu16 w[8]; mDNSu32 l[4]; } mDNSOpaque128;
2915ffb0c9Toomas Soome#if defined(_WIN32)
2925ffb0c9Toomas Soome #pragma pack(pop)
2933b436d0Toomas Soome#elif !defined(__GNUC__)
2943b436d0Toomas Soome #pragma pack()
2955ffb0c9Toomas Soome#endif
2965ffb0c9Toomas Soome
2975ffb0c9Toomas Soometypedef mDNSOpaque16 mDNSIPPort;        // An IP port is a two-byte opaque identifier (not an integer)
2985ffb0c9Toomas Soometypedef mDNSOpaque32 mDNSv4Addr;        // An IP address is a four-byte opaque identifier (not an integer)
2995ffb0c9Toomas Soometypedef mDNSOpaque128 mDNSv6Addr;       // An IPv6 address is a 16-byte opaque identifier (not an integer)
3005ffb0c9Toomas Soometypedef mDNSOpaque48 mDNSEthAddr;       // An Ethernet address is a six-byte opaque identifier (not an integer)
3014b22b93rs
3025ffb0c9Toomas Soome// Bit operations for opaque 64 bit quantity. Uses the 32 bit quantity(l[2]) to set and clear bits
3035ffb0c9Toomas Soome#define mDNSNBBY 8
3045ffb0c9Toomas Soome#define bit_set_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] |= (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
3055ffb0c9Toomas Soome#define bit_clr_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] &= ~(1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
3065ffb0c9Toomas Soome#define bit_get_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] & (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
3074b22b93rs
308c65ebfcToomas Soome// Bit operations for opaque 128 bit quantity. Uses the 32 bit quantity(l[4]) to set and clear bits
309c65ebfcToomas Soome#define bit_set_opaque128(op128, index) (op128.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] |= (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
310c65ebfcToomas Soome#define bit_clr_opaque128(op128, index) (op128.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] &= ~(1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
311c65ebfcToomas Soome#define bit_get_opaque128(op128, index) (op128.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] & (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
312c65ebfcToomas Soome
313c65ebfcToomas Soometypedef enum
3145ffb0c9Toomas Soome{
3155ffb0c9Toomas Soome    mDNSAddrType_None    = 0,
3165ffb0c9Toomas Soome    mDNSAddrType_IPv4    = 4,
3175ffb0c9Toomas Soome    mDNSAddrType_IPv6    = 6,
3185ffb0c9Toomas Soome    mDNSAddrType_Unknown = ~0   // Special marker value used in known answer list recording
319c65ebfcToomas Soome} mDNSAddr_Type;
3205ffb0c9Toomas Soome
321c65ebfcToomas Soometypedef enum
3225ffb0c9Toomas Soome{
3235ffb0c9Toomas Soome    mDNSTransport_None = 0,
3245ffb0c9Toomas Soome    mDNSTransport_UDP  = 1,
3255ffb0c9Toomas Soome    mDNSTransport_TCP  = 2
326c65ebfcToomas Soome} mDNSTransport_Type;
3274b22b93rs
3284b22b93rstypedef struct
3295ffb0c9Toomas Soome{
3305ffb0c9Toomas Soome    mDNSs32 type;
3315ffb0c9Toomas Soome    union { mDNSv6Addr v6; mDNSv4Addr v4; } ip;
3325ffb0c9Toomas Soome} mDNSAddr;
3334b22b93rs
3344b22b93rsenum { mDNSfalse = 0, mDNStrue = 1 };
3354b22b93rs
3364b22b93rs#define mDNSNULL 0L
3374b22b93rs
3384b22b93rsenum
3395ffb0c9Toomas Soome{
3405ffb0c9Toomas Soome    mStatus_Waiting           = 1,
3415ffb0c9Toomas Soome    mStatus_NoError           = 0,
3425ffb0c9Toomas Soome
3435ffb0c9Toomas Soome    // mDNS return values are in the range FFFE FF00 (-65792) to FFFE FFFF (-65537)
3445ffb0c9Toomas Soome    // The top end of the range (FFFE FFFF) is used for error codes;
3455ffb0c9Toomas Soome    // the bottom end of the range (FFFE FF00) is used for non-error values;
3465ffb0c9Toomas Soome
3475ffb0c9Toomas Soome    // Error codes:
3485ffb0c9Toomas Soome    mStatus_UnknownErr                = -65537,     // First value: 0xFFFE FFFF
3495ffb0c9Toomas Soome    mStatus_NoSuchNameErr             = -65538,
3505ffb0c9Toomas Soome    mStatus_NoMemoryErr               = -65539,
3515ffb0c9Toomas Soome    mStatus_BadParamErr               = -65540,
3525ffb0c9Toomas Soome    mStatus_BadReferenceErr           = -65541,
3535ffb0c9Toomas Soome    mStatus_BadStateErr               = -65542,
3545ffb0c9Toomas Soome    mStatus_BadFlagsErr               = -65543,
3555ffb0c9Toomas Soome    mStatus_UnsupportedErr            = -65544,
3565ffb0c9Toomas Soome    mStatus_NotInitializedErr         = -65545,
3575ffb0c9Toomas Soome    mStatus_NoCache                   = -65546,
3585ffb0c9Toomas Soome    mStatus_AlreadyRegistered         = -65547,
3595ffb0c9Toomas Soome    mStatus_NameConflict              = -65548,
3605ffb0c9Toomas Soome    mStatus_Invalid                   = -65549,
3615ffb0c9Toomas Soome    mStatus_Firewall                  = -65550,
3625ffb0c9Toomas Soome    mStatus_Incompatible              = -65551,
3635ffb0c9Toomas Soome    mStatus_BadInterfaceErr           = -65552,
3645ffb0c9Toomas Soome    mStatus_Refused                   = -65553,
3655ffb0c9Toomas Soome    mStatus_NoSuchRecord              = -65554,
3665ffb0c9Toomas Soome    mStatus_NoAuth                    = -65555,
3675ffb0c9Toomas Soome    mStatus_NoSuchKey                 = -65556,
3685ffb0c9Toomas Soome    mStatus_NATTraversal              = -65557,
3695ffb0c9Toomas Soome    mStatus_DoubleNAT                 = -65558,
3705ffb0c9Toomas Soome    mStatus_BadTime                   = -65559,
3715ffb0c9Toomas Soome    mStatus_BadSig                    = -65560,     // while we define this per RFC 2845, BIND 9 returns Refused for bad/missing signatures
3725ffb0c9Toomas Soome    mStatus_BadKey                    = -65561,
3735ffb0c9Toomas Soome    mStatus_TransientErr              = -65562,     // transient failures, e.g. sending packets shortly after a network transition or wake from sleep
3745ffb0c9Toomas Soome    mStatus_ServiceNotRunning         = -65563,     // Background daemon not running
3755ffb0c9Toomas Soome    mStatus_NATPortMappingUnsupported = -65564,     // NAT doesn't support PCP, NAT-PMP or UPnP
3765ffb0c9Toomas Soome    mStatus_NATPortMappingDisabled    = -65565,     // NAT supports PCP, NAT-PMP or UPnP, but it's disabled by the administrator
3775ffb0c9Toomas Soome    mStatus_NoRouter                  = -65566,
3785ffb0c9Toomas Soome    mStatus_PollingMode               = -65567,
3795ffb0c9Toomas Soome    mStatus_Timeout                   = -65568,
380c65ebfcToomas Soome    mStatus_HostUnreachErr            = -65569,
381c65ebfcToomas Soome    // -65570 to -65786 currently unused; available for allocation
3825ffb0c9Toomas Soome
3835ffb0c9Toomas Soome    // tcp connection status
3845ffb0c9Toomas Soome    mStatus_ConnPending       = -65787,
3855ffb0c9Toomas Soome    mStatus_ConnFailed        = -65788,
3865ffb0c9Toomas Soome    mStatus_ConnEstablished   = -65789,
3875ffb0c9Toomas Soome
3885ffb0c9Toomas Soome    // Non-error values:
3895ffb0c9Toomas Soome    mStatus_GrowCache         = -65790,
3905ffb0c9Toomas Soome    mStatus_ConfigChanged     = -65791,
3915ffb0c9Toomas Soome    mStatus_MemFree           = -65792      // Last value: 0xFFFE FF00
3925ffb0c9Toomas Soome                                // mStatus_MemFree is the last legal mDNS error code, at the end of the range allocated for mDNS
3935ffb0c9Toomas Soome};
3944b22b93rs
3954b22b93rstypedef mDNSs32 mStatus;
3965ffb0c9Toomas Soome#define MaxIp 5 // Needs to be consistent with MaxInputIf in dns_services.h
3975ffb0c9Toomas Soome
3985ffb0c9Toomas Soometypedef enum { q_stop = 0, q_start } q_state;
3995ffb0c9Toomas Soometypedef enum { reg_stop = 0, reg_start } reg_state;
4004b22b93rs
4014b22b93rs// RFC 1034/1035 specify that a domain label consists of a length byte plus up to 63 characters
4024b22b93rs#define MAX_DOMAIN_LABEL 63
4035ffb0c9Toomas Soometypedef struct { mDNSu8 c[ 64]; } domainlabel;      // One label: length byte and up to 63 characters
4044b22b93rs
4055ffb0c9Toomas Soome// RFC 1034/1035/2181 specify that a domain name (length bytes and data bytes) may be up to 255 bytes long,
4065ffb0c9Toomas Soome// plus the terminating zero at the end makes 256 bytes total in the on-the-wire format.
4075ffb0c9Toomas Soome#define MAX_DOMAIN_NAME 256
4085ffb0c9Toomas Soometypedef struct { mDNSu8 c[256]; } domainname;       // Up to 256 bytes of length-prefixed domainlabels
4094b22b93rs
4105ffb0c9Toomas Soometypedef struct { mDNSu8 c[256]; } UTF8str255;       // Null-terminated C string
4114b22b93rs
4125ffb0c9Toomas Soome// The longest legal textual form of a DNS name is 1009 bytes, including the C-string terminating NULL at the end.
4134b22b93rs// Explanation:
4144b22b93rs// When a native domainname object is converted to printable textual form using ConvertDomainNameToCString(),
4154b22b93rs// non-printing characters are represented in the conventional DNS way, as '\ddd', where ddd is a three-digit decimal number.
4165ffb0c9Toomas Soome// The longest legal domain name is 256 bytes, in the form of four labels as shown below:
4175ffb0c9Toomas Soome// Length byte, 63 data bytes, length byte, 63 data bytes, length byte, 63 data bytes, length byte, 62 data bytes, zero byte.
4184b22b93rs// Each label is encoded textually as characters followed by a trailing dot.
4194b22b93rs// If every character has to be represented as a four-byte escape sequence, then this makes the maximum textual form four labels
4204b22b93rs// plus the C-string terminating NULL as shown below:
4215ffb0c9Toomas Soome// 63*4+1 + 63*4+1 + 63*4+1 + 62*4+1 + 1 = 1009.
4224b22b93rs// Note that MAX_ESCAPED_DOMAIN_LABEL is not normally used: If you're only decoding a single label, escaping is usually not required.
4234b22b93rs// It is for domain names, where dots are used as label separators, that proper escaping is vital.
4244b22b93rs#define MAX_ESCAPED_DOMAIN_LABEL 254
4255ffb0c9Toomas Soome#define MAX_ESCAPED_DOMAIN_NAME 1009
4265ffb0c9Toomas Soome
4275ffb0c9Toomas Soome// MAX_REVERSE_MAPPING_NAME
4285ffb0c9Toomas Soome// For IPv4: "123.123.123.123.in-addr.arpa."  30 bytes including terminating NUL
4295ffb0c9Toomas 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
4305ffb0c9Toomas Soome
4315ffb0c9Toomas Soome#define MAX_REVERSE_MAPPING_NAME_V4 30
4325ffb0c9Toomas Soome#define MAX_REVERSE_MAPPING_NAME_V6 74
4335ffb0c9Toomas Soome#define MAX_REVERSE_MAPPING_NAME    74
4344b22b93rs
4354b22b93rs// Most records have a TTL of 75 minutes, so that their 80% cache-renewal query occurs once per hour.
4364b22b93rs// For records containing a hostname (in the name on the left, or in the rdata on the right),
4374b22b93rs// like A, AAAA, reverse-mapping PTR, and SRV, we use a two-minute TTL by default, because we don't want
4384b22b93rs// them to hang around for too long in the cache if the host in question crashes or otherwise goes away.
4395ffb0c9Toomas Soome
4404b22b93rs#define kStandardTTL (3600UL * 100 / 80)
4414b22b93rs#define kHostNameTTL 120UL
4425ffb0c9Toomas Soome
4435ffb0c9Toomas Soome// Some applications want to register their SRV records with a lower ttl so that in case the server
4445ffb0c9Toomas Soome// using a dynamic port number restarts, the clients will not have stale information for more than
4455ffb0c9Toomas Soome// 10 seconds
4465ffb0c9Toomas Soome
4475ffb0c9Toomas Soome#define kHostNameSmallTTL 10UL
4485ffb0c9Toomas Soome
4495ffb0c9Toomas Soome
4505ffb0c9Toomas Soome// Multicast DNS uses announcements (gratuitous responses) to update peer caches.
4515ffb0c9Toomas Soome// This means it is feasible to use relatively larger TTL values than we might otherwise
4525ffb0c9Toomas Soome// use, because we have a cache coherency protocol to keep the peer caches up to date.
4535ffb0c9Toomas Soome// With Unicast DNS, once an authoritative server gives a record with a certain TTL value to a client
4545ffb0c9Toomas Soome// or caching server, that client or caching server is entitled to hold onto the record until its TTL
4555ffb0c9Toomas Soome// expires, and has no obligation to contact the authoritative server again until that time arrives.
4565ffb0c9Toomas Soome// This means that whereas Multicast DNS can use announcements to pre-emptively update stale data
4575ffb0c9Toomas Soome// before it would otherwise have expired, standard Unicast DNS (not using LLQs) has no equivalent
4585ffb0c9Toomas Soome// mechanism, and TTL expiry is the *only* mechanism by which stale data gets deleted. Because of this,
4595ffb0c9Toomas Soome// we currently limit the TTL to ten seconds in such cases where no dynamic cache updating is possible.
4605ffb0c9Toomas Soome#define kStaticCacheTTL 10
4614b22b93rs
4624b22b93rs#define DefaultTTLforRRType(X) (((X) == kDNSType_A || (X) == kDNSType_AAAA || (X) == kDNSType_SRV) ? kHostNameTTL : kStandardTTL)
4635ffb0c9Toomas Soome#define mDNS_KeepaliveRecord(rr) ((rr)->rrtype == kDNSType_NULL && SameDomainLabel(SecondLabel((rr)->name)->c, (mDNSu8 *)"\x0A_keepalive"))
4645ffb0c9Toomas Soome
4655ffb0c9Toomas Soome// Number of times keepalives are sent if no ACK is received before waking up the system
4665ffb0c9Toomas Soome// this is analogous to net.inet.tcp.keepcnt
4675ffb0c9Toomas Soome#define kKeepaliveRetryCount    10
4685ffb0c9Toomas Soome// The frequency at which keepalives are retried if no ACK is received
4695ffb0c9Toomas Soome#define kKeepaliveRetryInterval 30
4705ffb0c9Toomas Soome
4715ffb0c9Toomas Soometypedef struct AuthRecord_struct AuthRecord;
4725ffb0c9Toomas Soometypedef struct ServiceRecordSet_struct ServiceRecordSet;
4735ffb0c9Toomas Soometypedef struct CacheRecord_struct CacheRecord;
4745ffb0c9Toomas Soometypedef struct CacheGroup_struct CacheGroup;
4755ffb0c9Toomas Soometypedef struct AuthGroup_struct AuthGroup;
4765ffb0c9Toomas Soometypedef struct DNSQuestion_struct DNSQuestion;
4775ffb0c9Toomas Soometypedef struct ZoneData_struct ZoneData;
4785ffb0c9Toomas Soometypedef struct mDNS_struct mDNS;
4795ffb0c9Toomas Soometypedef struct mDNS_PlatformSupport_struct mDNS_PlatformSupport;
4805ffb0c9Toomas Soometypedef struct NATTraversalInfo_struct NATTraversalInfo;
4815ffb0c9Toomas Soometypedef struct ResourceRecord_struct ResourceRecord;
4825ffb0c9Toomas Soome
4835ffb0c9Toomas Soome// Structure to abstract away the differences between TCP/SSL sockets, and one for UDP sockets
4845ffb0c9Toomas Soome// The actual definition of these structures appear in the appropriate platform support code
4855ffb0c9Toomas Soometypedef struct TCPSocket_struct TCPSocket;
4865ffb0c9Toomas Soometypedef struct UDPSocket_struct UDPSocket;
4874b22b93rs
4884b22b93rs// ***************************************************************************
4894b22b93rs#if 0
4905ffb0c9Toomas Soome#pragma mark -
4914b22b93rs#pragma mark - DNS Message structures
4924b22b93rs#endif
4934b22b93rs
4944b22b93rs#define mDNS_numZones   numQuestions
4954b22b93rs#define mDNS_numPrereqs numAnswers
4964b22b93rs#define mDNS_numUpdates numAuthorities
4974b22b93rs
498c65ebfcToomas Soometypedef struct
4995ffb0c9Toomas Soome{
5005ffb0c9Toomas Soome    mDNSOpaque16 id;
5015ffb0c9Toomas Soome    mDNSOpaque16 flags;
5025ffb0c9Toomas Soome    mDNSu16 numQuestions;
5035ffb0c9Toomas Soome    mDNSu16 numAnswers;
5045ffb0c9Toomas Soome    mDNSu16 numAuthorities;
5055ffb0c9Toomas Soome    mDNSu16 numAdditionals;
5065ffb0c9Toomas Soome} DNSMessageHeader;
5074b22b93rs
5084b22b93rs// We can send and receive packets up to 9000 bytes (Ethernet Jumbo Frame size, if that ever becomes widely used)
5094b22b93rs// However, in the normal case we try to limit packets to 1500 bytes so that we don't get IP fragmentation on standard Ethernet
5104b22b93rs// 40 (IPv6 header) + 8 (UDP header) + 12 (DNS message header) + 1440 (DNS message body) = 1500 total
5115ffb0c9Toomas Soome#ifndef AbsoluteMaxDNSMessageData
5124b22b93rs#define AbsoluteMaxDNSMessageData 8940
5135ffb0c9Toomas Soome#endif
5144b22b93rs#define NormalMaxDNSMessageData 1440
515c65ebfcToomas Soometypedef struct
5165ffb0c9Toomas Soome{
5175ffb0c9Toomas Soome    DNSMessageHeader h;                     // Note: Size 12 bytes
5185ffb0c9Toomas Soome    mDNSu8 data[AbsoluteMaxDNSMessageData]; // 40 (IPv6) + 8 (UDP) + 12 (DNS header) + 8940 (data) = 9000
5195ffb0c9Toomas Soome} DNSMessage;
5205ffb0c9Toomas Soome
5215ffb0c9Toomas Soometypedef struct tcpInfo_t
5225ffb0c9Toomas Soome{
5235ffb0c9Toomas Soome    mDNS             *m;
5245ffb0c9Toomas Soome    TCPSocket        *sock;
5255ffb0c9Toomas Soome    DNSMessage request;
5265ffb0c9Toomas Soome    int requestLen;
5275ffb0c9Toomas Soome    DNSQuestion      *question;   // For queries
5285ffb0c9Toomas Soome    AuthRecord       *rr;         // For record updates
5295ffb0c9Toomas Soome    mDNSAddr Addr;
5305ffb0c9Toomas Soome    mDNSIPPort Port;
5315ffb0c9Toomas Soome    mDNSIPPort SrcPort;
5325ffb0c9Toomas Soome    DNSMessage       *reply;
5335ffb0c9Toomas Soome    mDNSu16 replylen;
5345ffb0c9Toomas Soome    unsigned long nread;
5355ffb0c9Toomas Soome    int numReplies;
5365ffb0c9Toomas Soome} tcpInfo_t;
5375ffb0c9Toomas Soome
5385ffb0c9Toomas Soome// ***************************************************************************
5395ffb0c9Toomas Soome#if 0
5405ffb0c9Toomas Soome#pragma mark -
5415ffb0c9Toomas Soome#pragma mark - Other Packet Format Structures
5425ffb0c9Toomas Soome#endif
5435ffb0c9Toomas Soome
5445ffb0c9Toomas Soometypedef packedstruct
5455ffb0c9Toomas Soome{
5465ffb0c9Toomas Soome    mDNSEthAddr dst;
5475ffb0c9Toomas Soome    mDNSEthAddr src;
5485ffb0c9Toomas Soome    mDNSOpaque16 ethertype;
5495ffb0c9Toomas Soome} EthernetHeader;           // 14 bytes
5505ffb0c9Toomas Soome
5515ffb0c9Toomas Soometypedef packedstruct
5525ffb0c9Toomas Soome{
5535ffb0c9Toomas Soome    mDNSOpaque16 hrd;
5545ffb0c9Toomas Soome    mDNSOpaque16 pro;
5555ffb0c9Toomas Soome    mDNSu8 hln;
5565ffb0c9Toomas Soome    mDNSu8 pln;
5575ffb0c9Toomas Soome    mDNSOpaque16 op;
5585ffb0c9Toomas Soome    mDNSEthAddr sha;
5595ffb0c9Toomas Soome    mDNSv4Addr spa;
5605ffb0c9Toomas Soome    mDNSEthAddr tha;
5615ffb0c9Toomas Soome    mDNSv4Addr tpa;
5625ffb0c9Toomas Soome} ARP_EthIP;                // 28 bytes
5635ffb0c9Toomas Soome
5645ffb0c9Toomas Soometypedef packedstruct
5655ffb0c9Toomas Soome{
5665ffb0c9Toomas Soome    mDNSu8 vlen;
5675ffb0c9Toomas Soome    mDNSu8 tos;
568cda73f6Toomas Soome    mDNSOpaque16 totlen;
5695ffb0c9Toomas Soome    mDNSOpaque16 id;
5705ffb0c9Toomas Soome    mDNSOpaque16 flagsfrags;
5715ffb0c9Toomas Soome    mDNSu8 ttl;
5725ffb0c9Toomas Soome    mDNSu8 protocol;        // Payload type: 0x06 = TCP, 0x11 = UDP
5735ffb0c9Toomas Soome    mDNSu16 checksum;
5745ffb0c9Toomas Soome    mDNSv4Addr src;
5755ffb0c9Toomas Soome    mDNSv4Addr dst;
5765ffb0c9Toomas Soome} IPv4Header;               // 20 bytes
5775ffb0c9Toomas Soome
5785ffb0c9Toomas Soometypedef packedstruct
5795ffb0c9Toomas Soome{
5805ffb0c9Toomas Soome    mDNSu32 vcf;            // Version, Traffic Class, Flow Label
5815ffb0c9Toomas Soome    mDNSu16 len;            // Payload Length
5825ffb0c9Toomas Soome    mDNSu8 pro;             // Type of next header: 0x06 = TCP, 0x11 = UDP, 0x3A = ICMPv6
5835ffb0c9Toomas Soome    mDNSu8 ttl;             // Hop Limit
5845ffb0c9Toomas Soome    mDNSv6Addr src;
5855ffb0c9Toomas Soome    mDNSv6Addr dst;
5865ffb0c9Toomas Soome} IPv6Header;               // 40 bytes
5875ffb0c9Toomas Soome
5885ffb0c9Toomas Soometypedef packedstruct
5895ffb0c9Toomas Soome{
5905ffb0c9Toomas Soome    mDNSv6Addr src;
5915ffb0c9Toomas Soome    mDNSv6Addr dst;
5925ffb0c9Toomas Soome    mDNSOpaque32 len;
5935ffb0c9Toomas Soome    mDNSOpaque32 pro;
5945ffb0c9Toomas Soome} IPv6PseudoHeader;         // 40 bytes
5955ffb0c9Toomas Soome
5965ffb0c9Toomas Soometypedef union
5975ffb0c9Toomas Soome{
5985ffb0c9Toomas Soome    mDNSu8 bytes[20];
5995ffb0c9Toomas Soome    ARP_EthIP arp;
6005ffb0c9Toomas Soome    IPv4Header v4;
6015ffb0c9Toomas Soome    IPv6Header v6;
6025ffb0c9Toomas Soome} NetworkLayerPacket;
6035ffb0c9Toomas Soome
6045ffb0c9Toomas Soometypedef packedstruct
6055ffb0c9Toomas Soome{
6065ffb0c9Toomas Soome    mDNSIPPort src;
6075ffb0c9Toomas Soome    mDNSIPPort dst;
6085ffb0c9Toomas Soome    mDNSu32 seq;
6095ffb0c9Toomas Soome    mDNSu32 ack;
6105ffb0c9Toomas Soome    mDNSu8 offset;
6115ffb0c9Toomas Soome    mDNSu8 flags;
6125ffb0c9Toomas Soome    mDNSu16 window;
6135ffb0c9Toomas Soome    mDNSu16 checksum;
6145ffb0c9Toomas Soome    mDNSu16 urgent;
6155ffb0c9Toomas Soome} TCPHeader;                // 20 bytes; IP protocol type 0x06
6165ffb0c9Toomas Soome
6175ffb0c9Toomas Soometypedef struct
6185ffb0c9Toomas Soome{
6195ffb0c9Toomas Soome    mDNSInterfaceID IntfId;
6205ffb0c9Toomas Soome    mDNSu32 seq;
6215ffb0c9Toomas Soome    mDNSu32 ack;
6225ffb0c9Toomas Soome    mDNSu16 window;
6235ffb0c9Toomas Soome} mDNSTCPInfo;
6245ffb0c9Toomas Soome
6255ffb0c9Toomas Soometypedef packedstruct
6265ffb0c9Toomas Soome{
6275ffb0c9Toomas Soome    mDNSIPPort src;
6285ffb0c9Toomas Soome    mDNSIPPort dst;
6295ffb0c9Toomas Soome    mDNSu16 len;            // Length including UDP header (i.e. minimum value is 8 bytes)
6305ffb0c9Toomas Soome    mDNSu16 checksum;
6315ffb0c9Toomas Soome} UDPHeader;                // 8 bytes; IP protocol type 0x11
6325ffb0c9Toomas Soome
633c65ebfcToomas Soometypedef struct
6345ffb0c9Toomas Soome{
6355ffb0c9Toomas Soome    mDNSu8 type;            // 0x87 == Neighbor Solicitation, 0x88 == Neighbor Advertisement
6365ffb0c9Toomas Soome    mDNSu8 code;
6375ffb0c9Toomas Soome    mDNSu16 checksum;
6385ffb0c9Toomas Soome    mDNSu32 flags_res;      // R/S/O flags and reserved bits
6395ffb0c9Toomas Soome    mDNSv6Addr target;
6405ffb0c9Toomas Soome    // Typically 8 bytes of options are also present
6415ffb0c9Toomas Soome} IPv6NDP;                  // 24 bytes or more; IP protocol type 0x3A
6425ffb0c9Toomas Soome
6435ffb0c9Toomas Soometypedef struct
6445ffb0c9Toomas Soome{
6455ffb0c9Toomas Soome    mDNSAddr    ipaddr;
6465ffb0c9Toomas Soome    char        ethaddr[18];
6475ffb0c9Toomas Soome} IPAddressMACMapping;
6485ffb0c9Toomas Soome
6495ffb0c9Toomas Soome#define NDP_Sol 0x87
6505ffb0c9Toomas Soome#define NDP_Adv 0x88
6515ffb0c9Toomas Soome
6525ffb0c9Toomas Soome#define NDP_Router    0x80
6535ffb0c9Toomas Soome#define NDP_Solicited 0x40
6545ffb0c9Toomas Soome#define NDP_Override  0x20
6555ffb0c9Toomas Soome
6565ffb0c9Toomas Soome#define NDP_SrcLL 1
6575ffb0c9Toomas Soome#define NDP_TgtLL 2
6585ffb0c9Toomas Soome
6595ffb0c9Toomas Soometypedef union
6605ffb0c9Toomas Soome{
6615ffb0c9Toomas Soome    mDNSu8 bytes[20];
6625ffb0c9Toomas Soome    TCPHeader tcp;
6635ffb0c9Toomas Soome    UDPHeader udp;
6645ffb0c9Toomas Soome    IPv6NDP ndp;
6655ffb0c9Toomas Soome} TransportLayerPacket;
6665ffb0c9Toomas Soome
6675ffb0c9Toomas Soometypedef packedstruct
6685ffb0c9Toomas Soome{
6695ffb0c9Toomas Soome    mDNSOpaque64 InitiatorCookie;
6705ffb0c9Toomas Soome    mDNSOpaque64 ResponderCookie;
6715ffb0c9Toomas Soome    mDNSu8 NextPayload;
6725ffb0c9Toomas Soome    mDNSu8 Version;
6735ffb0c9Toomas Soome    mDNSu8 ExchangeType;
6745ffb0c9Toomas Soome    mDNSu8 Flags;
6755ffb0c9Toomas Soome    mDNSOpaque32 MessageID;
6765ffb0c9Toomas Soome    mDNSu32 Length;
6775ffb0c9Toomas Soome} IKEHeader;                // 28 bytes
6784b22b93rs
6794b22b93rs// ***************************************************************************
6804b22b93rs#if 0
6815ffb0c9Toomas Soome#pragma mark -
6824b22b93rs#pragma mark - Resource Record structures
6834b22b93rs#endif
6844b22b93rs
6854b22b93rs// Authoritative Resource Records:
6864b22b93rs// There are four basic types: Shared, Advisory, Unique, Known Unique
6874b22b93rs
6884b22b93rs// * Shared Resource Records do not have to be unique
6894b22b93rs// -- Shared Resource Records are used for DNS-SD service PTRs
6904b22b93rs// -- It is okay for several hosts to have RRs with the same name but different RDATA
6914b22b93rs// -- We use a random delay on responses to reduce collisions when all the hosts respond to the same query
6924b22b93rs// -- These RRs typically have moderately high TTLs (e.g. one hour)
6934b22b93rs// -- These records are announced on startup and topology changes for the benefit of passive listeners
6944b22b93rs// -- These records send a goodbye packet when deregistering
6954b22b93rs//
6964b22b93rs// * Advisory Resource Records are like Shared Resource Records, except they don't send a goodbye packet
6974b22b93rs//
6984b22b93rs// * Unique Resource Records should be unique among hosts within any given mDNS scope
6994b22b93rs// -- The majority of Resource Records are of this type
7004b22b93rs// -- If two entities on the network have RRs with the same name but different RDATA, this is a conflict
7014b22b93rs// -- Responses may be sent immediately, because only one host should be responding to any particular query
7024b22b93rs// -- These RRs typically have low TTLs (e.g. a few minutes)
7034b22b93rs// -- On startup and after topology changes, a host issues queries to verify uniqueness
7044b22b93rs
7054b22b93rs// * Known Unique Resource Records are treated like Unique Resource Records, except that mDNS does
7064b22b93rs// not have to verify their uniqueness because this is already known by other means (e.g. the RR name
7074b22b93rs// is derived from the host's IP or Ethernet address, which is already known to be a unique identifier).
7084b22b93rs
7094b22b93rs// Summary of properties of different record types:
7104b22b93rs// Probe?    Does this record type send probes before announcing?
7114b22b93rs// Conflict? Does this record type react if we observe an apparent conflict?
7124b22b93rs// Goodbye?  Does this record type send a goodbye packet on departure?
7134b22b93rs//
7144b22b93rs//               Probe? Conflict? Goodbye? Notes
7154b22b93rs// Unregistered                            Should not appear in any list (sanity check value)
7164b22b93rs// Shared         No      No       Yes     e.g. Service PTR record
7174b22b93rs// Deregistering  No      No       Yes     Shared record about to announce its departure and leave the list
7184b22b93rs// Advisory       No      No       No
7194b22b93rs// Unique         Yes     Yes      No      Record intended to be unique -- will probe to verify
7204b22b93rs// Verified       Yes     Yes      No      Record has completed probing, and is verified unique
7214b22b93rs// KnownUnique    No      Yes      No      Record is assumed by other means to be unique
7224b22b93rs
7234b22b93rs// Valid lifecycle of a record:
7244b22b93rs// Unregistered ->                   Shared      -> Deregistering -(goodbye)-> Unregistered
7254b22b93rs// Unregistered ->                   Advisory                               -> Unregistered
7264b22b93rs// Unregistered -> Unique -(probe)-> Verified                               -> Unregistered
7274b22b93rs// Unregistered ->                   KnownUnique                            -> Unregistered
7284b22b93rs
7294b22b93rs// Each Authoritative kDNSRecordType has only one bit set. This makes it easy to quickly see if a record
7304b22b93rs// is one of a particular set of types simply by performing the appropriate bitwise masking operation.
7314b22b93rs
7325ffb0c9Toomas Soome// Cache Resource Records (received from the network):
7335ffb0c9Toomas Soome// There are four basic types: Answer, Unique Answer, Additional, Unique Additional
7345ffb0c9Toomas Soome// Bit 7 (the top bit) of kDNSRecordType is always set for Cache Resource Records; always clear for Authoritative Resource Records
7355ffb0c9Toomas Soome// Bit 6 (value 0x40) is set for answer records; clear for authority/additional records
7365ffb0c9Toomas Soome// Bit 5 (value 0x20) is set for records received with the kDNSClass_UniqueRRSet
7375ffb0c9Toomas Soome
738c65ebfcToomas Soometypedef enum
7395ffb0c9Toomas Soome{
7405ffb0c9Toomas Soome    kDNSRecordTypeUnregistered     = 0x00,  // Not currently in any list
7415ffb0c9Toomas Soome    kDNSRecordTypeDeregistering    = 0x01,  // Shared record about to announce its departure and leave the list
7425ffb0c9Toomas Soome
7435ffb0c9Toomas Soome    kDNSRecordTypeUnique           = 0x02,  // Will become a kDNSRecordTypeVerified when probing is complete
7445ffb0c9Toomas Soome
7455ffb0c9Toomas Soome    kDNSRecordTypeAdvisory         = 0x04,  // Like Shared, but no goodbye packet
7465ffb0c9Toomas Soome    kDNSRecordTypeShared           = 0x08,  // Shared means record name does not have to be unique -- use random delay on responses
7475ffb0c9Toomas Soome
7485ffb0c9Toomas Soome    kDNSRecordTypeVerified         = 0x10,  // Unique means mDNS should check that name is unique (and then send immediate responses)
7495ffb0c9Toomas Soome    kDNSRecordTypeKnownUnique      = 0x20,  // Known Unique means mDNS can assume name is unique without checking
7505ffb0c9Toomas Soome                                            // For Dynamic Update records, Known Unique means the record must already exist on the server.
7515ffb0c9Toomas Soome    kDNSRecordTypeUniqueMask       = (kDNSRecordTypeUnique | kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique),
7525ffb0c9Toomas Soome    kDNSRecordTypeActiveSharedMask = (kDNSRecordTypeAdvisory         | kDNSRecordTypeShared),
7535ffb0c9Toomas Soome    kDNSRecordTypeActiveUniqueMask = (kDNSRecordTypeVerified         | kDNSRecordTypeKnownUnique),
7545ffb0c9Toomas Soome    kDNSRecordTypeActiveMask       = (kDNSRecordTypeActiveSharedMask | kDNSRecordTypeActiveUniqueMask),
7555ffb0c9Toomas Soome
7565ffb0c9Toomas Soome    kDNSRecordTypePacketAdd        = 0x80,  // Received in the Additional  Section of a DNS Response
7575ffb0c9Toomas Soome    kDNSRecordTypePacketAddUnique  = 0x90,  // Received in the Additional  Section of a DNS Response with kDNSClass_UniqueRRSet set
7585ffb0c9Toomas Soome    kDNSRecordTypePacketAuth       = 0xA0,  // Received in the Authorities Section of a DNS Response
7595ffb0c9Toomas Soome    kDNSRecordTypePacketAuthUnique = 0xB0,  // Received in the Authorities Section of a DNS Response with kDNSClass_UniqueRRSet set
7605ffb0c9Toomas Soome    kDNSRecordTypePacketAns        = 0xC0,  // Received in the Answer      Section of a DNS Response
7615ffb0c9Toomas Soome    kDNSRecordTypePacketAnsUnique  = 0xD0,  // Received in the Answer      Section of a DNS Response with kDNSClass_UniqueRRSet set
7625ffb0c9Toomas Soome
7635ffb0c9Toomas Soome    kDNSRecordTypePacketNegative   = 0xF0,  // Pseudo-RR generated to cache non-existence results like NXDomain
7645ffb0c9Toomas Soome
7655ffb0c9Toomas Soome    kDNSRecordTypePacketUniqueMask = 0x10   // True for PacketAddUnique, PacketAnsUnique, PacketAuthUnique, kDNSRecordTypePacketNegative
766c65ebfcToomas Soome} kDNSRecordTypes;
7675ffb0c9Toomas Soome
7685ffb0c9Toomas Soometypedef packedstruct { mDNSu16 priority; mDNSu16 weight; mDNSIPPort port; domainname target;   } rdataSRV;
7695ffb0c9Toomas Soometypedef packedstruct { mDNSu16 preference;                                domainname exchange; } rdataMX;
7705ffb0c9Toomas Soometypedef packedstruct { domainname mbox; domainname txt;                                        } rdataRP;
7715ffb0c9Toomas Soometypedef packedstruct { mDNSu16 preference; domainname map822; domainname mapx400;              } rdataPX;
7725ffb0c9Toomas Soome
7735ffb0c9Toomas Soometypedef packedstruct
7745ffb0c9Toomas Soome{
7755ffb0c9Toomas Soome    domainname mname;
7765ffb0c9Toomas Soome    domainname rname;
7775ffb0c9Toomas Soome    mDNSs32 serial;     // Modular counter; increases when zone changes
7785ffb0c9Toomas Soome    mDNSu32 refresh;    // Time in seconds that a slave waits after successful replication of the database before it attempts replication again
7795ffb0c9Toomas Soome    mDNSu32 retry;      // Time in seconds that a slave waits after an unsuccessful replication attempt before it attempts replication again
7805ffb0c9Toomas Soome    mDNSu32 expire;     // Time in seconds that a slave holds on to old data while replication attempts remain unsuccessful
7815ffb0c9Toomas Soome    mDNSu32 min;        // Nominally the minimum record TTL for this zone, in seconds; also used for negative caching.
7825ffb0c9Toomas Soome} rdataSOA;
7835ffb0c9Toomas Soome
7845ffb0c9Toomas Soome// http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
7855ffb0c9Toomas Soome// Algorithm used for RRSIG, DS and DNS KEY
7865ffb0c9Toomas Soome#define CRYPTO_RSA_SHA1             0x05
7875ffb0c9Toomas Soome#define CRYPTO_DSA_NSEC3_SHA1       0x06
7885ffb0c9Toomas Soome#define CRYPTO_RSA_NSEC3_SHA1       0x07
7895ffb0c9Toomas Soome#define CRYPTO_RSA_SHA256           0x08
7905ffb0c9Toomas Soome#define CRYPTO_RSA_SHA512           0x0A
7915ffb0c9Toomas Soome
7925ffb0c9Toomas Soome#define CRYPTO_ALG_MAX              0x0B
7935ffb0c9Toomas Soome
7945ffb0c9Toomas Soome// alg - same as in RRSIG, DNS KEY or DS.
7955ffb0c9Toomas Soome// RFC 4034 defines SHA1
7965ffb0c9Toomas Soome// RFC 4509 defines SHA256
7975ffb0c9Toomas Soome// Note: NSEC3 also uses 1 for SHA1 and hence we will reuse for now till a new
7985ffb0c9Toomas Soome// value is assigned.
7995ffb0c9Toomas Soome//
8005ffb0c9Toomas Soome#define SHA1_DIGEST_TYPE        1
8015ffb0c9Toomas Soome#define SHA256_DIGEST_TYPE      2
8025ffb0c9Toomas Soome#define DIGEST_TYPE_MAX         3
8035ffb0c9Toomas Soome
8045ffb0c9Toomas Soome// We need support for base64 and base32 encoding for displaying KEY, NSEC3
8055ffb0c9Toomas Soome// To make this platform agnostic, we define two types which the platform
8065ffb0c9Toomas Soome// needs to support
8075ffb0c9Toomas Soome#define ENC_BASE32              1
8085ffb0c9Toomas Soome#define ENC_BASE64              2
8095ffb0c9Toomas Soome#define ENC_ALG_MAX             3
8105ffb0c9Toomas Soome
8115ffb0c9Toomas Soome#define DS_FIXED_SIZE           4
8125ffb0c9Toomas Soometypedef packedstruct
8135ffb0c9Toomas Soome{
8145ffb0c9Toomas Soome    mDNSu16 keyTag;
8155ffb0c9Toomas Soome    mDNSu8 alg;
8165ffb0c9Toomas Soome    mDNSu8 digestType;
8175ffb0c9Toomas Soome    mDNSu8  *digest;
8185ffb0c9Toomas Soome} rdataDS;
8195ffb0c9Toomas Soome
8205ffb0c9Toomas Soometypedef struct TrustAnchor
8215ffb0c9Toomas Soome{
8225ffb0c9Toomas Soome    struct TrustAnchor *next;
8235ffb0c9Toomas Soome    int digestLen;
8245ffb0c9Toomas Soome    mDNSu32 validFrom;
825c65ebfcToomas Soome    mDNSu32 validUntil;
8265ffb0c9Toomas Soome    domainname zone;
8275ffb0c9Toomas Soome    rdataDS rds;
8285ffb0c9Toomas Soome} TrustAnchor;
8295ffb0c9Toomas Soome
8305ffb0c9Toomas Soome//size of rdataRRSIG excluding signerName and signature (which are variable fields)
8315ffb0c9Toomas Soome#define RRSIG_FIXED_SIZE      18
832c65ebfcToomas Soometypedef struct
8335ffb0c9Toomas Soome{
8345ffb0c9Toomas Soome    mDNSu16 typeCovered;
8355ffb0c9Toomas Soome    mDNSu8 alg;
8365ffb0c9Toomas Soome    mDNSu8 labels;
8375ffb0c9Toomas Soome    mDNSu32 origTTL;
8385ffb0c9Toomas Soome    mDNSu32 sigExpireTime;
8395ffb0c9Toomas Soome    mDNSu32 sigInceptTime;
8405ffb0c9Toomas Soome    mDNSu16 keyTag;
841c65ebfcToomas Soome    mDNSu8  signerName[1]; // signerName is a dynamically-sized array
8425ffb0c9Toomas Soome    // mDNSu8 *signature
8435ffb0c9Toomas Soome} rdataRRSig;
8445ffb0c9Toomas Soome
8455ffb0c9Toomas Soome// RFC 4034: For DNS Key RR
8465ffb0c9Toomas Soome// flags - the valid value for DNSSEC is 256 (Zone signing key - ZSK) and 257 (Secure Entry Point) which also
8475ffb0c9Toomas Soome// includes the ZSK bit
8485ffb0c9Toomas Soome//
8495ffb0c9Toomas Soome#define DNSKEY_ZONE_SIGN_KEY        0x100
8505ffb0c9Toomas Soome#define DNSKEY_SECURE_ENTRY_POINT   0x101
8515ffb0c9Toomas Soome
8525ffb0c9Toomas Soome// proto - the only valid value for protocol is 3 (See RFC 4034)
8535ffb0c9Toomas Soome#define DNSKEY_VALID_PROTO_VALUE    0x003
8545ffb0c9Toomas Soome
8555ffb0c9Toomas Soome// alg - The only mandatory algorithm that we support is RSA/SHA-1
8565ffb0c9Toomas Soome// DNSSEC_RSA_SHA1_ALG
8575ffb0c9Toomas Soome
8585ffb0c9Toomas Soome#define DNSKEY_FIXED_SIZE          4
8595ffb0c9Toomas Soometypedef packedstruct
8605ffb0c9Toomas Soome{
8615ffb0c9Toomas Soome    mDNSu16 flags;
8625ffb0c9Toomas Soome    mDNSu8 proto;
8635ffb0c9Toomas Soome    mDNSu8 alg;
8645ffb0c9Toomas Soome    mDNSu8  *data;
8655ffb0c9Toomas Soome} rdataDNSKey;
8665ffb0c9Toomas Soome
8675ffb0c9Toomas Soome#define NSEC3_FIXED_SIZE          5
8685ffb0c9Toomas Soome#define NSEC3_FLAGS_OPTOUT        1
8695ffb0c9Toomas Soome#define NSEC3_MAX_ITERATIONS      2500
8705ffb0c9Toomas Soometypedef packedstruct
8715ffb0c9Toomas Soome{
8725ffb0c9Toomas Soome    mDNSu8 alg;
8735ffb0c9Toomas Soome    mDNSu8 flags;
8745ffb0c9Toomas Soome    mDNSu16 iterations;
8755ffb0c9Toomas Soome    mDNSu8 saltLength;
8765ffb0c9Toomas Soome    mDNSu8 *salt;
8775ffb0c9Toomas Soome    // hashLength, nxt, bitmap
8785ffb0c9Toomas Soome} rdataNSEC3;
8795ffb0c9Toomas Soome
8805ffb0c9Toomas Soome// In the multicast usage of NSEC3, we know the actual size of RData
8815ffb0c9Toomas Soome// 4 bytes : HashAlg, Flags,Iterations
8825ffb0c9Toomas Soome// 5 bytes : Salt Length 1 byte, Salt 4 bytes
8835ffb0c9Toomas Soome// 21 bytes : HashLength 1 byte, Hash 20 bytes
8845ffb0c9Toomas Soome// 34 bytes : Window number, Bitmap length, Type bit map to include the first 256 types
8855ffb0c9Toomas Soome#define MCAST_NSEC3_RDLENGTH (4 + 5 + 21 + 34)
8865ffb0c9Toomas Soome#define SHA1_HASH_LENGTH 20
8875ffb0c9Toomas Soome
8885ffb0c9Toomas Soome// Base32 encoding takes 5 bytes of the input and encodes as 8 bytes of output.
8895ffb0c9Toomas Soome// For example, SHA-1 hash of 20 bytes will be encoded as 20/5 * 8 = 32 base32
8905ffb0c9Toomas Soome// bytes. For a max domain name size of 255 bytes of base32 encoding : (255/8)*5
8915ffb0c9Toomas Soome// is the max hash length possible.
892c65ebfcToomas Soome#define NSEC3_MAX_HASH_LEN  155
8935ffb0c9Toomas Soome// In NSEC3, the names are hashed and stored in the first label and hence cannot exceed label
8945ffb0c9Toomas Soome// size.
895c65ebfcToomas Soome#define NSEC3_MAX_B32_LEN   MAX_DOMAIN_LABEL
8965ffb0c9Toomas Soome
8975ffb0c9Toomas Soome// We define it here instead of dnssec.h so that these values can be used
8985ffb0c9Toomas Soome// in files without bringing in all of dnssec.h unnecessarily.
8995ffb0c9Toomas Soometypedef enum
9005ffb0c9Toomas Soome{
9015ffb0c9Toomas Soome    DNSSEC_Secure = 1,      // Securely validated and has a chain up to the trust anchor
9025ffb0c9Toomas Soome    DNSSEC_Insecure,        // Cannot build a chain up to the trust anchor
9035ffb0c9Toomas Soome    DNSSEC_Indeterminate,   // Not used currently
9045ffb0c9Toomas Soome    DNSSEC_Bogus,           // failed to validate signatures
9055ffb0c9Toomas Soome    DNSSEC_NoResponse       // No DNSSEC records to start with
9065ffb0c9Toomas Soome} DNSSECStatus;
9075ffb0c9Toomas Soome
9085ffb0c9Toomas Soome#define DNSSECRecordType(rrtype) (((rrtype) == kDNSType_RRSIG) || ((rrtype) == kDNSType_NSEC) || ((rrtype) == kDNSType_DNSKEY) || ((rrtype) == kDNSType_DS) || \
9095ffb0c9Toomas Soome                                  ((rrtype) == kDNSType_NSEC3))
9105ffb0c9Toomas Soome
9115ffb0c9Toomas Soometypedef enum
9125ffb0c9Toomas Soome{
913c65ebfcToomas Soome    platform_OSX = 1,   // OSX Platform
914c65ebfcToomas Soome    platform_iOS,       // iOS Platform
915c65ebfcToomas Soome    platform_Atv,       // Atv Platform
9165ffb0c9Toomas Soome    platform_NonApple   // Non-Apple (Windows, POSIX) Platform
9175ffb0c9Toomas Soome} Platform_t;
9185ffb0c9Toomas Soome
9195ffb0c9Toomas Soome// EDNS Option Code registrations are recorded in the "DNS EDNS0 Options" section of
9205ffb0c9Toomas Soome// <http://www.iana.org/assignments/dns-parameters>
9215ffb0c9Toomas Soome
9225ffb0c9Toomas Soome#define kDNSOpt_LLQ   1
9235ffb0c9Toomas Soome#define kDNSOpt_Lease 2
9245ffb0c9Toomas Soome#define kDNSOpt_NSID  3
9255ffb0c9Toomas Soome#define kDNSOpt_Owner 4
926c65ebfcToomas Soome#define kDNSOpt_Trace 65001  // 65001-65534 Reserved for Local/Experimental Use
9275ffb0c9Toomas Soome
9285ffb0c9Toomas Soometypedef struct
9295ffb0c9Toomas Soome{
9305ffb0c9Toomas Soome    mDNSu16 vers;
9315ffb0c9Toomas Soome    mDNSu16 llqOp;
9325ffb0c9Toomas Soome    mDNSu16 err;        // Or UDP reply port, in setup request
9335ffb0c9Toomas 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
9345ffb0c9Toomas Soome    mDNSOpaque64 id;
9355ffb0c9Toomas Soome    mDNSu32 llqlease;
9365ffb0c9Toomas Soome} LLQOptData;
9375ffb0c9Toomas Soome
9385ffb0c9Toomas Soometypedef struct
9395ffb0c9Toomas Soome{
9405ffb0c9Toomas Soome    mDNSu8 vers;            // Version number of this Owner OPT record
9415ffb0c9Toomas Soome    mDNSs8 seq;             // Sleep/wake epoch
9425ffb0c9Toomas Soome    mDNSEthAddr HMAC;       // Host's primary identifier (e.g. MAC of on-board Ethernet)
9435ffb0c9Toomas Soome    mDNSEthAddr IMAC;       // Interface's MAC address (if different to primary MAC)
9445ffb0c9Toomas Soome    mDNSOpaque48 password;  // Optional password
9455ffb0c9Toomas Soome} OwnerOptData;
9465ffb0c9Toomas Soome
9475ffb0c9Toomas Soometypedef struct
9485ffb0c9Toomas Soome{
9495ffb0c9Toomas Soome    mDNSu8    platf;      // Running platform (see enum Platform_t)
9505ffb0c9Toomas Soome    mDNSu32   mDNSv;      // mDNSResponder Version (DNS_SD_H defined in dns_sd.h)
9515ffb0c9Toomas Soome} TracerOptData;
9525ffb0c9Toomas Soome
9535ffb0c9Toomas Soome// Note: rdataOPT format may be repeated an arbitrary number of times in a single resource record
954c65ebfcToomas Soometypedef struct
9555ffb0c9Toomas Soome{
9565ffb0c9Toomas Soome    mDNSu16 opt;
9575ffb0c9Toomas Soome    mDNSu16 optlen;
9585ffb0c9Toomas Soome    union { LLQOptData llq; mDNSu32 updatelease; OwnerOptData owner; TracerOptData tracer; } u;
9595ffb0c9Toomas Soome} rdataOPT;
9605ffb0c9Toomas Soome
9615ffb0c9Toomas Soome// Space needed to put OPT records into a packet:
9625ffb0c9Toomas Soome// Header         11  bytes (name 1, type 2, class 2, TTL 4, length 2)
9635ffb0c9Toomas Soome// LLQ   rdata    18  bytes (opt 2, len 2, vers 2, op 2, err 2, id 8, lease 4)
9645ffb0c9Toomas Soome// Lease rdata     8  bytes (opt 2, len 2, lease 4)
9655ffb0c9Toomas Soome// Owner rdata 12-24  bytes (opt 2, len 2, owner 8-20)
9665ffb0c9Toomas Soome// Trace rdata     9  bytes (opt 2, len 2, platf 1, mDNSv 4)
9675ffb0c9Toomas Soome
9685ffb0c9Toomas Soome
9695ffb0c9Toomas Soome#define DNSOpt_Header_Space                 11
9705ffb0c9Toomas Soome#define DNSOpt_LLQData_Space               (4 + 2 + 2 + 2 + 8 + 4)
9715ffb0c9Toomas Soome#define DNSOpt_LeaseData_Space             (4 + 4)
9725ffb0c9Toomas Soome#define DNSOpt_OwnerData_ID_Space          (4 + 2 + 6)
9735ffb0c9Toomas Soome#define DNSOpt_OwnerData_ID_Wake_Space     (4 + 2 + 6 + 6)
9745ffb0c9Toomas Soome#define DNSOpt_OwnerData_ID_Wake_PW4_Space (4 + 2 + 6 + 6 + 4)
9755ffb0c9Toomas Soome#define DNSOpt_OwnerData_ID_Wake_PW6_Space (4 + 2 + 6 + 6 + 6)
9765ffb0c9Toomas Soome#define DNSOpt_TraceData_Space             (4 + 1 + 4)
9775ffb0c9Toomas Soome
9785ffb0c9Toomas Soome#define ValidOwnerLength(X) (   (X) == DNSOpt_OwnerData_ID_Space          - 4 || \
9795ffb0c9Toomas Soome                                (X) == DNSOpt_OwnerData_ID_Wake_Space     - 4 || \
9805ffb0c9Toomas Soome                                (X) == DNSOpt_OwnerData_ID_Wake_PW4_Space - 4 || \
9815ffb0c9Toomas Soome                                (X) == DNSOpt_OwnerData_ID_Wake_PW6_Space - 4    )
9825ffb0c9Toomas Soome
9835ffb0c9Toomas Soome#define DNSOpt_Owner_Space(A,B) (mDNSSameEthAddress((A),(B)) ? DNSOpt_OwnerData_ID_Space : DNSOpt_OwnerData_ID_Wake_Space)
9845ffb0c9Toomas Soome
9855ffb0c9Toomas Soome#define DNSOpt_Data_Space(O) (                                  \
9865ffb0c9Toomas Soome        (O)->opt == kDNSOpt_LLQ   ? DNSOpt_LLQData_Space   :        \
9875ffb0c9Toomas Soome        (O)->opt == kDNSOpt_Lease ? DNSOpt_LeaseData_Space :        \
9885ffb0c9Toomas Soome        (O)->opt == kDNSOpt_Trace ? DNSOpt_TraceData_Space :        \
9895ffb0c9Toomas Soome        (O)->opt == kDNSOpt_Owner ? DNSOpt_Owner_Space(&(O)->u.owner.HMAC, &(O)->u.owner.IMAC) : 0x10000)
9905ffb0c9Toomas Soome
9915ffb0c9Toomas Soome// NSEC record is defined in RFC 4034.
9925ffb0c9Toomas Soome// 16 bit RRTYPE space is split into 256 windows and each window has 256 bits (32 bytes).
9935ffb0c9Toomas Soome// If we create a structure for NSEC, it's size would be:
9945ffb0c9Toomas Soome//
9955ffb0c9Toomas Soome//   256 bytes domainname 'nextname'
9965ffb0c9Toomas Soome// + 256 * 34 = 8704 bytes of bitmap data
9975ffb0c9Toomas Soome// = 8960 bytes total
9985ffb0c9Toomas Soome//
9995ffb0c9Toomas Soome// This would be a waste, as types about 256 are not very common. But it would be odd, if we receive
10005ffb0c9Toomas Soome// a type above 256 (.US zone had TYPE65534 when this code was written) and not able to handle it.
10015ffb0c9Toomas Soome// Hence, we handle any size by not fixing a strucure in place. The following is just a placeholder
10025ffb0c9Toomas Soome// and never used anywhere.
10035ffb0c9Toomas Soome//
10045ffb0c9Toomas Soome#define NSEC_MCAST_WINDOW_SIZE 32
10055ffb0c9Toomas Soometypedef struct
10065ffb0c9Toomas Soome{
10075ffb0c9Toomas Soome    domainname *next; //placeholders are uncommented because C89 in Windows requires that a struct has at least a member.
10085ffb0c9Toomas Soome    char bitmap[32];
10095ffb0c9Toomas Soome} rdataNSEC;
10105ffb0c9Toomas Soome
10115ffb0c9Toomas Soome// StandardAuthRDSize is 264 (256+8), which is large enough to hold a maximum-sized SRV record (6 + 256 bytes)
10125ffb0c9Toomas Soome// MaximumRDSize is 8K the absolute maximum we support (at least for now)
10135ffb0c9Toomas Soome#define StandardAuthRDSize 264
10145ffb0c9Toomas Soome#ifndef MaximumRDSize
10155ffb0c9Toomas Soome#define MaximumRDSize 8192
10165ffb0c9Toomas Soome#endif
10175ffb0c9Toomas Soome
10185ffb0c9Toomas Soome// InlineCacheRDSize is 68
10195ffb0c9Toomas Soome// Records received from the network with rdata this size or less have their rdata stored right in the CacheRecord object
10205ffb0c9Toomas Soome// Records received from the network with rdata larger than this have additional storage allocated for the rdata
10215ffb0c9Toomas Soome// A quick unscientific sample from a busy network at Apple with lots of machines revealed this:
10225ffb0c9Toomas Soome// 1461 records in cache
10235ffb0c9Toomas Soome// 292 were one-byte TXT records
10245ffb0c9Toomas Soome// 136 were four-byte A records
10255ffb0c9Toomas Soome// 184 were sixteen-byte AAAA records
10265ffb0c9Toomas Soome// 780 were various PTR, TXT and SRV records from 12-64 bytes
10275ffb0c9Toomas Soome// Only 69 records had rdata bigger than 64 bytes
10285ffb0c9Toomas Soome// Note that since CacheRecord object and a CacheGroup object are allocated out of the same pool, it's sensible to
10295ffb0c9Toomas Soome// have them both be the same size. Making one smaller without making the other smaller won't actually save any memory.
10305ffb0c9Toomas Soome#define InlineCacheRDSize 68
10315ffb0c9Toomas Soome
10325ffb0c9Toomas Soome// The RDataBody union defines the common rdata types that fit into our 264-byte limit
10335ffb0c9Toomas Soometypedef union
10345ffb0c9Toomas Soome{
10355ffb0c9Toomas Soome    mDNSu8 data[StandardAuthRDSize];
10365ffb0c9Toomas Soome    mDNSv4Addr ipv4;        // For 'A' record
10375ffb0c9Toomas Soome    domainname name;        // For PTR, NS, CNAME, DNAME
10385ffb0c9Toomas Soome    UTF8str255 txt;
10395ffb0c9Toomas Soome    rdataMX mx;
10405ffb0c9Toomas Soome    mDNSv6Addr ipv6;        // For 'AAAA' record
10415ffb0c9Toomas Soome    rdataSRV srv;
10425ffb0c9Toomas Soome    rdataOPT opt[2];        // For EDNS0 OPT record; RDataBody may contain multiple variable-length rdataOPT objects packed together
10435ffb0c9Toomas Soome} RDataBody;
10445ffb0c9Toomas Soome
10455ffb0c9Toomas Soome// The RDataBody2 union is the same as above, except it includes fields for the larger types like soa, rp, px
10465ffb0c9Toomas Soometypedef union
10475ffb0c9Toomas Soome{
10485ffb0c9Toomas Soome    mDNSu8 data[StandardAuthRDSize];
10495ffb0c9Toomas Soome    mDNSv4Addr ipv4;        // For 'A' record
10505ffb0c9Toomas Soome    domainname name;        // For PTR, NS, CNAME, DNAME
10515ffb0c9Toomas Soome    rdataSOA soa;           // This is large; not included in the normal RDataBody definition
10525ffb0c9Toomas Soome    UTF8str255 txt;
10535ffb0c9Toomas Soome    rdataMX mx;
10545ffb0c9Toomas Soome    rdataRP rp;             // This is large; not included in the normal RDataBody definition
10555ffb0c9Toomas Soome    rdataPX px;             // This is large; not included in the normal RDataBody definition
10565ffb0c9Toomas Soome    mDNSv6Addr ipv6;        // For 'AAAA' record
10575ffb0c9Toomas Soome    rdataSRV srv;
10585ffb0c9Toomas Soome    rdataOPT opt[2];        // For EDNS0 OPT record; RDataBody may contain multiple variable-length rdataOPT objects packed together
10595ffb0c9Toomas Soome    rdataDS ds;
10605ffb0c9Toomas Soome    rdataDNSKey key;
10615ffb0c9Toomas Soome    rdataRRSig rrsig;
10625ffb0c9Toomas Soome} RDataBody2;
10635ffb0c9Toomas Soome
10645ffb0c9Toomas Soometypedef struct
10655ffb0c9Toomas Soome{
10665ffb0c9Toomas Soome    mDNSu16 MaxRDLength;    // Amount of storage allocated for rdata (usually sizeof(RDataBody))
10675ffb0c9Toomas Soome    mDNSu16 padding;        // So that RDataBody is aligned on 32-bit boundary
10685ffb0c9Toomas Soome    RDataBody u;
10695ffb0c9Toomas Soome} RData;
10705ffb0c9Toomas Soome
10715ffb0c9Toomas Soome// sizeofRDataHeader should be 4 bytes
10725ffb0c9Toomas Soome#define sizeofRDataHeader (sizeof(RData) - sizeof(RDataBody))
10735ffb0c9Toomas Soome
10745ffb0c9Toomas Soome// RData_small is a smaller version of the RData object, used for inline data storage embedded in a CacheRecord_struct
10755ffb0c9Toomas Soometypedef struct
10765ffb0c9Toomas Soome{
10775ffb0c9Toomas Soome    mDNSu16 MaxRDLength;    // Storage allocated for data (may be greater than InlineCacheRDSize if additional storage follows this object)
10785ffb0c9Toomas Soome    mDNSu16 padding;        // So that data is aligned on 32-bit boundary
10795ffb0c9Toomas Soome    mDNSu8 data[InlineCacheRDSize];
10805ffb0c9Toomas Soome} RData_small;
10815ffb0c9Toomas Soome
10825ffb0c9Toomas Soome// Note: Within an mDNSRecordCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
10835ffb0c9Toomas Soometypedef void mDNSRecordCallback (mDNS *const m, AuthRecord *const rr, mStatus result);
10845ffb0c9Toomas Soome
10855ffb0c9Toomas Soome// Note:
10865ffb0c9Toomas Soome// Restrictions: An mDNSRecordUpdateCallback may not make any mDNS API calls.
10875ffb0c9Toomas Soome// The intent of this callback is to allow the client to free memory, if necessary.
10885ffb0c9Toomas Soome// The internal data structures of the mDNS code may not be in a state where mDNS API calls may be made safely.
10895ffb0c9Toomas Soometypedef void mDNSRecordUpdateCallback (mDNS *const m, AuthRecord *const rr, RData *OldRData, mDNSu16 OldRDLen);
10905ffb0c9Toomas Soome
10915ffb0c9Toomas Soome// ***************************************************************************
10925ffb0c9Toomas Soome#if 0
10935ffb0c9Toomas Soome#pragma mark -
10945ffb0c9Toomas Soome#pragma mark - NAT Traversal structures and constants
10955ffb0c9Toomas Soome#endif
10965ffb0c9Toomas Soome
10975ffb0c9Toomas Soome#define NATMAP_MAX_RETRY_INTERVAL    ((mDNSPlatformOneSecond * 60) * 15)    // Max retry interval is 15 minutes
10985ffb0c9Toomas Soome#define NATMAP_MIN_RETRY_INTERVAL     (mDNSPlatformOneSecond * 2)           // Min retry interval is 2 seconds
10995ffb0c9Toomas Soome#define NATMAP_INIT_RETRY             (mDNSPlatformOneSecond / 4)           // start at 250ms w/ exponential decay
11005ffb0c9Toomas Soome#define NATMAP_DEFAULT_LEASE          (60 * 60 * 2)                         // 2 hour lease life in seconds
11015ffb0c9Toomas Soome#define NATMAP_VERS 0
11025ffb0c9Toomas Soome
11035ffb0c9Toomas Soometypedef enum
11045ffb0c9Toomas Soome{
11055ffb0c9Toomas Soome    NATOp_AddrRequest    = 0,
11065ffb0c9Toomas Soome    NATOp_MapUDP         = 1,
11075ffb0c9Toomas Soome    NATOp_MapTCP         = 2,
11085ffb0c9Toomas Soome
11095ffb0c9Toomas Soome    NATOp_AddrResponse   = 0x80 | 0,
11105ffb0c9Toomas Soome    NATOp_MapUDPResponse = 0x80 | 1,
11115ffb0c9Toomas Soome    NATOp_MapTCPResponse = 0x80 | 2,
11125ffb0c9Toomas Soome} NATOp_t;
11135ffb0c9Toomas Soome
11145ffb0c9Toomas Soomeenum
11155ffb0c9Toomas Soome{
11165ffb0c9Toomas Soome    NATErr_None    = 0,
11175ffb0c9Toomas Soome    NATErr_Vers    = 1,
11185ffb0c9Toomas Soome    NATErr_Refused = 2,
11195ffb0c9Toomas Soome    NATErr_NetFail = 3,
11205ffb0c9Toomas Soome    NATErr_Res     = 4,
11215ffb0c9Toomas Soome    NATErr_Opcode  = 5
11225ffb0c9Toomas Soome};
11235ffb0c9Toomas Soome
11245ffb0c9Toomas Soometypedef mDNSu16 NATErr_t;
11255ffb0c9Toomas Soome
11265ffb0c9Toomas Soometypedef packedstruct
11275ffb0c9Toomas Soome{
11285ffb0c9Toomas Soome    mDNSu8 vers;
11295ffb0c9Toomas Soome    mDNSu8 opcode;
11305ffb0c9Toomas Soome} NATAddrRequest;
11315ffb0c9Toomas Soome
11325ffb0c9Toomas Soometypedef packedstruct
11335ffb0c9Toomas Soome{
11345ffb0c9Toomas Soome    mDNSu8 vers;
11355ffb0c9Toomas Soome    mDNSu8 opcode;
11365ffb0c9Toomas Soome    mDNSu16 err;
11375ffb0c9Toomas Soome    mDNSu32 upseconds;          // Time since last NAT engine reboot, in seconds
11385ffb0c9Toomas Soome    mDNSv4Addr ExtAddr;
11395ffb0c9Toomas Soome} NATAddrReply;
11405ffb0c9Toomas Soome
11415ffb0c9Toomas Soometypedef packedstruct
11425ffb0c9Toomas Soome{
11435ffb0c9Toomas Soome    mDNSu8 vers;
11445ffb0c9Toomas Soome    mDNSu8 opcode;
11455ffb0c9Toomas Soome    mDNSOpaque16 unused;
11465ffb0c9Toomas Soome    mDNSIPPort intport;
11475ffb0c9Toomas Soome    mDNSIPPort extport;
11485ffb0c9Toomas Soome    mDNSu32 NATReq_lease;
11495ffb0c9Toomas Soome} NATPortMapRequest;
11504b22b93rs
11515ffb0c9Toomas Soometypedef packedstruct
11525ffb0c9Toomas Soome{
11535ffb0c9Toomas Soome    mDNSu8 vers;
11545ffb0c9Toomas Soome    mDNSu8 opcode;
11555ffb0c9Toomas Soome    mDNSu16 err;
11565ffb0c9Toomas Soome    mDNSu32 upseconds;          // Time since last NAT engine reboot, in seconds
11575ffb0c9Toomas Soome    mDNSIPPort intport;
11585ffb0c9Toomas Soome    mDNSIPPort extport;
11595ffb0c9Toomas Soome    mDNSu32 NATRep_lease;
11605ffb0c9Toomas Soome} NATPortMapReply;
11614b22b93rs
11625ffb0c9Toomas Soome// PCP Support for IPv4 mappings
11634b22b93rs
11645ffb0c9Toomas Soome#define PCP_VERS 0x02
11655ffb0c9Toomas Soome#define PCP_WAITSECS_AFTER_EPOCH_INVALID 5
11664b22b93rs
11675ffb0c9Toomas Soometypedef enum
11685ffb0c9Toomas Soome{
11695ffb0c9Toomas Soome    PCPOp_Announce = 0,
11705ffb0c9Toomas Soome    PCPOp_Map      = 1
11715ffb0c9Toomas Soome} PCPOp_t;
11724b22b93rs
11735ffb0c9Toomas Soometypedef enum
11745ffb0c9Toomas Soome{
11755ffb0c9Toomas Soome    PCPProto_All = 0,
11765ffb0c9Toomas Soome    PCPProto_TCP = 6,
11775ffb0c9Toomas Soome    PCPProto_UDP = 17
11785ffb0c9Toomas Soome} PCPProto_t;
11794b22b93rs
11805ffb0c9Toomas Soometypedef enum
11815ffb0c9Toomas Soome{
11825ffb0c9Toomas Soome    PCPResult_Success         = 0,
11835ffb0c9Toomas Soome    PCPResult_UnsuppVersion   = 1,
11845ffb0c9Toomas Soome    PCPResult_NotAuthorized   = 2,
11855ffb0c9Toomas Soome    PCPResult_MalformedReq    = 3,
11865ffb0c9Toomas Soome    PCPResult_UnsuppOpcode    = 4,
11875ffb0c9Toomas Soome    PCPResult_UnsuppOption    = 5,
11885ffb0c9Toomas Soome    PCPResult_MalformedOption = 6,
11895ffb0c9Toomas Soome    PCPResult_NetworkFailure  = 7,
11905ffb0c9Toomas Soome    PCPResult_NoResources     = 8,
11915ffb0c9Toomas Soome    PCPResult_UnsuppProtocol  = 9,
11925ffb0c9Toomas Soome    PCPResult_UserExQuota     = 10,
11935ffb0c9Toomas Soome    PCPResult_CantProvideExt  = 11,
11945ffb0c9Toomas Soome    PCPResult_AddrMismatch    = 12,
11955ffb0c9Toomas Soome    PCPResult_ExcesRemotePeer = 13
11965ffb0c9Toomas Soome} PCPResult_t;
11974b22b93rs
1198c65ebfcToomas Soometypedef struct
11995ffb0c9Toomas Soome{
12005ffb0c9Toomas Soome    mDNSu8       version;
12015ffb0c9Toomas Soome    mDNSu8       opCode;
12025ffb0c9Toomas Soome    mDNSOpaque16 reserved;
12035ffb0c9Toomas Soome    mDNSu32      lifetime;
12045ffb0c9Toomas Soome    mDNSv6Addr   clientAddr;
12055ffb0c9Toomas Soome    mDNSu32      nonce[3];
12065ffb0c9Toomas Soome    mDNSu8       protocol;
12075ffb0c9Toomas Soome    mDNSu8       reservedMapOp[3];
12085ffb0c9Toomas Soome    mDNSIPPort   intPort;
12095ffb0c9Toomas Soome    mDNSIPPort   extPort;
12105ffb0c9Toomas Soome    mDNSv6Addr   extAddress;
12115ffb0c9Toomas Soome} PCPMapRequest;
12124b22b93rs
1213c65ebfcToomas Soometypedef struct
12145ffb0c9Toomas Soome{
12155ffb0c9Toomas Soome    mDNSu8     version;
12165ffb0c9Toomas Soome    mDNSu8     opCode;
12175ffb0c9Toomas Soome    mDNSu8     reserved;
12185ffb0c9Toomas Soome    mDNSu8     result;
12195ffb0c9Toomas Soome    mDNSu32    lifetime;
12205ffb0c9Toomas Soome    mDNSu32    epoch;
12215ffb0c9Toomas Soome    mDNSu32    clientAddrParts[3];
12225ffb0c9Toomas Soome    mDNSu32    nonce[3];
12235ffb0c9Toomas Soome    mDNSu8     protocol;
12245ffb0c9Toomas Soome    mDNSu8     reservedMapOp[3];
12255ffb0c9Toomas Soome    mDNSIPPort intPort;
12265ffb0c9Toomas Soome    mDNSIPPort extPort;
12275ffb0c9Toomas Soome    mDNSv6Addr extAddress;
12285ffb0c9Toomas Soome} PCPMapReply;
12295ffb0c9Toomas Soome
12305ffb0c9Toomas Soome// LNT Support
12314b22b93rs
12325ffb0c9Toomas Soometypedef enum
12335ffb0c9Toomas Soome{
12345ffb0c9Toomas Soome    LNTDiscoveryOp      = 1,
12355ffb0c9Toomas Soome    LNTExternalAddrOp   = 2,
12365ffb0c9Toomas Soome    LNTPortMapOp        = 3,
12375ffb0c9Toomas Soome    LNTPortMapDeleteOp  = 4
12385ffb0c9Toomas Soome} LNTOp_t;
12395ffb0c9Toomas Soome
12405ffb0c9Toomas Soome#define LNT_MAXBUFSIZE 8192
12415ffb0c9Toomas Soometypedef struct tcpLNTInfo_struct tcpLNTInfo;
12425ffb0c9Toomas Soomestruct tcpLNTInfo_struct
12435ffb0c9Toomas Soome{
12445ffb0c9Toomas Soome    tcpLNTInfo       *next;
12455ffb0c9Toomas Soome    mDNS             *m;
12465ffb0c9Toomas Soome    NATTraversalInfo *parentNATInfo;    // pointer back to the parent NATTraversalInfo
12475ffb0c9Toomas Soome    TCPSocket        *sock;
12485ffb0c9Toomas Soome    LNTOp_t op;                         // operation performed using this connection
12495ffb0c9Toomas Soome    mDNSAddr Address;                   // router address
12505ffb0c9Toomas Soome    mDNSIPPort Port;                    // router port
12515ffb0c9Toomas Soome    mDNSu8           *Request;          // xml request to router
12525ffb0c9Toomas Soome    int requestLen;
12535ffb0c9Toomas Soome    mDNSu8           *Reply;            // xml reply from router
12545ffb0c9Toomas Soome    int replyLen;
12555ffb0c9Toomas Soome    unsigned long nread;                // number of bytes read so far
12565ffb0c9Toomas Soome    int retries;                        // number of times we've tried to do this port mapping
12575ffb0c9Toomas Soome};
12585ffb0c9Toomas Soome
12595ffb0c9Toomas Soometypedef void (*NATTraversalClientCallback)(mDNS *m, NATTraversalInfo *n);
12605ffb0c9Toomas Soome
12615ffb0c9Toomas Soome// if m->timenow <  ExpiryTime then we have an active mapping, and we'll renew halfway to expiry
12625ffb0c9Toomas Soome// if m->timenow >= ExpiryTime then our mapping has expired, and we're trying to create one
12634b22b93rs
12645ffb0c9Toomas Soometypedef enum
12655ffb0c9Toomas Soome{
12665ffb0c9Toomas Soome    NATTProtocolNone    = 0,
12675ffb0c9Toomas Soome    NATTProtocolNATPMP  = 1,
12685ffb0c9Toomas Soome    NATTProtocolUPNPIGD = 2,
12695ffb0c9Toomas Soome    NATTProtocolPCP     = 3,
12705ffb0c9Toomas Soome} NATTProtocol;
12715ffb0c9Toomas Soome
12725ffb0c9Toomas Soomestruct NATTraversalInfo_struct
12735ffb0c9Toomas Soome{
12745ffb0c9Toomas Soome    // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
12755ffb0c9Toomas Soome    NATTraversalInfo           *next;
12765ffb0c9Toomas Soome
12775ffb0c9Toomas Soome    mDNSs32 ExpiryTime;                             // Time this mapping expires, or zero if no mapping
12785ffb0c9Toomas Soome    mDNSs32 retryInterval;                          // Current interval, between last packet we sent and the next one
12795ffb0c9Toomas Soome    mDNSs32 retryPortMap;                           // If Protocol is nonzero, time to send our next mapping packet
12805ffb0c9Toomas Soome    mStatus NewResult;                              // New error code; will be copied to Result just prior to invoking callback
12815ffb0c9Toomas Soome    NATTProtocol lastSuccessfulProtocol;            // To send correct deletion request & update non-PCP external address operations
12825ffb0c9Toomas Soome    mDNSBool sentNATPMP;                            // Whether we just sent a NAT-PMP packet, so we won't send another if
12835ffb0c9Toomas Soome                                                    //    we receive another NAT-PMP "Unsupported Version" packet
12844b22b93rs
12855ffb0c9Toomas Soome#ifdef _LEGACY_NAT_TRAVERSAL_
12865ffb0c9Toomas Soome    tcpLNTInfo tcpInfo;                             // Legacy NAT traversal (UPnP) TCP connection
12875ffb0c9Toomas Soome#endif
12884b22b93rs
12895ffb0c9Toomas Soome    // Result fields: When the callback is invoked these fields contain the answers the client is looking for
12905ffb0c9Toomas Soome    // When the callback is invoked ExternalPort is *usually* set to be the same the same as RequestedPort, except:
12915ffb0c9Toomas Soome    // (a) When we're behind a NAT gateway with port mapping disabled, ExternalPort is reported as zero to
12925ffb0c9Toomas Soome    //     indicate that we don't currently have a working mapping (but RequestedPort retains the external port
12935ffb0c9Toomas Soome    //     we'd like to get, the next time we meet an accomodating NAT gateway willing to give us one).
12945ffb0c9Toomas Soome    // (b) When we have a routable non-RFC1918 address, we don't *need* a port mapping, so ExternalPort
12955ffb0c9Toomas Soome    //     is reported as the same as our InternalPort, since that is effectively our externally-visible port too.
12965ffb0c9Toomas Soome    //     Again, RequestedPort retains the external port we'd like to get the next time we find ourself behind a NAT gateway.
12975ffb0c9Toomas Soome    // To improve stability of port mappings, RequestedPort is updated any time we get a successful
12985ffb0c9Toomas Soome    // mapping response from the PCP, NAT-PMP or UPnP gateway. For example, if we ask for port 80, and
12995ffb0c9Toomas Soome    // get assigned port 81, then thereafter we'll contine asking for port 81.
13005ffb0c9Toomas Soome    mDNSInterfaceID InterfaceID;
13015ffb0c9Toomas Soome    mDNSv4Addr ExternalAddress;                     // Initially set to onesIPv4Addr, until first callback
13025ffb0c9Toomas Soome    mDNSv4Addr NewAddress;                          // May be updated with actual value assigned by gateway
13035ffb0c9Toomas Soome    mDNSIPPort ExternalPort;
13045ffb0c9Toomas Soome    mDNSu32 Lifetime;
13055ffb0c9Toomas Soome    mStatus Result;
13065ffb0c9Toomas Soome
13075ffb0c9Toomas Soome    // Client API fields: The client must set up these fields *before* making any NAT traversal API calls
13085ffb0c9Toomas Soome    mDNSu8 Protocol;                                // NATOp_MapUDP or NATOp_MapTCP, or zero if just requesting the external IP address
13095ffb0c9Toomas Soome    mDNSIPPort IntPort;                             // Client's internal port number (doesn't change)
13105ffb0c9Toomas Soome    mDNSIPPort RequestedPort;                       // Requested external port; may be updated with actual value assigned by gateway
13115ffb0c9Toomas Soome    mDNSu32 NATLease;                               // Requested lifetime in seconds (doesn't change)
13125ffb0c9Toomas Soome    NATTraversalClientCallback clientCallback;
13135ffb0c9Toomas Soome    void                       *clientContext;
13145ffb0c9Toomas Soome};
13154b22b93rs
13165ffb0c9Toomas Soome// ***************************************************************************
13175ffb0c9Toomas Soome#if 0
13185ffb0c9Toomas Soome#pragma mark -
13195ffb0c9Toomas Soome#pragma mark - DNSServer & McastResolver structures and constants
13205ffb0c9Toomas Soome#endif
13214b22b93rs
13225ffb0c9Toomas Soomeenum
13235ffb0c9Toomas Soome{
1324cda73f6Toomas Soome    DNSServer_FlagDelete      = 0x1,
1325cda73f6Toomas Soome    DNSServer_FlagNew         = 0x2,
1326cda73f6Toomas Soome#if APPLE_OSX_mDNSResponder
1327cda73f6Toomas Soome    DNSServer_FlagUnreachable = 0x4,
1328cda73f6Toomas Soome#endif
13295ffb0c9Toomas Soome};
13304b22b93rs
13315ffb0c9Toomas Soomeenum
13325ffb0c9Toomas Soome{
13335ffb0c9Toomas Soome    McastResolver_FlagDelete = 1,
13345ffb0c9Toomas Soome    McastResolver_FlagNew    = 2
13355ffb0c9Toomas Soome};
13365ffb0c9Toomas Soome
13375ffb0c9Toomas Soometypedef struct McastResolver
13385ffb0c9Toomas Soome{
13395ffb0c9Toomas Soome    struct McastResolver *next;
13405ffb0c9Toomas Soome    mDNSInterfaceID interface;
13415ffb0c9Toomas Soome    mDNSu32 flags;              // Set when we're planning to delete this from the list
13425ffb0c9Toomas Soome    domainname domain;
13435ffb0c9Toomas Soome    mDNSu32 timeout;            // timeout value for questions
13445ffb0c9Toomas Soome} McastResolver;
13455ffb0c9Toomas Soome
13463b436d0Toomas Soomeenum {
13473b436d0Toomas Soome    Mortality_Mortal      = 0,          // This cache record can expire and get purged
13483b436d0Toomas Soome    Mortality_Immortal    = 1,          // Allow this record to remain in the cache indefinitely
13493b436d0Toomas Soome    Mortality_Ghost       = 2           // An immortal record that has expired and can linger in the cache
13503b436d0Toomas Soome};
13513b436d0Toomas Soometypedef mDNSu8 MortalityState;
13523b436d0Toomas Soome
13535ffb0c9Toomas Soome// scoped values for DNSServer matching
13545ffb0c9Toomas Soomeenum
13555ffb0c9Toomas Soome{
13565ffb0c9Toomas Soome    kScopeNone         = 0,        // DNS server used by unscoped questions
13575ffb0c9Toomas Soome    kScopeInterfaceID  = 1,        // Scoped DNS server used only by scoped questions
1358c65ebfcToomas Soome    kScopeServiceID    = 2,         // Service specific DNS server used only by questions
13595ffb0c9Toomas Soome                                   // have a matching serviceID
1360c65ebfcToomas Soome    kScopesMaxCount    = 3         // Max count for scopes enum
13615ffb0c9Toomas Soome};
13625ffb0c9Toomas Soome
13635ffb0c9Toomas Soome// Note: DNSSECAware is set if we are able to get a valid response to
13645ffb0c9Toomas Soome// a DNSSEC question. In some cases it is possible that the proxy
13655ffb0c9Toomas Soome// strips the EDNS0 option and we just get a plain response with no
13665ffb0c9Toomas Soome// signatures. But we still mark DNSSECAware in that case. As DNSSECAware
13675ffb0c9Toomas Soome// is only used to determine whether DNSSEC_VALIDATION_SECURE_OPTIONAL
13685ffb0c9Toomas Soome// should be turned off or not, it is sufficient that we are getting
13695ffb0c9Toomas Soome// responses back.
13705ffb0c9Toomas Soometypedef struct DNSServer
13715ffb0c9Toomas Soome{
13725ffb0c9Toomas Soome    struct DNSServer *next;
13735ffb0c9Toomas Soome    mDNSInterfaceID interface;  // DNS requests should be sent on this interface
13745ffb0c9Toomas Soome    mDNSs32 serviceID;
13755ffb0c9Toomas Soome    mDNSAddr addr;
13765ffb0c9Toomas Soome    mDNSIPPort port;
13775ffb0c9Toomas Soome    mDNSu32 flags;              // Set when we're planning to delete this from the list
13785ffb0c9Toomas Soome    domainname domain;          // name->server matching for "split dns"
13795ffb0c9Toomas Soome    mDNSs32 penaltyTime;        // amount of time this server is penalized
13805ffb0c9Toomas Soome    mDNSu32 scoped;             // See the scoped enum above
13815ffb0c9Toomas Soome    mDNSu32 timeout;            // timeout value for questions
13825ffb0c9Toomas Soome    mDNSu16 resGroupID;         // ID of the resolver group that contains this DNSServer
1383c65ebfcToomas Soome    mDNSu8 retransDO;           // Total Retransmissions for queries sent with DO option
1384c65ebfcToomas Soome    mDNSBool cellIntf;          // Resolver from Cellular Interface?
13855ffb0c9Toomas Soome    mDNSBool req_A;             // If set, send v4 query (DNSConfig allows A queries)
13865ffb0c9Toomas Soome    mDNSBool req_AAAA;          // If set, send v6 query (DNSConfig allows AAAA queries)
13875ffb0c9Toomas Soome    mDNSBool req_DO;            // If set, okay to send DNSSEC queries (EDNS DO bit is supported)
1388c65ebfcToomas Soome    mDNSBool DNSSECAware;       // Set if we are able to receive a response to a request sent with DO option.
1389c65ebfcToomas Soome    mDNSBool isExpensive;       // True if the interface to this server is expensive.
13903b436d0Toomas Soome    mDNSBool isCLAT46;          // True if the interface to this server is CLAT46.
13915ffb0c9Toomas Soome} DNSServer;
13924b22b93rs
13934b22b93rstypedef struct
13945ffb0c9Toomas Soome{
13955ffb0c9Toomas Soome    mDNSu8 *AnonData;
13965ffb0c9Toomas Soome    int AnonDataLen;
13975ffb0c9Toomas Soome    mDNSu32 salt;
13985ffb0c9Toomas Soome    ResourceRecord *nsec3RR;
13995ffb0c9Toomas Soome    mDNSInterfaceID SendNow;     // The interface ID that this record should be sent on
14005ffb0c9Toomas Soome} AnonymousInfo;
14015ffb0c9Toomas Soome
14025ffb0c9Toomas Soomestruct ResourceRecord_struct
14035ffb0c9Toomas Soome{
1404c65ebfcToomas Soome    mDNSu8 RecordType;                  // See kDNSRecordTypes enum.
14053b436d0Toomas Soome    MortalityState mortality;           // Mortality of this resource record (See MortalityState enum)
1406c65ebfcToomas Soome    mDNSu16 rrtype;                     // See DNS_TypeValues enum.
1407c65ebfcToomas Soome    mDNSu16 rrclass;                    // See DNS_ClassValues enum.
14085ffb0c9Toomas Soome    mDNSu32 rroriginalttl;              // In seconds
14095ffb0c9Toomas Soome    mDNSu16 rdlength;                   // Size of the raw rdata, in bytes, in the on-the-wire format
14105ffb0c9Toomas Soome                                        // (In-memory storage may be larger, for structures containing 'holes', like SOA)
14115ffb0c9Toomas Soome    mDNSu16 rdestimate;                 // Upper bound on on-the-wire size of rdata after name compression
14125ffb0c9Toomas Soome    mDNSu32 namehash;                   // Name-based (i.e. case-insensitive) hash of name
14135ffb0c9Toomas Soome    mDNSu32 rdatahash;                  // For rdata containing domain name (e.g. PTR, SRV, CNAME etc.), case-insensitive name hash
14145ffb0c9Toomas Soome                                        // else, for all other rdata, 32-bit hash of the raw rdata
14155ffb0c9Toomas Soome                                        // Note: This requirement is important. Various routines like AddAdditionalsToResponseList(),
14165ffb0c9Toomas Soome                                        // ReconfirmAntecedents(), etc., use rdatahash as a pre-flight check to see
14175ffb0c9Toomas Soome                                        // whether it's worth doing a full SameDomainName() call. If the rdatahash
14185ffb0c9Toomas Soome                                        // is not a correct case-insensitive name hash, they'll get false negatives.
14195ffb0c9Toomas Soome    // Grouping pointers together at the end of the structure improves the memory layout efficiency
14205ffb0c9Toomas Soome    mDNSInterfaceID InterfaceID;        // Set if this RR is specific to one interface
14215ffb0c9Toomas Soome                                        // For records received off the wire, InterfaceID is *always* set to the receiving interface
14225ffb0c9Toomas Soome                                        // For our authoritative records, InterfaceID is usually zero, except for those few records
14235ffb0c9Toomas Soome                                        // that are interface-specific (e.g. address records, especially linklocal addresses)
14245ffb0c9Toomas Soome    const domainname *name;
14255ffb0c9Toomas Soome    RData           *rdata;             // Pointer to storage for this rdata
1426cda73f6Toomas Soome    DNSServer       *rDNSServer;        // Unicast DNS server authoritative for this entry; null for multicast
14275ffb0c9Toomas Soome    AnonymousInfo   *AnonInfo;          // Anonymous Information
14285ffb0c9Toomas Soome};
14295ffb0c9Toomas Soome
14305ffb0c9Toomas Soome
14315ffb0c9Toomas Soome// Unless otherwise noted, states may apply to either independent record registrations or service registrations
14324b22b93rstypedef enum
14335ffb0c9Toomas Soome{
14345ffb0c9Toomas Soome    regState_Zero              = 0,
14355ffb0c9Toomas Soome    regState_Pending           = 1,     // update sent, reply not received
14365ffb0c9Toomas Soome    regState_Registered        = 2,     // update sent, reply received
14375ffb0c9Toomas Soome    regState_DeregPending      = 3,     // dereg sent, reply not received
14385ffb0c9Toomas Soome    regState_Unregistered      = 4,     // not in any list
14395ffb0c9Toomas Soome    regState_Refresh           = 5,     // outstanding refresh (or target change) message
14405ffb0c9Toomas Soome    regState_NATMap            = 6,     // establishing NAT port mapping
14415ffb0c9Toomas Soome    regState_UpdatePending     = 7,     // update in flight as result of mDNS_Update call
14425ffb0c9Toomas Soome    regState_NoTarget          = 8,     // SRV Record registration pending registration of hostname
14435ffb0c9Toomas Soome    regState_NATError          = 9     // unable to complete NAT traversal
14445ffb0c9Toomas Soome} regState_t;
14454b22b93rs
14465ffb0c9Toomas Soomeenum
14475ffb0c9Toomas Soome{
14485ffb0c9Toomas Soome    Target_Manual = 0,
14495ffb0c9Toomas Soome    Target_AutoHost = 1,
14505ffb0c9Toomas Soome    Target_AutoHostAndNATMAP = 2
14515ffb0c9Toomas Soome};
14525ffb0c9Toomas Soome
14535ffb0c9Toomas Soometypedef enum
14545ffb0c9Toomas Soome{
14555ffb0c9Toomas Soome    mergeState_Zero = 0,
14565ffb0c9Toomas Soome    mergeState_DontMerge = 1  // Set on fatal error conditions to disable merging
14575ffb0c9Toomas Soome} mergeState_t;
14585ffb0c9Toomas Soome
14595ffb0c9Toomas Soome#define AUTH_GROUP_NAME_SIZE    128
14605ffb0c9Toomas Soomestruct AuthGroup_struct             // Header object for a list of AuthRecords with the same name
14615ffb0c9Toomas Soome{
14625ffb0c9Toomas Soome    AuthGroup      *next;               // Next AuthGroup object in this hash table bucket
14635ffb0c9Toomas Soome    mDNSu32 namehash;                   // Name-based (i.e. case insensitive) hash of name
14645ffb0c9Toomas Soome    AuthRecord     *members;            // List of CacheRecords with this same name
14655ffb0c9Toomas Soome    AuthRecord    **rrauth_tail;        // Tail end of that list
14665ffb0c9Toomas Soome    domainname     *name;               // Common name for all AuthRecords in this list
14675ffb0c9Toomas Soome    AuthRecord     *NewLocalOnlyRecords;
14685ffb0c9Toomas Soome    mDNSu8 namestorage[AUTH_GROUP_NAME_SIZE];
14695ffb0c9Toomas Soome};
14705ffb0c9Toomas Soome
14715ffb0c9Toomas Soome#ifndef AUTH_HASH_SLOTS
14725ffb0c9Toomas Soome#define AUTH_HASH_SLOTS 499
14735ffb0c9Toomas Soome#endif
14745ffb0c9Toomas Soome#define FORALL_AUTHRECORDS(SLOT,AG,AR)                              \
14755ffb0c9Toomas Soome    for ((SLOT) = 0; (SLOT) < AUTH_HASH_SLOTS; (SLOT)++)                                                                     \
14765ffb0c9Toomas Soome        for ((AG)=m->rrauth.rrauth_hash[(SLOT)]; (AG); (AG)=(AG)->next)                                                                         \
14775ffb0c9Toomas Soome            for ((AR) = (AG)->members; (AR); (AR)=(AR)->next)
14785ffb0c9Toomas Soome
14795ffb0c9Toomas Soometypedef union AuthEntity_union AuthEntity;
14805ffb0c9Toomas Soomeunion AuthEntity_union { AuthEntity *next; AuthGroup ag; };
14815ffb0c9Toomas Soometypedef struct {
14825ffb0c9Toomas Soome    mDNSu32 rrauth_size;                // Total number of available auth entries
14835ffb0c9Toomas Soome    mDNSu32 rrauth_totalused;           // Number of auth entries currently occupied
14845ffb0c9Toomas Soome    mDNSu32 rrauth_report;
14855ffb0c9Toomas Soome    mDNSu8 rrauth_lock;                 // For debugging: Set at times when these lists may not be modified
14865ffb0c9Toomas Soome    AuthEntity *rrauth_free;
14875ffb0c9Toomas Soome    AuthGroup *rrauth_hash[AUTH_HASH_SLOTS];
14885ffb0c9Toomas Soome}AuthHash;
14895ffb0c9Toomas Soome
14905ffb0c9Toomas Soome// AuthRecordAny includes mDNSInterface_Any and interface specific auth records.
14915ffb0c9Toomas Soometypedef enum
14925ffb0c9Toomas Soome{
14935ffb0c9Toomas Soome    AuthRecordAny,              // registered for *Any, NOT including P2P interfaces
14945ffb0c9Toomas Soome    AuthRecordAnyIncludeP2P,    // registered for *Any, including P2P interfaces
14955ffb0c9Toomas Soome    AuthRecordAnyIncludeAWDL,   // registered for *Any, including AWDL interface
14965ffb0c9Toomas Soome    AuthRecordAnyIncludeAWDLandP2P, // registered for *Any, including AWDL and P2P interfaces
14975ffb0c9Toomas Soome    AuthRecordLocalOnly,
14985ffb0c9Toomas Soome    AuthRecordP2P               // discovered over D2D/P2P framework
14995ffb0c9Toomas Soome} AuthRecType;
15005ffb0c9Toomas Soome
15015ffb0c9Toomas Soometypedef enum
15025ffb0c9Toomas Soome{
15035ffb0c9Toomas Soome    AuthFlagsWakeOnly = 0x1     // WakeOnly service
15045ffb0c9Toomas Soome} AuthRecordFlags;
15054b22b93rs
15064b22b93rsstruct AuthRecord_struct
15075ffb0c9Toomas Soome{
15085ffb0c9Toomas Soome    // For examples of how to set up this structure for use in mDNS_Register(),
15095ffb0c9Toomas Soome    // see mDNS_AdvertiseInterface() or mDNS_RegisterService().
15105ffb0c9Toomas Soome    // Basically, resrec and persistent metadata need to be set up before calling mDNS_Register().
15115ffb0c9Toomas Soome    // mDNS_SetupResourceRecord() is avaliable as a helper routine to set up most fields to sensible default values for you
15125ffb0c9Toomas Soome
15135ffb0c9Toomas Soome    AuthRecord     *next;               // Next in list; first element of structure for efficiency reasons
15145ffb0c9Toomas Soome    // Field Group 1: Common ResourceRecord fields
1515cda73f6Toomas Soome    ResourceRecord resrec;              // 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit (now 44/64)
15165ffb0c9Toomas Soome
15175ffb0c9Toomas Soome    // Field Group 2: Persistent metadata for Authoritative Records
15185ffb0c9Toomas Soome    AuthRecord     *Additional1;        // Recommended additional record to include in response (e.g. SRV for PTR record)
15195ffb0c9Toomas Soome    AuthRecord     *Additional2;        // Another additional (e.g. TXT for PTR record)
15205ffb0c9Toomas Soome    AuthRecord     *DependentOn;        // This record depends on another for its uniqueness checking
15215ffb0c9Toomas Soome    AuthRecord     *RRSet;              // This unique record is part of an RRSet
15225ffb0c9Toomas Soome    mDNSRecordCallback *RecordCallback; // Callback function to call for state changes, and to free memory asynchronously on deregistration
15235ffb0c9Toomas Soome    void           *RecordContext;      // Context parameter for the callback function
15245ffb0c9Toomas Soome    mDNSu8 AutoTarget;                  // Set if the target of this record (PTR, CNAME, SRV, etc.) is our host name
15255ffb0c9Toomas Soome    mDNSu8 AllowRemoteQuery;            // Set if we allow hosts not on the local link to query this record
15265ffb0c9Toomas Soome    mDNSu8 ForceMCast;                  // Set by client to advertise solely via multicast, even for apparently unicast names
15275ffb0c9Toomas Soome    mDNSu8 AuthFlags;
15285ffb0c9Toomas Soome
15295ffb0c9Toomas Soome    OwnerOptData WakeUp;                // WakeUp.HMAC.l[0] nonzero indicates that this is a Sleep Proxy record
15305ffb0c9Toomas Soome    mDNSAddr AddressProxy;              // For reverse-mapping Sleep Proxy PTR records, address in question
15315ffb0c9Toomas Soome    mDNSs32 TimeRcvd;                   // In platform time units
15325ffb0c9Toomas Soome    mDNSs32 TimeExpire;                 // In platform time units
15335ffb0c9Toomas Soome    AuthRecType ARType;                 // LocalOnly, P2P or Normal ?
15345ffb0c9Toomas Soome    mDNSs32 KATimeExpire;               // In platform time units: time to send keepalive packet for the proxy record
15355ffb0c9Toomas Soome
15365ffb0c9Toomas Soome    // Field Group 3: Transient state for Authoritative Records
15375ffb0c9Toomas Soome    mDNSu8 Acknowledged;                // Set if we've given the success callback to the client
15385ffb0c9Toomas Soome    mDNSu8 ProbeRestartCount;           // Number of times we have restarted probing
15395ffb0c9Toomas Soome    mDNSu8 ProbeCount;                  // Number of probes remaining before this record is valid (kDNSRecordTypeUnique)
15405ffb0c9Toomas Soome    mDNSu8 AnnounceCount;               // Number of announcements remaining (kDNSRecordTypeShared)
15415ffb0c9Toomas Soome    mDNSu8 RequireGoodbye;              // Set if this RR has been announced on the wire and will require a goodbye packet
15425ffb0c9Toomas Soome    mDNSu8 AnsweredLocalQ;              // Set if this AuthRecord has been delivered to any local question (LocalOnly or mDNSInterface_Any)
15435ffb0c9Toomas Soome    mDNSu8 IncludeInProbe;              // Set if this RR is being put into a probe right now
15445ffb0c9Toomas Soome    mDNSu8 ImmedUnicast;                // Set if we may send our response directly via unicast to the requester
15455ffb0c9Toomas Soome    mDNSInterfaceID SendNSECNow;        // Set if we need to generate associated NSEC data for this rrname
15465ffb0c9Toomas Soome    mDNSInterfaceID ImmedAnswer;        // Someone on this interface issued a query we need to answer (all-ones for all interfaces)
15474b22b93rs#if MDNS_LOG_ANSWER_SUPPRESSION_TIMES
15485ffb0c9Toomas Soome    mDNSs32 ImmedAnswerMarkTime;
15494b22b93rs#endif
15505ffb0c9Toomas Soome    mDNSInterfaceID ImmedAdditional;    // Hint that we might want to also send this record, just to be helpful
15515ffb0c9Toomas Soome    mDNSInterfaceID SendRNow;           // The interface this query is being sent on right now
15525ffb0c9Toomas Soome    mDNSv4Addr v4Requester;             // Recent v4 query for this record, or all-ones if more than one recent query
15535ffb0c9Toomas Soome    mDNSv6Addr v6Requester;             // Recent v6 query for this record, or all-ones if more than one recent query
15545ffb0c9Toomas Soome    AuthRecord     *NextResponse;       // Link to the next element in the chain of responses to generate
15555ffb0c9Toomas Soome    const mDNSu8   *NR_AnswerTo;        // Set if this record was selected by virtue of being a direct answer to a question
15565ffb0c9Toomas Soome    AuthRecord     *NR_AdditionalTo;    // Set if this record was selected by virtue of being additional to another
15575ffb0c9Toomas Soome    mDNSs32 ThisAPInterval;             // In platform time units: Current interval for announce/probe
15585ffb0c9Toomas Soome    mDNSs32 LastAPTime;                 // In platform time units: Last time we sent announcement/probe
15595ffb0c9Toomas Soome    mDNSs32 LastMCTime;                 // Last time we multicast this record (used to guard against packet-storm attacks)
15605ffb0c9Toomas Soome    mDNSInterfaceID LastMCInterface;    // Interface this record was multicast on at the time LastMCTime was recorded
15615ffb0c9Toomas Soome    RData          *NewRData;           // Set if we are updating this record with new rdata
15625ffb0c9Toomas Soome    mDNSu16 newrdlength;                // ... and the length of the new RData
15635ffb0c9Toomas Soome    mDNSRecordUpdateCallback *UpdateCallback;
15645ffb0c9Toomas Soome    mDNSu32 UpdateCredits;              // Token-bucket rate limiting of excessive updates
15655ffb0c9Toomas Soome    mDNSs32 NextUpdateCredit;           // Time next token is added to bucket
15665ffb0c9Toomas Soome    mDNSs32 UpdateBlocked;              // Set if update delaying is in effect
15675ffb0c9Toomas Soome
15685ffb0c9Toomas Soome    // Field Group 4: Transient uDNS state for Authoritative Records
15695ffb0c9Toomas Soome    regState_t state;           // Maybe combine this with resrec.RecordType state? Right now it's ambiguous and confusing.
15705ffb0c9Toomas Soome                                // e.g. rr->resrec.RecordType can be kDNSRecordTypeUnregistered,
15715ffb0c9Toomas Soome                                // and rr->state can be regState_Unregistered
15725ffb0c9Toomas Soome                                // What if we find one of those statements is true and the other false? What does that mean?
15735ffb0c9Toomas Soome    mDNSBool uselease;          // dynamic update contains (should contain) lease option
15745ffb0c9Toomas Soome    mDNSs32 expire;             // In platform time units: expiration of lease (-1 for static)
15755ffb0c9Toomas Soome    mDNSBool Private;           // If zone is private, DNS updates may have to be encrypted to prevent eavesdropping
15765ffb0c9Toomas Soome    mDNSOpaque16 updateid;      // Identifier to match update request and response -- also used when transferring records to Sleep Proxy
15775ffb0c9Toomas Soome    mDNSOpaque64 updateIntID;   // Interface IDs (one bit per interface index)to which updates have been sent
15785ffb0c9Toomas Soome    const domainname *zone;     // the zone that is updated
15795ffb0c9Toomas Soome    ZoneData  *nta;
15805ffb0c9Toomas Soome    struct tcpInfo_t *tcp;
15815ffb0c9Toomas Soome    NATTraversalInfo NATinfo;
15825ffb0c9Toomas Soome    mDNSBool SRVChanged;       // temporarily deregistered service because its SRV target or port changed
15835ffb0c9Toomas Soome    mergeState_t mState;       // Unicast Record Registrations merge state
15845ffb0c9Toomas Soome    mDNSu8 refreshCount;        // Number of refreshes to the server
15855ffb0c9Toomas Soome    mStatus updateError;        // Record update resulted in Error ?
15865ffb0c9Toomas Soome
15875ffb0c9Toomas Soome    // uDNS_UpdateRecord support fields
15885ffb0c9Toomas Soome    // Do we really need all these in *addition* to NewRData and newrdlength above?
15895ffb0c9Toomas Soome    void *UpdateContext;    // Context parameter for the update callback function
15905ffb0c9Toomas Soome    mDNSu16 OrigRDLen;      // previously registered, being deleted
15915ffb0c9Toomas Soome    mDNSu16 InFlightRDLen;  // currently being registered
15925ffb0c9Toomas Soome    mDNSu16 QueuedRDLen;    // pending operation (re-transmitting if necessary) THEN register the queued update
15935ffb0c9Toomas Soome    RData *OrigRData;
15945ffb0c9Toomas Soome    RData *InFlightRData;
15955ffb0c9Toomas Soome    RData *QueuedRData;
15965ffb0c9Toomas Soome
15975ffb0c9Toomas Soome    // Field Group 5: Large data objects go at the end
15985ffb0c9Toomas Soome    domainname namestorage;
15995ffb0c9Toomas Soome    RData rdatastorage;                 // Normally the storage is right here, except for oversized records
16005ffb0c9Toomas Soome    // rdatastorage MUST be the last thing in the structure -- when using oversized AuthRecords, extra bytes
16015ffb0c9Toomas Soome    // are appended after the end of the AuthRecord, logically augmenting the size of the rdatastorage
16025ffb0c9Toomas Soome    // DO NOT ADD ANY MORE FIELDS HERE
16035ffb0c9Toomas Soome};
16045ffb0c9Toomas Soome
16055ffb0c9Toomas Soome// IsLocalDomain alone is not sufficient to determine that a record is mDNS or uDNS. By default domain names within
16065ffb0c9Toomas Soome// the "local" pseudo-TLD (and within the IPv4 and IPv6 link-local reverse mapping domains) are automatically treated
16075ffb0c9Toomas Soome// as mDNS records, but it is also possible to force any record (even those not within one of the inherently local
16085ffb0c9Toomas Soome// domains) to be handled as an mDNS record by setting the ForceMCast flag, or by setting a non-zero InterfaceID.
16095ffb0c9Toomas Soome// For example, the reverse-mapping PTR record created in AdvertiseInterface sets the ForceMCast flag, since it points to
16105ffb0c9Toomas Soome// a dot-local hostname, and therefore it would make no sense to register this record with a wide-area Unicast DNS server.
16115ffb0c9Toomas Soome// The same applies to Sleep Proxy records, which we will answer for when queried via mDNS, but we never want to try
16125ffb0c9Toomas Soome// to register them with a wide-area Unicast DNS server -- and we probably don't have the required credentials anyway.
16135ffb0c9Toomas Soome// Currently we have no concept of a wide-area uDNS record scoped to a particular interface, so if the InterfaceID is
16145ffb0c9Toomas Soome// nonzero we treat this the same as ForceMCast.
16155ffb0c9Toomas Soome// Note: Question_uDNS(Q) is used in *only* one place -- on entry to mDNS_StartQuery_internal, to decide whether to set TargetQID.
16165ffb0c9Toomas Soome// Everywhere else in the code, the determination of whether a question is unicast is made by checking to see if TargetQID is nonzero.
16175ffb0c9Toomas Soome#define AuthRecord_uDNS(R) ((R)->resrec.InterfaceID == mDNSInterface_Any && !(R)->ForceMCast && !IsLocalDomain((R)->resrec.name))
16185ffb0c9Toomas Soome#define Question_uDNS(Q)   ((Q)->InterfaceID == mDNSInterface_Unicast || (Q)->ProxyQuestion || \
1619c65ebfcToomas Soome                            ((Q)->InterfaceID != mDNSInterface_LocalOnly && (Q)->InterfaceID != mDNSInterface_P2P && (Q)->InterfaceID != mDNSInterface_BLE && !(Q)->ForceMCast && !IsLocalDomain(&(Q)->qname)))
16205ffb0c9Toomas Soome
1621c65ebfcToomas Soome// AuthRecordLocalOnly records are registered using mDNSInterface_LocalOnly and
1622c65ebfcToomas Soome// AuthRecordP2P records are created by D2DServiceFound events.  Both record types are kept on the same list.
16235ffb0c9Toomas Soome#define RRLocalOnly(rr) ((rr)->ARType == AuthRecordLocalOnly || (rr)->ARType == AuthRecordP2P)
16245ffb0c9Toomas Soome
1625c65ebfcToomas Soome// All other auth records, not including those defined as RRLocalOnly().
16265ffb0c9Toomas Soome#define RRAny(rr) ((rr)->ARType == AuthRecordAny || (rr)->ARType == AuthRecordAnyIncludeP2P || (rr)->ARType == AuthRecordAnyIncludeAWDL || (rr)->ARType == AuthRecordAnyIncludeAWDLandP2P)
16275ffb0c9Toomas Soome
16285ffb0c9Toomas Soome// Question (A or AAAA) that is suppressed currently because IPv4 or IPv6 address
16295ffb0c9Toomas Soome// is not available locally for A or AAAA question respectively. Also, if the
16305ffb0c9Toomas Soome// query is disallowed for the "pid" that we are sending on behalf of, suppress it.
16315ffb0c9Toomas Soome#define QuerySuppressed(Q) (((Q)->SuppressUnusable && (Q)->SuppressQuery) || ((Q)->DisallowPID))
16325ffb0c9Toomas Soome
16335ffb0c9Toomas Soome#define PrivateQuery(Q) ((Q)->AuthInfo && (Q)->AuthInfo->AutoTunnel)
16345ffb0c9Toomas Soome
16355ffb0c9Toomas Soome// Normally we always lookup the cache and /etc/hosts before sending the query on the wire. For single label
16365ffb0c9Toomas Soome// queries (A and AAAA) that are unqualified (indicated by AppendSearchDomains), we want to append search
16375ffb0c9Toomas Soome// domains before we try them as such
16385ffb0c9Toomas Soome#define ApplySearchDomainsFirst(q) ((q)->AppendSearchDomains && (CountLabels(&((q)->qname))) == 1)
16394b22b93rs
16404b22b93rs// Wrapper struct for Auth Records for higher-level code that cannot use the AuthRecord's ->next pointer field
16414b22b93rstypedef struct ARListElem
16425ffb0c9Toomas Soome{
16435ffb0c9Toomas Soome    struct ARListElem *next;
16445ffb0c9Toomas Soome    AuthRecord ar;          // Note: Must be last element of structure, to accomodate oversized AuthRecords
16455ffb0c9Toomas Soome} ARListElem;
16464b22b93rs
16474b22b93rsstruct CacheRecord_struct
16485ffb0c9Toomas Soome{
16495ffb0c9Toomas Soome    CacheRecord    *next;               // Next in list; first element of structure for efficiency reasons
1650cda73f6Toomas Soome    ResourceRecord resrec;              // 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit (now 44/64)
16515ffb0c9Toomas Soome
16525ffb0c9Toomas Soome    // Transient state for Cache Records
16535ffb0c9Toomas Soome    CacheRecord    *NextInKAList;       // Link to the next element in the chain of known answers to send
16545ffb0c9Toomas Soome    mDNSs32 TimeRcvd;                   // In platform time units
16555ffb0c9Toomas Soome    mDNSs32 DelayDelivery;              // Set if we want to defer delivery of this answer to local clients
16565ffb0c9Toomas Soome    mDNSs32 NextRequiredQuery;          // In platform time units
16573b436d0Toomas Soome    // Extra four bytes here (on 64bit)
16585ffb0c9Toomas Soome    DNSQuestion    *CRActiveQuestion;   // Points to an active question referencing this answer. Can never point to a NewQuestion.
16595ffb0c9Toomas Soome    mDNSs32 LastUnansweredTime;         // In platform time units; last time we incremented UnansweredQueries
16605ffb0c9Toomas Soome    mDNSu8  UnansweredQueries;          // Number of times we've issued a query for this record without getting an answer
16615ffb0c9Toomas Soome    mDNSu8  CRDNSSECQuestion;           // Set to 1 if this was created in response to a DNSSEC question
16625ffb0c9Toomas Soome    mDNSOpaque16 responseFlags;         // Second 16 bit in the DNS response
16635ffb0c9Toomas Soome    CacheRecord    *NextInCFList;       // Set if this is in the list of records we just received with the cache flush bit set
16645ffb0c9Toomas Soome    CacheRecord    *nsec;               // NSEC records needed for non-existence proofs
16655ffb0c9Toomas Soome    CacheRecord    *soa;                // SOA record to return for proxy questions
16665ffb0c9Toomas Soome
16675ffb0c9Toomas Soome    mDNSAddr sourceAddress;             // node from which we received this record
1668cda73f6Toomas Soome    // Size to here is 76 bytes when compiling 32-bit; 104 bytes when compiling 64-bit (now 160 bytes for 64-bit)
16695ffb0c9Toomas Soome    RData_small smallrdatastorage;      // Storage for small records is right here (4 bytes header + 68 bytes data = 72 bytes)
16705ffb0c9Toomas Soome};
16715ffb0c9Toomas Soome
16725ffb0c9Toomas Soome// Should match the CacheGroup_struct members, except namestorage[].  Only used to calculate
1673cda73f6Toomas Soome// the size of the namestorage array in CacheGroup_struct so that sizeof(CacheGroup) == sizeof(CacheRecord)
16745ffb0c9Toomas Soomestruct CacheGroup_base
16755ffb0c9Toomas Soome{
16765ffb0c9Toomas Soome    CacheGroup     *next;
16775ffb0c9Toomas Soome    mDNSu32         namehash;
16785ffb0c9Toomas Soome    CacheRecord    *members;
16795ffb0c9Toomas Soome    CacheRecord   **rrcache_tail;
16805ffb0c9Toomas Soome    domainname     *name;
16815ffb0c9Toomas Soome};
16825ffb0c9Toomas Soome
16835ffb0c9Toomas Soomestruct CacheGroup_struct                // Header object for a list of CacheRecords with the same name
16845ffb0c9Toomas Soome{
16855ffb0c9Toomas Soome    CacheGroup     *next;               // Next CacheGroup object in this hash table bucket
16865ffb0c9Toomas Soome    mDNSu32         namehash;           // Name-based (i.e. case insensitive) hash of name
16875ffb0c9Toomas Soome    CacheRecord    *members;            // List of CacheRecords with this same name
16885ffb0c9Toomas Soome    CacheRecord   **rrcache_tail;       // Tail end of that list
16895ffb0c9Toomas Soome    domainname     *name;               // Common name for all CacheRecords in this list
16905ffb0c9Toomas Soome    mDNSu8 namestorage[sizeof(CacheRecord) - sizeof(struct CacheGroup_base)];  // match sizeof(CacheRecord)
16915ffb0c9Toomas Soome};
16924b22b93rs
16934b22b93rs// Storage sufficient to hold either a CacheGroup header or a CacheRecord
16945ffb0c9Toomas Soome// -- for best efficiency (to avoid wasted unused storage) they should be the same size
16954b22b93rstypedef union CacheEntity_union CacheEntity;
16964b22b93rsunion CacheEntity_union { CacheEntity *next; CacheGroup cg; CacheRecord cr; };
16974b22b93rs
16984b22b93rstypedef struct
16995ffb0c9Toomas Soome{
17005ffb0c9Toomas Soome    CacheRecord r;
17015ffb0c9Toomas Soome    mDNSu8 _extradata[MaximumRDSize-InlineCacheRDSize];     // Glue on the necessary number of extra bytes
17025ffb0c9Toomas Soome    domainname namestorage;                                 // Needs to go *after* the extra rdata bytes
17035ffb0c9Toomas Soome} LargeCacheRecord;
17045ffb0c9Toomas Soome
17055ffb0c9Toomas Soometypedef struct HostnameInfo
17065ffb0c9Toomas Soome{
17075ffb0c9Toomas Soome    struct HostnameInfo *next;
17085ffb0c9Toomas Soome    NATTraversalInfo natinfo;
17094b22b93rs    domainname fqdn;
17105ffb0c9Toomas Soome    AuthRecord arv4;                          // registered IPv4 address record
17115ffb0c9Toomas Soome    AuthRecord arv6;                          // registered IPv6 address record
17125ffb0c9Toomas Soome    mDNSRecordCallback *StatusCallback;       // callback to deliver success or error code to client layer
17135ffb0c9Toomas Soome    const void *StatusContext;                // Client Context
17145ffb0c9Toomas Soome} HostnameInfo;
17154b22b93rs
17164b22b93rstypedef struct ExtraResourceRecord_struct ExtraResourceRecord;
17174b22b93rsstruct ExtraResourceRecord_struct
17185ffb0c9Toomas Soome{
17195ffb0c9Toomas Soome    ExtraResourceRecord *next;
17204b22b93rs    mDNSu32 ClientID;  // Opaque ID field to be used by client to map an AddRecord call to a set of Extra records
17215ffb0c9Toomas Soome    AuthRecord r;
17225ffb0c9Toomas Soome    // Note: Add any additional fields *before* the AuthRecord in this structure, not at the end.
17235ffb0c9Toomas Soome    // In some cases clients can allocate larger chunks of memory and set r->rdata->MaxRDLength to indicate
17245ffb0c9Toomas Soome    // that this extra memory is available, which would result in any fields after the AuthRecord getting smashed
17255ffb0c9Toomas Soome};
17265ffb0c9Toomas Soome
17275ffb0c9Toomas Soome// Note: Within an mDNSServiceCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
17285ffb0c9Toomas Soometypedef void mDNSServiceCallback (mDNS *const m, ServiceRecordSet *const sr, mStatus result);
17295ffb0c9Toomas Soome
17305ffb0c9Toomas Soome// A ServiceRecordSet has no special meaning to the core code of the Multicast DNS protocol engine;
17315ffb0c9Toomas Soome// it is just a convenience structure to group together the records that make up a standard service
17325ffb0c9Toomas Soome// registration so that they can be allocted and deallocted together as a single memory object.
17335ffb0c9Toomas Soome// It contains its own ServiceCallback+ServiceContext to report aggregate results up to the next layer of software above.
17345ffb0c9Toomas Soome// It also contains:
17355ffb0c9Toomas Soome//  * the basic PTR/SRV/TXT triplet used to represent any DNS-SD service
17365ffb0c9Toomas Soome//  * the "_services" PTR record for service enumeration
17375ffb0c9Toomas Soome//  * the optional list of SubType PTR records
17385ffb0c9Toomas Soome//  * the optional list of additional records attached to the service set (e.g. iChat pictures)
17394b22b93rs
17404b22b93rsstruct ServiceRecordSet_struct
17415ffb0c9Toomas Soome{
17425ffb0c9Toomas Soome    // These internal state fields are used internally by mDNSCore; the client layer needn't be concerned with them.
17435ffb0c9Toomas Soome    // No fields need to be set up by the client prior to calling mDNS_RegisterService();
17445ffb0c9Toomas Soome    // all required data is passed as parameters to that function.
17455ffb0c9Toomas Soome    mDNSServiceCallback *ServiceCallback;
17465ffb0c9Toomas Soome    void                *ServiceContext;
17475ffb0c9Toomas Soome    mDNSBool Conflict;              // Set if this record set was forcibly deregistered because of a conflict
17485ffb0c9Toomas Soome
17495ffb0c9Toomas Soome    ExtraResourceRecord *Extras;    // Optional list of extra AuthRecords attached to this service registration
17505ffb0c9Toomas Soome    mDNSu32 NumSubTypes;
17515ffb0c9Toomas Soome    AuthRecord          *SubTypes;
17525ffb0c9Toomas Soome    const mDNSu8        *AnonData;
1753c65ebfcToomas Soome    mDNSu32             flags;      // saved for subsequent calls to mDNS_RegisterService() if records
17545ffb0c9Toomas Soome                                    // need to be re-registered.
17555ffb0c9Toomas Soome    AuthRecord RR_ADV;              // e.g. _services._dns-sd._udp.local. PTR _printer._tcp.local.
17565ffb0c9Toomas Soome    AuthRecord RR_PTR;              // e.g. _printer._tcp.local.        PTR Name._printer._tcp.local.
17575ffb0c9Toomas Soome    AuthRecord RR_SRV;              // e.g. Name._printer._tcp.local.   SRV 0 0 port target
17585ffb0c9Toomas Soome    AuthRecord RR_TXT;              // e.g. Name._printer._tcp.local.   TXT PrintQueueName
17595ffb0c9Toomas Soome    // Don't add any fields after AuthRecord RR_TXT.
17605ffb0c9Toomas Soome    // This is where the implicit extra space goes if we allocate a ServiceRecordSet containing an oversized RR_TXT record
17615ffb0c9Toomas Soome};
17624b22b93rs
17634b22b93rs// ***************************************************************************
17644b22b93rs#if 0
17655ffb0c9Toomas Soome#pragma mark -
17664b22b93rs#pragma mark - Question structures
17674b22b93rs#endif
17684b22b93rs
17694b22b93rs// We record the last eight instances of each duplicate query
17705ffb0c9Toomas Soome// This gives us v4/v6 on each of Ethernet, AirPort and Firewire, and two free slots "for future expansion"
17714b22b93rs// If the host has more active interfaces that this it is not fatal -- duplicate question suppression will degrade gracefully.
17724b22b93rs// Since we will still remember the last eight, the busiest interfaces will still get the effective duplicate question suppression.
17734b22b93rs#define DupSuppressInfoSize 8
17744b22b93rs
17754b22b93rstypedef struct
17765ffb0c9Toomas Soome{
17775ffb0c9Toomas Soome    mDNSs32 Time;
17785ffb0c9Toomas Soome    mDNSInterfaceID InterfaceID;
17795ffb0c9Toomas Soome    mDNSs32 Type;                           // v4 or v6?
17805ffb0c9Toomas Soome} DupSuppressInfo;
17814b22b93rs
17824b22b93rstypedef enum
17835ffb0c9Toomas Soome{
17845ffb0c9Toomas Soome    LLQ_InitialRequest    = 1,
17855ffb0c9Toomas Soome    LLQ_SecondaryRequest  = 2,
17865ffb0c9Toomas Soome    LLQ_Established       = 3,
17875ffb0c9Toomas Soome    LLQ_Poll              = 4
17885ffb0c9Toomas Soome} LLQ_State;
17894b22b93rs
17904b22b93rs// LLQ constants
17914b22b93rs#define kLLQ_Vers      1
17924b22b93rs#define kLLQ_DefLease  7200 // 2 hours
17934b22b93rs#define kLLQ_MAX_TRIES 3    // retry an operation 3 times max
17944b22b93rs#define kLLQ_INIT_RESEND 2 // resend an un-ack'd packet after 2 seconds, then double for each additional
17954b22b93rs// LLQ Operation Codes
17964b22b93rs#define kLLQOp_Setup     1
17974b22b93rs#define kLLQOp_Refresh   2
17984b22b93rs#define kLLQOp_Event     3
17994b22b93rs
18004b22b93rs// LLQ Errror Codes
18014b22b93rsenum
18025ffb0c9Toomas Soome{
18035ffb0c9Toomas Soome    LLQErr_NoError    = 0,
18045ffb0c9Toomas Soome    LLQErr_ServFull   = 1,
18055ffb0c9Toomas Soome    LLQErr_Static     = 2,
18065ffb0c9Toomas Soome    LLQErr_FormErr    = 3,
18075ffb0c9Toomas Soome    LLQErr_NoSuchLLQ  = 4,
18085ffb0c9Toomas Soome    LLQErr_BadVers    = 5,
18095ffb0c9Toomas Soome    LLQErr_UnknownErr = 6
18105ffb0c9Toomas Soome};
18115ffb0c9Toomas Soome
18125ffb0c9Toomas Soomeenum { NoAnswer_Normal = 0, NoAnswer_Suspended = 1, NoAnswer_Fail = 2 };
18135ffb0c9Toomas Soome
1814c65ebfcToomas Soome// DNS Push Notification
1815c65ebfcToomas Soometypedef enum
1816c65ebfcToomas Soome{
1817c65ebfcToomas Soome    DNSPUSH_NOERROR  = 0,
1818c65ebfcToomas Soome    DNSPUSH_FORMERR  = 1,
1819c65ebfcToomas Soome    DNSPUSH_SERVFAIL = 2,
1820c65ebfcToomas Soome    DNSPUSH_NOTIMP   = 4,
1821c65ebfcToomas Soome    DNSPUSH_REFUSED  = 5
1822c65ebfcToomas Soome} DNSPUSH_ErrorCode;
1823c65ebfcToomas Soome
1824c65ebfcToomas Soometypedef enum {
1825c65ebfcToomas Soome    DNSPUSH_INIT         = 1,
1826c65ebfcToomas Soome    DNSPUSH_NOSERVER     = 2,
1827c65ebfcToomas Soome    DNSPUSH_SERVERFOUND  = 3,
1828c65ebfcToomas Soome    DNSPUSH_ESTABLISHED  = 4
1829c65ebfcToomas Soome} DNSPush_State;
18303b436d0Toomas Soome
18313b436d0Toomas Soomeenum {
18323b436d0Toomas Soome    AllowExpired_None = 0,                  // Don't allow expired answers or mark answers immortal (behave normally)
18333b436d0Toomas Soome    AllowExpired_MakeAnswersImmortal = 1,   // Any answers to this question get marked as immortal
18343b436d0Toomas Soome    AllowExpired_AllowExpiredAnswers = 2    // Allow already expired answers from the cache
18353b436d0Toomas Soome};
18363b436d0Toomas Soometypedef mDNSu8 AllowExpiredState;
1837c65ebfcToomas Soome
18385ffb0c9Toomas Soome#define HMAC_LEN    64
18395ffb0c9Toomas Soome#define HMAC_IPAD   0x36
18405ffb0c9Toomas Soome#define HMAC_OPAD   0x5c
18415ffb0c9Toomas Soome#define MD5_LEN     16
18425ffb0c9Toomas Soome
18435ffb0c9Toomas Soome#define AutoTunnelUnregistered(X) (                                               \
18445ffb0c9Toomas Soome        (X)->AutoTunnelHostRecord.resrec.RecordType == kDNSRecordTypeUnregistered && \
18455ffb0c9Toomas Soome        (X)->AutoTunnelTarget.resrec.RecordType == kDNSRecordTypeUnregistered && \
18465ffb0c9Toomas Soome        (X)->AutoTunnelDeviceInfo.resrec.RecordType == kDNSRecordTypeUnregistered && \
18475ffb0c9Toomas Soome        (X)->AutoTunnelService.resrec.RecordType == kDNSRecordTypeUnregistered && \
18485ffb0c9Toomas Soome        (X)->AutoTunnel6Record.resrec.RecordType == kDNSRecordTypeUnregistered )
18495ffb0c9Toomas Soome
18505ffb0c9Toomas Soome// Internal data structure to maintain authentication information
18515ffb0c9Toomas Soometypedef struct DomainAuthInfo
18525ffb0c9Toomas Soome{
18535ffb0c9Toomas Soome    struct DomainAuthInfo *next;
18545ffb0c9Toomas Soome    mDNSs32 deltime;                        // If we're planning to delete this DomainAuthInfo, the time we want it deleted
18555ffb0c9Toomas Soome    mDNSBool   AutoTunnel;                  // Whether this is AutoTunnel
18565ffb0c9Toomas Soome    AuthRecord AutoTunnelHostRecord;        // User-visible hostname; used as SRV target for AutoTunnel services
18575ffb0c9Toomas Soome    AuthRecord AutoTunnelTarget;            // Opaque hostname of tunnel endpoint; used as SRV target for AutoTunnelService record
18585ffb0c9Toomas Soome    AuthRecord AutoTunnelDeviceInfo;        // Device info of tunnel endpoint
18595ffb0c9Toomas Soome    AuthRecord AutoTunnelService;           // Service record (possibly NAT-Mapped) of IKE daemon implementing tunnel endpoint
18605ffb0c9Toomas Soome    AuthRecord AutoTunnel6Record;           // AutoTunnel AAAA Record obtained from awacsd
18615ffb0c9Toomas Soome    mDNSBool AutoTunnelServiceStarted;         // Whether a service has been registered in this domain
18625ffb0c9Toomas Soome    mDNSv6Addr AutoTunnelInnerAddress;
18635ffb0c9Toomas Soome    domainname domain;
18645ffb0c9Toomas Soome    domainname keyname;
18655ffb0c9Toomas Soome    domainname hostname;
18665ffb0c9Toomas Soome    mDNSIPPort port;
18675ffb0c9Toomas Soome    char b64keydata[32];
18685ffb0c9Toomas Soome    mDNSu8 keydata_ipad[HMAC_LEN];              // padded key for inner hash rounds
18695ffb0c9Toomas Soome    mDNSu8 keydata_opad[HMAC_LEN];              // padded key for outer hash rounds
18705ffb0c9Toomas Soome} DomainAuthInfo;
18715ffb0c9Toomas Soome
18725ffb0c9Toomas Soome// Note: Within an mDNSQuestionCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
18735ffb0c9Toomas Soome// Note: Any value other than QC_rmv i.e., any non-zero value will result in kDNSServiceFlagsAdd to the application
18745ffb0c9Toomas Soome// layer. These values are used within mDNSResponder and not sent across to the application. QC_addnocache is for
18755ffb0c9Toomas Soome// delivering a response without adding to the cache. QC_forceresponse is superset of QC_addnocache where in
18765ffb0c9Toomas Soome// addition to not entering in the cache, it also forces the negative response through.
18775ffb0c9Toomas Soometypedef enum { QC_rmv = 0, QC_add, QC_addnocache, QC_forceresponse, QC_dnssec , QC_nodnssec, QC_suppressed } QC_result;
18785ffb0c9Toomas Soometypedef void mDNSQuestionCallback (mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord);
18795ffb0c9Toomas Soometypedef void AsyncDispatchFunc(mDNS *const m, void *context);
18805ffb0c9Toomas Soometypedef void DNSSECAuthInfoFreeCallback(mDNS *const m, void *context);
18815ffb0c9Toomas Soomeextern void mDNSPlatformDispatchAsync(mDNS *const m, void *context, AsyncDispatchFunc func);
18825ffb0c9Toomas Soome
18835ffb0c9Toomas Soome#define NextQSendTime(Q)  ((Q)->LastQTime + (Q)->ThisQInterval)
18845ffb0c9Toomas Soome#define ActiveQuestion(Q) ((Q)->ThisQInterval > 0 && !(Q)->DuplicateOf)
18855ffb0c9Toomas Soome#define TimeToSendThisQuestion(Q,time) (ActiveQuestion(Q) && (time) - NextQSendTime(Q) >= 0)
18865ffb0c9Toomas Soome
18875ffb0c9Toomas Soome// q->ValidationStatus is either DNSSECValNotRequired or DNSSECValRequired and then moves onto DNSSECValInProgress.
18885ffb0c9Toomas Soome// When Validation is done, we mark all "DNSSECValInProgress" questions "DNSSECValDone". If we are answering
18895ffb0c9Toomas Soome// questions from /etc/hosts, then we go straight to DNSSECValDone from the initial state.
18905ffb0c9Toomas Soometypedef enum { DNSSECValNotRequired = 0, DNSSECValRequired, DNSSECValInProgress, DNSSECValDone } DNSSECValState;
18915ffb0c9Toomas Soome
18925ffb0c9Toomas Soome// ValidationRequired can be set to the following values:
18935ffb0c9Toomas Soome//
1894c65ebfcToomas Soome// SECURE validation is set to determine whether something is secure or bogus
18955ffb0c9Toomas Soome// INSECURE validation is set internally by dnssec code to indicate that it is currently proving something
18965ffb0c9Toomas Soome// is insecure
18975ffb0c9Toomas Soome#define DNSSEC_VALIDATION_NONE              0x00
18985ffb0c9Toomas Soome#define DNSSEC_VALIDATION_SECURE            0x01
18995ffb0c9Toomas Soome#define DNSSEC_VALIDATION_SECURE_OPTIONAL   0x02
19005ffb0c9Toomas Soome#define DNSSEC_VALIDATION_INSECURE          0x03
19015ffb0c9Toomas Soome
19025ffb0c9Toomas Soome// For both ValidationRequired and ValidatingResponse question, we validate DNSSEC responses.
19035ffb0c9Toomas Soome// For ProxyQuestion with DNSSECOK, we just receive the DNSSEC records to pass them along without
19045ffb0c9Toomas Soome// validation and if the CD bit is not set, we also validate.
19055ffb0c9Toomas Soome#define DNSSECQuestion(q) ((q)->ValidationRequired || (q)->ValidatingResponse || ((q)->ProxyQuestion && (q)->ProxyDNSSECOK))
19065ffb0c9Toomas Soome
19075ffb0c9Toomas Soome// ValidatingQuestion is used when we need to know whether we are validating the DNSSEC responses for a question
19085ffb0c9Toomas Soome#define ValidatingQuestion(q) ((q)->ValidationRequired || (q)->ValidatingResponse)
19095ffb0c9Toomas Soome
19105ffb0c9Toomas Soome#define DNSSECOptionalQuestion(q) ((q)->ValidationRequired == DNSSEC_VALIDATION_SECURE_OPTIONAL)
19115ffb0c9Toomas Soome
19125ffb0c9Toomas Soome// Given the resource record and the question, should we follow the CNAME ?
19135ffb0c9Toomas Soome#define FollowCNAME(q, rr, AddRecord)   (AddRecord && (q)->qtype != kDNSType_CNAME && \
19145ffb0c9Toomas Soome                                         (rr)->RecordType != kDNSRecordTypePacketNegative && \
19155ffb0c9Toomas Soome                                         (rr)->rrtype == kDNSType_CNAME)
19165ffb0c9Toomas Soome
1917c65ebfcToomas Soome// RFC 4122 defines it to be 16 bytes
19185ffb0c9Toomas Soome#define UUID_SIZE       16
19195ffb0c9Toomas Soome
19203b436d0Toomas Soome#define AWD_METRICS (USE_AWD && TARGET_OS_IOS)
1921c65ebfcToomas Soome
1922c65ebfcToomas Soome#if AWD_METRICS
19233b436d0Toomas Soome
19243b436d0Toomas Soomeenum
1925cda73f6Toomas Soome{
19263b436d0Toomas Soome    ExpiredAnswer_None = 0,                  // No expired answers used
19273b436d0Toomas Soome    ExpiredAnswer_Allowed = 1,               // An expired answer is allowed by this request
19283b436d0Toomas Soome    ExpiredAnswer_AnsweredWithExpired = 2,   // Question was answered with an expired answer
19293b436d0Toomas Soome    ExpiredAnswer_ExpiredAnswerChanged = 3,  // Expired answer changed on refresh
19303b436d0Toomas Soome
19313b436d0Toomas Soome    ExpiredAnswer_EnumCount
19323b436d0Toomas Soome};
19333b436d0Toomas Soometypedef mDNSu8 ExpiredAnswerMetric;
1934cda73f6Toomas Soome
19353b436d0Toomas Soometypedef struct
19363b436d0Toomas Soome{
19373b436d0Toomas Soome    domainname *        originalQName;          // Name of original A/AAAA record if this question is for a CNAME record.
19383b436d0Toomas Soome    mDNSu32             querySendCount;         // Number of queries that have been sent to DNS servers so far.
19393b436d0Toomas Soome    mDNSs32             firstQueryTime;         // The time when the first query was sent to a DNS server.
19403b436d0Toomas Soome    mDNSBool            answered;               // Has this question been answered?
19413b436d0Toomas Soome    ExpiredAnswerMetric expiredAnswerState;     // Expired answer state (see ExpiredAnswerMetric above)
19423b436d0Toomas Soome
1943cda73f6Toomas Soome}   uDNSMetrics;
1944cda73f6Toomas Soome#endif
1945cda73f6Toomas Soome
1946c65ebfcToomas Soome// DNS64 code is only for iOS, which is currently the only Apple OS that supports DNS proxy network extensions.
1947c65ebfcToomas Soome#define USE_DNS64 (HAVE_DNS64 && TARGET_OS_IOS)
1948c65ebfcToomas Soome
1949c65ebfcToomas Soome#if USE_DNS64
1950c65ebfcToomas Soome#include "DNS64State.h"
1951c65ebfcToomas Soome#endif
1952c65ebfcToomas Soome
1953c65ebfcToomas Soome#if TARGET_OS_EMBEDDED
1954c65ebfcToomas Soomeextern mDNSu32 curr_num_regservices; // tracks the current number of services registered
1955c65ebfcToomas Soomeextern mDNSu32 max_num_regservices;  // tracks the max number of simultaneous services registered by the device
1956c65ebfcToomas Soome#endif
1957c65ebfcToomas Soome
19584b22b93rsstruct DNSQuestion_struct
19595ffb0c9Toomas Soome{
19605ffb0c9Toomas Soome    // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
19615ffb0c9Toomas Soome    DNSQuestion          *next;
19625ffb0c9Toomas Soome    mDNSu32 qnamehash;
19635ffb0c9Toomas Soome    mDNSs32 DelayAnswering;                 // Set if we want to defer answering this question until the cache settles
19645ffb0c9Toomas Soome    mDNSs32 LastQTime;                      // Last scheduled transmission of this Q on *all* applicable interfaces
19655ffb0c9Toomas Soome    mDNSs32 ThisQInterval;                  // LastQTime + ThisQInterval is the next scheduled transmission of this Q
19665ffb0c9Toomas Soome                                            // ThisQInterval > 0 for an active question;
19675ffb0c9Toomas Soome                                            // ThisQInterval = 0 for a suspended question that's still in the list
19685ffb0c9Toomas Soome                                            // ThisQInterval = -1 for a cancelled question (should not still be in list)
19695ffb0c9Toomas Soome    mDNSs32 ExpectUnicastResp;              // Set when we send a query with the kDNSQClass_UnicastResponse bit set
19705ffb0c9Toomas Soome    mDNSs32 LastAnswerPktNum;               // The sequence number of the last response packet containing an answer to this Q
19715ffb0c9Toomas Soome    mDNSu32 RecentAnswerPkts;               // Number of answers since the last time we sent this query
19725ffb0c9Toomas Soome    mDNSu32 CurrentAnswers;                 // Number of records currently in the cache that answer this question
19735ffb0c9Toomas Soome    mDNSu32 BrowseThreshold;                // If we have received at least this number of answers,
19745ffb0c9Toomas Soome                                            // set the next question interval to MaxQuestionInterval
19755ffb0c9Toomas Soome    mDNSu32 LargeAnswers;                   // Number of answers with rdata > 1024 bytes
19765ffb0c9Toomas Soome    mDNSu32 UniqueAnswers;                  // Number of answers received with kDNSClass_UniqueRRSet bit set
19775ffb0c9Toomas Soome    mDNSInterfaceID FlappingInterface1;     // Set when an interface goes away, to flag if remove events are delivered for this Q
19785ffb0c9Toomas Soome    mDNSInterfaceID FlappingInterface2;     // Set when an interface goes away, to flag if remove events are delivered for this Q
19795ffb0c9Toomas Soome    DomainAuthInfo       *AuthInfo;         // Non-NULL if query is currently being done using Private DNS
19805ffb0c9Toomas Soome    DNSQuestion          *DuplicateOf;
19815ffb0c9Toomas Soome    DNSQuestion          *NextInDQList;
19825ffb0c9Toomas Soome    AnonymousInfo        *AnonInfo;         // Anonymous Information
19835ffb0c9Toomas Soome    DupSuppressInfo DupSuppress[DupSuppressInfoSize];
19845ffb0c9Toomas Soome    mDNSInterfaceID SendQNow;               // The interface this query is being sent on right now
19855ffb0c9Toomas Soome    mDNSBool SendOnAll;                     // Set if we're sending this question on all active interfaces
1986c65ebfcToomas Soome    mDNSBool CachedAnswerNeedsUpdate;       // See SendQueries().  Set if we're sending this question
19875ffb0c9Toomas Soome                                            // because a cached answer needs to be refreshed.
19885ffb0c9Toomas Soome    mDNSu32 RequestUnicast;                 // Non-zero if we want to send query with kDNSQClass_UnicastResponse bit set
19895ffb0c9Toomas Soome    mDNSs32 LastQTxTime;                    // Last time this Q was sent on one (but not necessarily all) interfaces
19905ffb0c9Toomas Soome    mDNSu32 CNAMEReferrals;                 // Count of how many CNAME redirections we've done
19915ffb0c9Toomas Soome    mDNSBool SuppressQuery;                 // This query should be suppressed and not sent on the wire
19925ffb0c9Toomas Soome    mDNSu8 LOAddressAnswers;                // Number of answers from the local only auth records that are
19935ffb0c9Toomas Soome                                            // answering A, AAAA, CNAME, or PTR (/etc/hosts)
19945ffb0c9Toomas Soome    mDNSu8 WakeOnResolveCount;              // Number of wakes that should be sent on resolve
19955ffb0c9Toomas Soome    mDNSs32 StopTime;                       // Time this question should be stopped by giving them a negative answer
19965ffb0c9Toomas Soome
19975ffb0c9Toomas Soome    // DNSSEC fields
19985ffb0c9Toomas Soome    DNSSECValState ValidationState;            // Current state of the Validation process
19995ffb0c9Toomas Soome    DNSSECStatus ValidationStatus;             // Validation status for "ValidationRequired" questions (dnssec)
20005ffb0c9Toomas Soome    mDNSu8 ValidatingResponse;                 // Question trying to validate a response (dnssec) on behalf of
20015ffb0c9Toomas Soome                                               // ValidationRequired question
20025ffb0c9Toomas Soome    void *DNSSECAuthInfo;
20035ffb0c9Toomas Soome    DNSSECAuthInfoFreeCallback *DAIFreeCallback;
20045ffb0c9Toomas Soome
20055ffb0c9Toomas Soome    // Wide Area fields. These are used internally by the uDNS core (Unicast)
20065ffb0c9Toomas Soome    UDPSocket            *LocalSocket;
20075ffb0c9Toomas Soome
20085ffb0c9Toomas Soome    // |-> DNS Configuration related fields used in uDNS (Subset of Wide Area/Unicast fields)
20095ffb0c9Toomas Soome    DNSServer            *qDNSServer;       // Caching server for this query (in the absence of an SRV saying otherwise)
2010c65ebfcToomas Soome    mDNSOpaque128 validDNSServers;          // Valid DNSServers for this question
20115ffb0c9Toomas Soome    mDNSu16 noServerResponse;               // At least one server did not respond.
20125ffb0c9Toomas Soome    mDNSu16 triedAllServersOnce;            // Tried all DNS servers once
20135ffb0c9Toomas Soome    mDNSu8 unansweredQueries;               // The number of unanswered queries to this server
20143b436d0Toomas Soome    AllowExpiredState allowExpired;         // Allow expired answers state (see enum AllowExpired_None, etc. above)
20155ffb0c9Toomas Soome
20165ffb0c9Toomas Soome    ZoneData             *nta;              // Used for getting zone data for private or LLQ query
20175ffb0c9Toomas Soome    mDNSAddr servAddr;                      // Address and port learned from _dns-llq, _dns-llq-tls or _dns-query-tls SRV query
20185ffb0c9Toomas Soome    mDNSIPPort servPort;
20195ffb0c9Toomas Soome    struct tcpInfo_t *tcp;
20205ffb0c9Toomas Soome    mDNSIPPort tcpSrcPort;                  // Local Port TCP packet received on;need this as tcp struct is disposed
20215ffb0c9Toomas Soome                                            // by tcpCallback before calling into mDNSCoreReceive
20225ffb0c9Toomas Soome    mDNSu8 NoAnswer;                        // Set if we want to suppress answers until tunnel setup has completed
20235ffb0c9Toomas Soome    mDNSu8 Restart;                         // This question should be restarted soon
20245ffb0c9Toomas Soome
20255ffb0c9Toomas Soome    // LLQ-specific fields. These fields are only meaningful when LongLived flag is set
20265ffb0c9Toomas Soome    LLQ_State state;
20275ffb0c9Toomas Soome    mDNSu32 ReqLease;                       // seconds (relative)
20285ffb0c9Toomas Soome    mDNSs32 expire;                         // ticks (absolute)
20295ffb0c9Toomas Soome    mDNSs16 ntries;                         // for UDP: the number of packets sent for this LLQ state
20305ffb0c9Toomas Soome                                            // for TCP: there is some ambiguity in the use of this variable, but in general, it is
20315ffb0c9Toomas Soome                                            //          the number of TCP/TLS connection attempts for this LLQ state, or
20325ffb0c9Toomas Soome                                            //          the number of packets sent for this TCP/TLS connection
2033c65ebfcToomas Soome
2034c65ebfcToomas Soome    // DNS Push Notification fields. These fields are only meaningful when LongLived flag is set
2035c65ebfcToomas Soome    DNSPush_State dnsPushState;             // The state of the DNS push notification negotiation
2036c65ebfcToomas Soome    mDNSAddr      dnsPushServerAddr;        // Address of the system acting as the DNS Push Server
2037c65ebfcToomas Soome    mDNSIPPort    dnsPushServerPort;        // Port on which the DNS Push Server is being advertised.
2038c65ebfcToomas Soome
20395ffb0c9Toomas Soome    mDNSOpaque64 id;
20405ffb0c9Toomas Soome
20415ffb0c9Toomas Soome    // DNS Proxy fields
20425ffb0c9Toomas Soome    mDNSOpaque16 responseFlags;             // Temporary place holder for the error we get back from the DNS server
20435ffb0c9Toomas Soome                                            // till we populate in the cache
20445ffb0c9Toomas Soome    mDNSBool     DisallowPID;               // Is the query allowed for the "PID" that we are sending on behalf of ?
20455ffb0c9Toomas Soome    mDNSs32      ServiceID;                 // Service identifier to match against the DNS server
2046c65ebfcToomas Soome
20475ffb0c9Toomas Soome    // Client API fields: The client must set up these fields *before* calling mDNS_StartQuery()
20485ffb0c9Toomas Soome    mDNSInterfaceID InterfaceID;            // Non-zero if you want to issue queries only on a single specific IP interface
20495ffb0c9Toomas Soome    mDNSu32  flags;                         // flags from original DNSService*() API request.
20505ffb0c9Toomas Soome    mDNSAddr Target;                        // Non-zero if you want to direct queries to a specific unicast target address
20515ffb0c9Toomas Soome    mDNSIPPort TargetPort;                  // Must be set if Target is set
20525ffb0c9Toomas Soome    mDNSOpaque16 TargetQID;                 // Must be set if Target is set
20535ffb0c9Toomas Soome    domainname qname;
20543b436d0Toomas Soome    domainname firstExpiredQname;           // first expired qname in request chain
20555ffb0c9Toomas Soome    mDNSu16 qtype;
20565ffb0c9Toomas Soome    mDNSu16 qclass;
20575ffb0c9Toomas Soome    mDNSBool LongLived;                     // Set by client for calls to mDNS_StartQuery to indicate LLQs to unicast layer.
20585ffb0c9Toomas Soome    mDNSBool ExpectUnique;                  // Set by client if it's expecting unique RR(s) for this question, not shared RRs
20595ffb0c9Toomas Soome    mDNSBool ForceMCast;                    // Set by client to force mDNS query, even for apparently uDNS names
20605ffb0c9Toomas Soome    mDNSBool ReturnIntermed;                // Set by client to request callbacks for intermediate CNAME/NXDOMAIN results
20615ffb0c9Toomas Soome    mDNSBool SuppressUnusable;              // Set by client to suppress unusable queries to be sent on the wire
20625ffb0c9Toomas Soome    mDNSu8 RetryWithSearchDomains;          // Retry with search domains if there is no entry in the cache or AuthRecords
20635ffb0c9Toomas Soome    mDNSu8 TimeoutQuestion;                 // Timeout this question if there is no reply in configured time
20645ffb0c9Toomas Soome    mDNSu8 WakeOnResolve;                   // Send wakeup on resolve
20655ffb0c9Toomas Soome    mDNSu8 UseBackgroundTrafficClass;       // Set by client to use background traffic class for request
20665ffb0c9Toomas Soome    mDNSs8 SearchListIndex;                 // Index into SearchList; Used by the client layer but not touched by core
20675ffb0c9Toomas Soome    mDNSs8 AppendSearchDomains;             // Search domains can be appended for this query
20685ffb0c9Toomas Soome    mDNSs8 AppendLocalSearchDomains;        // Search domains ending in .local can be appended for this query
20695ffb0c9Toomas Soome    mDNSu8 ValidationRequired;              // Requires DNSSEC validation.
20705ffb0c9Toomas Soome    mDNSu8 ProxyQuestion;                   // Proxy Question
20715ffb0c9Toomas Soome    mDNSu8 ProxyDNSSECOK;                   // Proxy Question with EDNS0 DNSSEC OK bit set
20725ffb0c9Toomas Soome    mDNSs32 pid;                            // Process ID of the client that is requesting the question
20735ffb0c9Toomas Soome    mDNSu8  uuid[UUID_SIZE];                // Unique ID of the client that is requesting the question (valid only if pid is zero)
2074cda73f6Toomas Soome    mDNSu32 euid;                           // Effective User Id of the client that is requesting the question
20755ffb0c9Toomas Soome    domainname           *qnameOrig;        // Copy of the original question name if it is not fully qualified
20765ffb0c9Toomas Soome    mDNSQuestionCallback *QuestionCallback;
20775ffb0c9Toomas Soome    void                 *QuestionContext;
20783b436d0Toomas Soome#if AWD_METRICS
2079cda73f6Toomas Soome    uDNSMetrics metrics;                    // Data used for collecting unicast DNS query metrics.
2080cda73f6Toomas Soome#endif
2081c65ebfcToomas Soome#if USE_DNS64
2082c65ebfcToomas Soome    DNS64 dns64;                            // DNS64 state for performing IPv6 address synthesis on networks with NAT64.
2083c65ebfcToomas Soome#endif
20845ffb0c9Toomas Soome};
20854b22b93rs
2086c65ebfcToomas Soometypedef enum { ZoneServiceUpdate, ZoneServiceQuery, ZoneServiceLLQ, ZoneServiceDNSPush } ZoneService;
20875ffb0c9Toomas Soome
20885ffb0c9Toomas Soometypedef void ZoneDataCallback (mDNS *const m, mStatus err, const ZoneData *result);
20895ffb0c9Toomas Soome
20905ffb0c9Toomas Soomestruct ZoneData_struct
20915ffb0c9Toomas Soome{
20925ffb0c9Toomas Soome    domainname ChildName;               // Name for which we're trying to find the responsible server
20935ffb0c9Toomas Soome    ZoneService ZoneService;            // Which service we're seeking for this zone (update, query, or LLQ)
20945ffb0c9Toomas Soome    domainname       *CurrentSOA;       // Points to somewhere within ChildName
20955ffb0c9Toomas Soome    domainname ZoneName;                // Discovered result: Left-hand-side of SOA record
20965ffb0c9Toomas Soome    mDNSu16 ZoneClass;                  // Discovered result: DNS Class from SOA record
20975ffb0c9Toomas Soome    domainname Host;                    // Discovered result: Target host from SRV record
20985ffb0c9Toomas Soome    mDNSIPPort Port;                    // Discovered result: Update port, query port, or LLQ port from SRV record
20995ffb0c9Toomas Soome    mDNSAddr Addr;                      // Discovered result: Address of Target host from SRV record
21005ffb0c9Toomas Soome    mDNSBool ZonePrivate;               // Discovered result: Does zone require encrypted queries?
21015ffb0c9Toomas Soome    ZoneDataCallback *ZoneDataCallback; // Caller-specified function to be called upon completion
21025ffb0c9Toomas Soome    void             *ZoneDataContext;
21035ffb0c9Toomas Soome    DNSQuestion question;               // Storage for any active question
21045ffb0c9Toomas Soome};
21055ffb0c9Toomas Soome
21065ffb0c9Toomas Soomeextern ZoneData *StartGetZoneData(mDNS *const m, const domainname *const name, const ZoneService target, ZoneDataCallback callback, void *callbackInfo);
21075ffb0c9Toomas Soomeextern void CancelGetZoneData(mDNS *const m, ZoneData *nta);
21085ffb0c9Toomas Soomeextern mDNSBool IsGetZoneDataQuestion(DNSQuestion *q);
21095ffb0c9Toomas Soome
21105ffb0c9Toomas Soometypedef struct DNameListElem
21115ffb0c9Toomas Soome{
21125ffb0c9Toomas Soome    struct DNameListElem *next;
21135ffb0c9Toomas Soome    mDNSu32 uid;
21145ffb0c9Toomas Soome    domainname name;
21155ffb0c9Toomas Soome} DNameListElem;
21165ffb0c9Toomas Soome
21175ffb0c9Toomas Soome#if APPLE_OSX_mDNSResponder
21185ffb0c9Toomas Soome// Different states that we go through locating the peer
21195ffb0c9Toomas Soome#define TC_STATE_AAAA_PEER          0x000000001     /* Peer's BTMM IPv6 address */
21205ffb0c9Toomas Soome#define TC_STATE_AAAA_PEER_RELAY    0x000000002     /* Peer's IPv6 Relay address */
21215ffb0c9Toomas Soome#define TC_STATE_SRV_PEER           0x000000003     /* Peer's SRV Record corresponding to IPv4 address */
21225ffb0c9Toomas Soome#define TC_STATE_ADDR_PEER          0x000000004     /* Peer's IPv4 address */
21235ffb0c9Toomas Soome
21245ffb0c9Toomas Soometypedef struct ClientTunnel
21255ffb0c9Toomas Soome{
21265ffb0c9Toomas Soome    struct ClientTunnel *next;
21275ffb0c9Toomas Soome    domainname dstname;
21285ffb0c9Toomas Soome    mDNSBool MarkedForDeletion;
21295ffb0c9Toomas Soome    mDNSv6Addr loc_inner;
21305ffb0c9Toomas Soome    mDNSv4Addr loc_outer;
21315ffb0c9Toomas Soome    mDNSv6Addr loc_outer6;
21325ffb0c9Toomas Soome    mDNSv6Addr rmt_inner;
21335ffb0c9Toomas Soome    mDNSv4Addr rmt_outer;
21345ffb0c9Toomas Soome    mDNSv6Addr rmt_outer6;
21355ffb0c9Toomas Soome    mDNSIPPort rmt_outer_port;
21365ffb0c9Toomas Soome    mDNSu16 tc_state;
21375ffb0c9Toomas Soome    DNSQuestion q;
21385ffb0c9Toomas Soome} ClientTunnel;
21395ffb0c9Toomas Soome#endif
21404b22b93rs
21414b22b93rs// ***************************************************************************
21424b22b93rs#if 0
21435ffb0c9Toomas Soome#pragma mark -
21445ffb0c9Toomas Soome#pragma mark - NetworkInterfaceInfo_struct
21454b22b93rs#endif
21464b22b93rs
21475ffb0c9Toomas Soometypedef struct NetworkInterfaceInfo_struct NetworkInterfaceInfo;
21484b22b93rs
21495ffb0c9Toomas Soome// A NetworkInterfaceInfo_struct serves two purposes:
21505ffb0c9Toomas Soome// 1. It holds the address, PTR and HINFO records to advertise a given IP address on a given physical interface
21515ffb0c9Toomas Soome// 2. It tells mDNSCore which physical interfaces are available; each physical interface has its own unique InterfaceID.
21525ffb0c9Toomas Soome//    Since there may be multiple IP addresses on a single physical interface,
21535ffb0c9Toomas Soome//    there may be multiple NetworkInterfaceInfo_structs with the same InterfaceID.
21545ffb0c9Toomas Soome//    In this case, to avoid sending the same packet n times, when there's more than one
21555ffb0c9Toomas Soome//    struct with the same InterfaceID, mDNSCore picks one member of the set to be the
21565ffb0c9Toomas Soome//    active representative of the set; all others have the 'InterfaceActive' flag unset.
21574b22b93rs
21585ffb0c9Toomas Soomestruct NetworkInterfaceInfo_struct
21595ffb0c9Toomas Soome{
21605ffb0c9Toomas Soome    // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
21615ffb0c9Toomas Soome    NetworkInterfaceInfo *next;
21625ffb0c9Toomas Soome
21635ffb0c9Toomas Soome    mDNSu8 InterfaceActive;             // Set if interface is sending & receiving packets (see comment above)
21645ffb0c9Toomas Soome    mDNSu8 IPv4Available;               // If InterfaceActive, set if v4 available on this InterfaceID
21655ffb0c9Toomas Soome    mDNSu8 IPv6Available;               // If InterfaceActive, set if v6 available on this InterfaceID
21665ffb0c9Toomas Soome
21675ffb0c9Toomas Soome    DNSQuestion NetWakeBrowse;
21685ffb0c9Toomas Soome    DNSQuestion NetWakeResolve[3];      // For fault-tolerance, we try up to three Sleep Proxies
21695ffb0c9Toomas Soome    mDNSAddr SPSAddr[3];
21705ffb0c9Toomas Soome    mDNSIPPort SPSPort[3];
21715ffb0c9Toomas Soome    mDNSs32 NextSPSAttempt;             // -1 if we're not currently attempting to register with any Sleep Proxy
21725ffb0c9Toomas Soome    mDNSs32 NextSPSAttemptTime;
21735ffb0c9Toomas Soome
21745ffb0c9Toomas Soome    // Standard AuthRecords that every Responder host should have (one per active IP address)
21755ffb0c9Toomas Soome    AuthRecord RR_A;                    // 'A' or 'AAAA' (address) record for our ".local" name
21765ffb0c9Toomas Soome    AuthRecord RR_PTR;                  // PTR (reverse lookup) record
21775ffb0c9Toomas Soome    AuthRecord RR_HINFO;
21785ffb0c9Toomas Soome
21795ffb0c9Toomas Soome    // Client API fields: The client must set up these fields *before* calling mDNS_RegisterInterface()
21805ffb0c9Toomas Soome    mDNSInterfaceID InterfaceID;        // Identifies physical interface; MUST NOT be 0, -1, or -2
21815ffb0c9Toomas Soome    mDNSAddr ip;                        // The IPv4 or IPv6 address to advertise
21825ffb0c9Toomas Soome    mDNSAddr mask;
21835ffb0c9Toomas Soome    mDNSEthAddr MAC;
21845ffb0c9Toomas Soome    char ifname[64];                    // Windows uses a GUID string for the interface name, which doesn't fit in 16 bytes
21855ffb0c9Toomas Soome    mDNSu8 Advertise;                   // False if you are only searching on this interface
21865ffb0c9Toomas Soome    mDNSu8 McastTxRx;                   // Send/Receive multicast on this { InterfaceID, address family } ?
21875ffb0c9Toomas Soome    mDNSu8 NetWake;                     // Set if Wake-On-Magic-Packet is enabled on this interface
21885ffb0c9Toomas Soome    mDNSu8 Loopback;                    // Set if this is the loopback interface
21895ffb0c9Toomas Soome    mDNSu8 IgnoreIPv4LL;                // Set if IPv4 Link-Local addresses have to be ignored.
21905ffb0c9Toomas Soome    mDNSu8 SendGoodbyes;                // Send goodbyes on this interface while sleeping
21915ffb0c9Toomas Soome    mDNSBool DirectLink;                // a direct link, indicating we can skip the probe for
21925ffb0c9Toomas Soome                                        // address records
2193cda73f6Toomas Soome    mDNSBool SupportsUnicastMDNSResponse;  // Indicates that the interface supports unicast responses
21943b436d0Toomas Soome                                        // to Bonjour queries.  Generally true for an interface.
21955ffb0c9Toomas Soome};
21965ffb0c9Toomas Soome
21975ffb0c9Toomas Soome#define SLE_DELETE                      0x00000001
21985ffb0c9Toomas Soome#define SLE_WAB_BROWSE_QUERY_STARTED    0x00000002
21995ffb0c9Toomas Soome#define SLE_WAB_LBROWSE_QUERY_STARTED   0x00000004
22005ffb0c9Toomas Soome#define SLE_WAB_REG_QUERY_STARTED       0x00000008
22015ffb0c9Toomas Soome
22025ffb0c9Toomas Soometypedef struct SearchListElem
22035ffb0c9Toomas Soome{
22045ffb0c9Toomas Soome    struct SearchListElem *next;
22055ffb0c9Toomas Soome    domainname domain;
22065ffb0c9Toomas Soome    int flag;
22075ffb0c9Toomas Soome    mDNSInterfaceID InterfaceID;
22085ffb0c9Toomas Soome    DNSQuestion BrowseQ;
22095ffb0c9Toomas Soome    DNSQuestion DefBrowseQ;
22105ffb0c9Toomas Soome    DNSQuestion AutomaticBrowseQ;
22115ffb0c9Toomas Soome    DNSQuestion RegisterQ;
22125ffb0c9Toomas Soome    DNSQuestion DefRegisterQ;
22135ffb0c9Toomas Soome    int numCfAnswers;
22145ffb0c9Toomas Soome    ARListElem *AuthRecs;
22155ffb0c9Toomas Soome} SearchListElem;
22165ffb0c9Toomas Soome
22175ffb0c9Toomas Soome// For domain enumeration and automatic browsing
22185ffb0c9Toomas Soome// This is the user's DNS search list.
22195ffb0c9Toomas Soome// In each of these domains we search for our special pointer records (lb._dns-sd._udp.<domain>, etc.)
22205ffb0c9Toomas Soome// to discover recommended domains for domain enumeration (browse, default browse, registration,
22215ffb0c9Toomas Soome// default registration) and possibly one or more recommended automatic browsing domains.
22225ffb0c9Toomas Soomeextern SearchListElem *SearchList;      // This really ought to be part of mDNS_struct -- SC
22234b22b93rs
22244b22b93rs// ***************************************************************************
22254b22b93rs#if 0
22265ffb0c9Toomas Soome#pragma mark -
22274b22b93rs#pragma mark - Main mDNS object, used to hold all the mDNS state
22284b22b93rs#endif
22294b22b93rs
22305ffb0c9Toomas Soometypedef void mDNSCallback (mDNS *const m, mStatus result);
22314b22b93rs
22325ffb0c9Toomas Soome#ifndef CACHE_HASH_SLOTS
22334b22b93rs#define CACHE_HASH_SLOTS 499
22345ffb0c9Toomas Soome#endif
22354b22b93rs
22364b22b93rsenum
22375ffb0c9Toomas Soome{
22385ffb0c9Toomas Soome    SleepState_Awake = 0,
22395ffb0c9Toomas Soome    SleepState_Transferring = 1,
22405ffb0c9Toomas Soome    SleepState_Sleeping = 2
22415ffb0c9Toomas Soome};
22425ffb0c9Toomas Soome
22435ffb0c9Toomas Soometypedef enum
22445ffb0c9Toomas Soome{
22455ffb0c9Toomas Soome    kStatsActionIncrement,
22465ffb0c9Toomas Soome    kStatsActionDecrement,
22475ffb0c9