Переглянути джерело

change: 关闭IP包透传,移除mDNS,移除dns服务,进一步释放内存

Wendal Chen 2 роки тому
батько
коміт
a3000d3d7f

+ 1 - 1
include/wm_wifi_config.h

@@ -25,7 +25,7 @@
 
 #define  TLS_CONFIG_AP_BEACON_SOFT         (CFG_OFF && TLS_CONFIG_AP)
 #define  TLS_CONFIG_AP_OPT_PS              (CFG_ON && TLS_CONFIG_AP)/* SOFTAP POWER SAVE */
-#define  TLS_CONFIG_AP_OPT_FWD             (CFG_ON && TLS_CONFIG_AP)/* IP PACKET FORWARD */
+#define  TLS_CONFIG_AP_OPT_FWD             (CFG_OFF && TLS_CONFIG_AP)/* IP PACKET FORWARD */
 
 #define  TLS_CONFIG_WPS       				CFG_WIFI_OFF /* WPS&EAPOL should be enabled together */
 #define  TLS_IEEE8021X_EAPOL   				CFG_WIFI_OFF

+ 11 - 11
platform/sys/tls_sys.c

@@ -110,8 +110,8 @@ static void sys_net_up()
         tls_netif_set_addr( &ip_addr, &net_mask, &gateway);
         MEMCPY((char*)ip_2_ip4(&dns1), &ip_param.dns1, 4);
         MEMCPY((char*)ip_2_ip4(&dns2), &ip_param.dns2, 4);
-        tls_netif_dns_setserver(0, &dns1);
-        tls_netif_dns_setserver(1, &dns2);
+        //tls_netif_dns_setserver(0, &dns1);
+        //tls_netif_dns_setserver(1, &dns2);
 		
 		/*when DHCP is disabled, Use static IP without IP_NET_UP Reporting, 
 		  set wifi powersaving flag according to TLS_PARAM_ID_PSM here.*/
@@ -130,10 +130,10 @@ static void sys_net2_up()
 {
     ip_addr_t ip_addr, net_mask, gateway;
     struct tls_param_ip ip_param;
-    u8 dnsname[32];
+    // u8 dnsname[32];
 
-    dnsname[0] = '\0';
-    tls_param_get(TLS_PARAM_ID_DNSNAME, dnsname, 0);
+    // dnsname[0] = '\0';
+    // tls_param_get(TLS_PARAM_ID_DNSNAME, dnsname, 0);
     tls_param_get(TLS_PARAM_ID_SOFTAP_IP, &ip_param, FALSE);
 
     tls_netif2_set_up();
@@ -148,10 +148,10 @@ static void sys_net2_up()
         tls_dhcps_start();
     }
 
-    if ('\0' != dnsname[0])
-    {
-        tls_dnss_start(dnsname);
-    }
+    // if ('\0' != dnsname[0])
+    // {
+    //     tls_dnss_start(dnsname);
+    // }
 
     return ;
 }
@@ -160,7 +160,7 @@ static void sys_net2_up()
 
 static void sys_net2_down()
 {
-    tls_dnss_stop();
+    //tls_dnss_stop();
 
     tls_dhcps_stop();
 
@@ -229,7 +229,7 @@ static void tls_auto_reconnect_softap(void)
     memcpy(apinfo->keyinfo.key, key.psk, key.key_length);
 
     tls_param_get(TLS_PARAM_ID_SOFTAP_IP, &ip_param, TRUE);
-    /*ip配置信息:ip地址,掩码,dns名称*/
+    /*ip锟斤拷锟斤拷锟斤拷息:ip锟斤拷址锟斤拷锟斤拷锟诫,dns锟斤拷锟斤拷*/
     memcpy(ipinfo->ip_addr, ip_param.ip, 4);
     memcpy(ipinfo->netmask, ip_param.netmask, 4);
     tls_param_get(TLS_PARAM_ID_DNSNAME, ipinfo->dnsname, FALSE);

+ 1 - 1
src/app/dnsserver/dns_server.c

@@ -30,7 +30,7 @@
 
 #include "wm_wifi_oneshot.h"
 
-#if TLS_CONFIG_AP
+#if 0
 static DNS_SERVER DnsServer;
 
 static INT32S _DnsCompareName(INT8U * MyDns, INT8U * Query)

+ 0 - 3863
src/app/mDNS/mDNSCore/APSCommonServices.h

@@ -1,3863 +0,0 @@
-/*
-	File:    APSCommonServices.h
-	Package: AirPlayAudioPOSIXReceiver
-	Version: AirPlay_Audio_POSIX_Receiver_211.1.p8
-	
-	Disclaimer: IMPORTANT: This Apple software is supplied to you, by Apple Inc. ("Apple"), in your
-	capacity as a current, and in good standing, Licensee in the MFi Licensing Program. Use of this
-	Apple software is governed by and subject to the terms and conditions of your MFi License,
-	including, but not limited to, the restrictions specified in the provision entitled ”Public
-	Software”, and is further subject to your agreement to the following additional terms, and your
-	agreement that the use, installation, modification or redistribution of this Apple software
-	constitutes acceptance of these additional terms. If you do not agree with these additional terms,
-	please do not use, install, modify or redistribute this Apple software.
-	
-	Subject to all of these terms and in?consideration of your agreement to abide by them, Apple grants
-	you, for as long as you are a current and in good-standing MFi Licensee, a personal, non-exclusive
-	license, under Apple's copyrights in this original Apple software (the "Apple Software"), to use,
-	reproduce, and modify the Apple Software in source form, and to use, reproduce, modify, and
-	redistribute the Apple Software, with or without modifications, in binary form. While you may not
-	redistribute the Apple Software in source form, should you redistribute the Apple Software in binary
-	form, you must retain this notice and the following text and disclaimers in all such redistributions
-	of the Apple Software. Neither the name, trademarks, service marks, or logos of Apple Inc. may be
-	used to endorse or promote products derived from the Apple Software without specific prior written
-	permission from Apple. Except as expressly stated in this notice, no other rights or licenses,
-	express or implied, are granted by Apple herein, including but not limited to any patent rights that
-	may be infringed by your derivative works or by other works in which the Apple Software may be
-	incorporated.
-	
-	Unless you explicitly state otherwise, if you provide any ideas, suggestions, recommendations, bug
-	fixes or enhancements to Apple in connection with this software (“Feedback”), you hereby grant to
-	Apple a non-exclusive, fully paid-up, perpetual, irrevocable, worldwide license to make, use,
-	reproduce, incorporate, modify, display, perform, sell, make or have made derivative works of,
-	distribute (directly or indirectly) and sublicense, such Feedback in connection with Apple products
-	and services. Providing this Feedback is voluntary, but if you do provide Feedback to Apple, you
-	acknowledge and agree that Apple may exercise the license granted above without the payment of
-	royalties or further consideration to Participant.
-	
-	The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR
-	IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY
-	AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR
-	IN COMBINATION WITH YOUR PRODUCTS.
-	
-	IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES
-	(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-	PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION
-	AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
-	(INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
-	POSSIBILITY OF SUCH DAMAGE.
-	
-	Copyright (C) 2002-2014 Apple Inc. All Rights Reserved.
-*/
-
-#ifndef	__APSCommonServices_h__
-#define	__APSCommonServices_h__
-// CommonServices_PLATFORM_HEADER can be defined to include a platform-specific file before any other files are included.
-#include "wm_type_def.h"
-#include "lwip/arch.h"
-#include "wm_sockets.h"
-#if( defined( CommonServices_PLATFORM_HEADER ) )
-	#include  CommonServices_PLATFORM_HEADER
-#endif
-
-#if 0
-#pragma mark == Compiler ==
-#endif
-
-#define HAVE_IPV6 TLS_CONFIG_IPV6
-#if HAVE_IPV6
-#define mDNSIPv6Support 1
-#endif
-
-#define LOG printf
-//#define LOG(...)
-
-#ifndef ssize_t
-typedef int ssize_t;
-#endif
-#define usleep(a)		tls_os_time_delay(a/10000)
-
-//===========================================================================================================================
-//	Compiler
-//===========================================================================================================================
-
-#if( __clang__ )
-	#define COMPILER_CLANG		( ( __clang_major__ * 10000 ) + ( __clang_minor__ * 100 ) + __clang_patchlevel__ )
-#endif
-
-#if( __GNUC__ )
-	#define COMPILER_GCC		( ( __GNUC__ * 10000 ) + ( __GNUC_MINOR__ * 100 ) + __GNUC_PATCHLEVEL__ )
-#endif
-
-// STATIC_INLINE - Portable way to marking an inline function for use in a header file.
-
-#if( !defined( STATIC_INLINE ) )
-	#if( defined( __GNUC__ ) && ( __GNUC__ >= 4 ) )
-		#define STATIC_INLINE		static __inline__ __attribute__( ( always_inline ) )
-	#elif( defined( __GNUC__ ) )
-		#define STATIC_INLINE		static __inline__
-	#elif( defined( __MWERKS__ ) || defined( __cplusplus ) )
-		#define STATIC_INLINE		static inline
-	#elif( defined( __WIN32__ ) )
-		#define STATIC_INLINE		static __inline__
-	#else
-		#define STATIC_INLINE		static inline
-	#endif
-#endif
-
-// ATTRIBUTE_NORETURN -- Marks a function as never returning.
-
-#if( !defined( ATTRIBUTE_NORETURN ) )
-	#if( defined( __GNUC__ ) )
-		#define ATTRIBUTE_NORETURN		__attribute__( ( __noreturn__ ) )
-	#else
-		#define ATTRIBUTE_NORETURN
-	#endif
-#endif
-
-// Compatibility for clang's extension macros.
-
-#if( !defined( __has_feature ) )
-	#define __has_feature( x )		0
-#endif
-
-#if( !defined( __has_include ) )
-	#define __has_include( x )		0
-#endif
-
-// CF_RETURNS_RETAINED -- Marks a function as returning a CFRetain'd object.
-
-#if( !defined( CF_RETURNS_RETAINED ) )
-	#if( __has_feature( attribute_cf_returns_retained ) )
-		#define CF_RETURNS_RETAINED		__attribute__( ( cf_returns_retained ) )
-	#else
-		#define CF_RETURNS_RETAINED
-	#endif
-#endif
-
-// CF_RETURNS_NOT_RETAINED -- Marks a function as not returning a CFRetain'd object.
-
-#if( !defined( CF_RETURNS_NOT_RETAINED ) )
-	#if( __has_feature( attribute_cf_returns_not_retained ) )
-		#define CF_RETURNS_NOT_RETAINED		__attribute__( ( cf_returns_not_retained ) )
-	#else
-		#define CF_RETURNS_NOT_RETAINED
-	#endif
-#endif
-
-// STATIC_ANALYZER_NORETURN -- Tells the static analyzer assume a function doesn't return (e.g. assertion handlers).
-
-#if( !defined( STATIC_ANALYZER_NORETURN ) )
-	#if( __clang__ )
-		#define STATIC_ANALYZER_NORETURN		__attribute__( ( analyzer_noreturn ) )
-	#else
-		#define STATIC_ANALYZER_NORETURN
-	#endif
-#endif
-
-#if 0
-#pragma mark == Target ==
-#endif
-
-//===========================================================================================================================
-//	Target
-//===========================================================================================================================
-
-// Windows
-			#define	TARGET_OS_WINDOWS_KERNEL	0
-
-#if 0
-#pragma mark == Target High Level ==
-#endif
-
-//===========================================================================================================================
-//	Target High Level -- TARGET_* flags based on the above TARGET_OS_* flags.
-//===========================================================================================================================
-
-	#define	TARGET_OS_POSIX		1
-
-	#define	TARGET_HAS_STD_C_LIB		1
-
-// TARGET_HAS_C_LIB_IO -- Has C library I/O support (fopen, fprintf, etc.).
-
-#if( !defined( TARGET_HAS_C_LIB_IO ) )
-		#define	TARGET_HAS_C_LIB_IO			1
-#endif
-
-// TARGET_HAS_FLOATING_POINT_SUPPORT -- Has either floating point emulation libraries or hardware floating point.
-
-	#define TARGET_HAS_FLOATING_POINT_SUPPORT		1
-
-	#define	TARGET_LANGUAGE_C_LIKE		1
-
-// which doesn't have BSD sockets support. NetX Duo is only available on ThreadX.
-
-// Note: EFI's compiler says _MSC_VER is 1400, but it doesn't support VS 2005 or later features.
-
-#if 0
-#pragma mark == Includes ==
-#endif
-
-//===========================================================================================================================
-//	Includes
-//===========================================================================================================================
-
-	#include <stddef.h>
-
-// Unknown
-
-// Include sys/param.h on systems that have it to pick up things like the "BSD" preprocessor symbol.
-
-	#define	TARGET_OS_BSD		0
-
-#if 0
-#pragma mark == Post-Include Defines ==
-#endif
-
-//===========================================================================================================================
-//	Defines that rely on the base set of includes
-//===========================================================================================================================
-
-// TARGET_HAS_AUDIO_SESSION: 1=Platform supports CoreAudio's AudioSession APIs (and AVFoundation's AVAudioSession).
-
-#if( !defined( TARGET_HAS_AUDIO_SESSION ) )
-		#define TARGET_HAS_AUDIO_SESSION		0
-#endif
-
-// TARGET_HAS_COMMON_CRYPTO: 1=Use CommonCrypto. 0=Use OpenSSL or some other crypto library.
-
-#if( !defined( TARGET_HAS_COMMON_CRYPTO ) )
-		#define TARGET_HAS_COMMON_CRYPTO		0
-#endif
-
-#if( !defined( TARGET_HAS_COMMON_CRYPTO_DIGEST ) )
-		#define TARGET_HAS_COMMON_CRYPTO_DIGEST		1
-#endif
-
-// TARGET_HAS_MD5_UTILS: 1=Use MD5Utils.c instead of an OS-specific library.
-
-#if( !defined( TARGET_HAS_MD5_UTILS ) )
-#endif
-
-// TARGET_HAS_SHA_UTILS: 1=Use SHAUtils.c instead of an OS-specific library.
-
-#if( !defined( TARGET_HAS_SHA_UTILS ) )
-#endif
-
-#if( TARGET_HAS_COMMON_CRYPTO_DIGEST )
-	#if( !defined( COMMON_DIGEST_FOR_OPENSSL ) )
-		#define MD5_DIGEST_LENGTH				CC_MD5_DIGEST_LENGTH
-		#define MD5_CTX							psDigestContext_t
-		#define MD5_Init						psMd5Init
-		#define MD5_Update( CTX, PTR, LEN ) 	psMd5Update( (CTX), (PTR), (LEN) )
-		#define MD5_Final(PTR, CTX)			psMd5Final( (CTX), (PTR))
-		
-		#define SHA_DIGEST_LENGTH				20
-		#define SHA_CTX							psDigestContext_t
-		#define SHA1_Init						psSha1Init
-		#define SHA1_Update( CTX, PTR, LEN )	psSha1Update( (CTX), (PTR), (LEN) )
-		#define SHA1_Final( DIGEST, CTX )		psSha1Final( (CTX), (DIGEST) )
-		#define SHA1( PTR, LEN, DIGEST )		sha1( (PTR), (LEN), DIGEST )
-		
-		#define SHA256_DIGEST_LENGTH			CC_SHA256_DIGEST_LENGTH
-		#define SHA256_CTX						psDigestContext_t
-		#define SHA256_Init						CC_SHA256_Init
-		#define SHA256_Update( CTX, PTR, LEN )	CC_SHA256_Update( (CTX), (PTR), (LEN) )
-		#define SHA256_Final					CC_SHA256_Final
-		#define SHA256( PTR, LEN, DIGEST )		CC_SHA256( (PTR), (LEN), DIGEST )
-		
-		#define SHA512_DIGEST_LENGTH			CC_SHA512_DIGEST_LENGTH
-		#define SHA512_CTX						psDigestContext_t
-		#define SHA512_Init						psSha512Init
-		#define SHA512_Update( CTX, PTR, LEN )	psSha512Update( (CTX), (PTR), (LEN) )
-		#define SHA512_Final(PTR, CTX)					psSha512Final( (CTX), (PTR))
-		#define SHA512( PTR, LEN, DIGEST )		CC_SHA512( (PTR), (LEN), DIGEST )
-	#endif
-
-	#define SHA512_CTX	 psDigestContext_t
-	#define HEADER_MD5_H	1 // Trick openssl/md5.h into doing nothing.
-	#define HEADER_SHA_H	1 // Trick openssl/sha.h into doing nothing.
-#elif( TARGET_HAS_MOCANA_SSL )
-	#define MD5_DIGEST_LENGTH					MD5_DIGESTSIZE
-	#define MD5_CTX								MD5_CTX
-	#define MD5_Init							MD5init_HandShake
-	#define MD5_Update( CTX, PTR, LEN ) 		MD5update_HandShake( (CTX), (const ubyte *)(PTR), (LEN) )
-	#define MD5_Final( DIGEST, CTX )			MD5final_HandShake( (CTX), (ubyte *)(DIGEST) )
-	
-	#define SHA_DIGEST_LENGTH					20
-	#define SHA_CTX								SHA1_CTX
-	#define SHA1_Init							SHA1_initDigestHandShake
-	#define SHA1_Update( CTX, PTR, LEN )		SHA1_updateDigestHandShake( (CTX), (const ubyte *)(PTR), (LEN) )
-	#define SHA1_Final( DIGEST, CTX )			SHA1_finalDigestHandShake( (CTX), (DIGEST) )
-	#define SHA1( PTR, LEN, DIGEST )			SHA1_completeDigest( (ubyte *)(PTR), (LEN), (DIGEST) )
-	
-	#define SHA512_DIGEST_LENGTH				64
-	#define SHA512_CTX							SHA512_CTX_compat
-	#define SHA512_Init( CTX )					SHA512_Init_compat( (CTX) )
-	#define SHA512_Update( CTX, PTR, LEN )		SHA512_Update_compat( (CTX), (PTR), (LEN) )
-	#define SHA512_Final( DIGEST, CTX )			SHA512_Final_compat( (DIGEST), (CTX) )
-	#define SHA512( PTR, LEN, DIGEST )			SHA512_compat( (PTR), (LEN), DIGEST )
-#elif( TARGET_HAS_USSL )
-	#define MD5_DIGEST_LENGTH					16
-	#define MD5_CTX								md5_context
-	#define MD5_Init							md5_starts
-	#define MD5_Update( CTX, PTR, LEN ) 		md5_update( (CTX), (unsigned char *)(PTR), (int)(LEN) )
-	#define MD5_Final( DIGEST, CTX )			md5_finish( (CTX), (DIGEST) )
-	
-	#define SHA_DIGEST_LENGTH					20
-	#define SHA_CTX								sha1_context
-	#define SHA1_Init							sha1_starts
-	#define SHA1_Update( CTX, PTR, LEN )		sha1_update( (CTX), (unsigned char *)(PTR), (int)(LEN) )
-	#define SHA1_Final( DIGEST, CTX )			sha1_finish( (CTX), (DIGEST) )
-	#define SHA1( PTR, LEN, DIGEST )			sha1( (unsigned char *)(PTR), (int)(LEN), (DIGEST) )
-	
-	#define SHA256_DIGEST_LENGTH				32
-	#define SHA256_CTX							sha2_context
-	#define SHA256_Init( CTX )					sha2_starts( (CTX), 0 )
-	#define SHA256_Update( CTX, PTR, LEN )		sha2_update( (CTX), (unsigned char *)(PTR), (int)(LEN) )
-	#define SHA256_Final( DIGEST, CTX )			sha2_finish( (CTX), (DIGEST) )
-	#define SHA256( PTR, LEN, DIGEST )			sha2( (unsigned char *)(PTR), (int)(LEN), (DIGEST), 0 )
-#elif( TARGET_HAS_SHA_UTILS )
-	#define SHA_DIGEST_LENGTH					20
-	#define SHA_CTX								SHA_CTX_compat
-	#define SHA1_Init( CTX )					SHA1_Init_compat( (CTX) )
-	#define SHA1_Update( CTX, PTR, LEN )		SHA1_Update_compat( (CTX), (PTR), (LEN) )
-	#define SHA1_Final( DIGEST, CTX )			SHA1_Final_compat( (DIGEST), (CTX) )
-	#define SHA1( PTR, LEN, DIGEST )			SHA1_compat( (PTR), (LEN), DIGEST )
-	
-	#define SHA512_DIGEST_LENGTH				64
-	#define SHA512_CTX							SHA512_CTX_compat
-	#define SHA512_Init( CTX )					SHA512_Init_compat( (CTX) )
-	#define SHA512_Update( CTX, PTR, LEN )		SHA512_Update_compat( (CTX), (PTR), (LEN) )
-	#define SHA512_Final( DIGEST, CTX )			SHA512_Final_compat( (DIGEST), (CTX) )
-	#define SHA512( PTR, LEN, DIGEST )			SHA512_compat( (PTR), (LEN), DIGEST )
-	
-	#define SHA3_DIGEST_LENGTH					64
-	#define SHA3_CTX							SHA3_CTX_compat
-	#define SHA3_Init( CTX )					SHA3_Init_compat( (CTX) )
-	#define SHA3_Update( CTX, PTR, LEN )		SHA3_Update_compat( (CTX), (PTR), (LEN) )
-	#define SHA3_Final( DIGEST, CTX )			SHA3_Final_compat( (DIGEST), (CTX) )
-	#define SHA3( PTR, LEN, DIGEST )			SHA3_compat( (PTR), (LEN), DIGEST )
-#endif
-
-#if 0
-#pragma mark == CPU ==
-#endif
-
-//===========================================================================================================================
-//	CPU
-//===========================================================================================================================
-
-#if( !defined( TARGET_CPU_ARM ) )
-// ARM
-	#if( defined( __arm__ ) || defined( __arm ) || defined( __ARM ) || defined( __THUMB ) )
-		#define	TARGET_CPU_ARM				1
-	#else
-		#define	TARGET_CPU_ARM				0
-	#endif
-#endif
-
-#if( !defined( TARGET_CPU_ARM64 ) )
-	#if( defined( __arm64__ ) || defined( __arm64 ) )
-		#define	TARGET_CPU_ARM64			1
-	#else
-		#define	TARGET_CPU_ARM64			0
-	#endif
-#endif
-
-#if( !defined( TARGET_CPU_MIPS ) )
-// MIPS
-	#if( defined( __mips__ ) || __MIPS__ || defined( MIPS32 ) || defined( __MIPSEB__ ) || defined( __MIPSEL__ ) )
-		#define	TARGET_CPU_MIPS				1
-	#elif( defined( R3000 ) || defined( R4000 ) || defined( R4650 ) || defined( _M_MRX000 ) )
-		#define	TARGET_CPU_MIPS				1
-	#else
-		#define	TARGET_CPU_MIPS				0
-	#endif
-#endif
-
-#if( !defined( TARGET_CPU_PPC ) )
-// PowerPC
-	#if( defined( __ppc__ ) || defined( __POWERPC__ ) || defined( __PPC__ ) || defined( powerpc ) || defined( ppc ) || defined( _M_MPPC ) )
-		#define	TARGET_CPU_PPC				1
-	#else
-		#define	TARGET_CPU_PPC				0
-	#endif
-#endif
-#if( !defined( TARGET_CPU_PPC64 ) )
-	#if( defined( __ppc64__ ) )
-		#define	TARGET_CPU_PPC64			1
-	#else
-		#define	TARGET_CPU_PPC64			0
-	#endif
-#endif
-
-#if( !defined( TARGET_CPU_X86 ) )
-// x86
-	#if( defined( __i386__ ) || __INTEL__ || defined( i386 ) || defined( intel ) || defined( _M_IX86 ) )
-		#define	TARGET_CPU_X86				1
-	#else
-		#define	TARGET_CPU_X86				0
-	#endif
-#endif
-#if( !defined( TARGET_CPU_X86_64 ) )
-	#if( defined( __x86_64__ ) || defined( _M_X64 ) || defined( _M_AMD64 ) || defined( _M_IA64 ) )
-		#define	TARGET_CPU_X86_64			1
-	#else
-		#define	TARGET_CPU_X86_64			0
-	#endif
-#endif
-
-// TARGET_NEEDS_NATURAL_ALIGNMENT - CPU requires naturally aligned accesses or an exception occurs.
-
-#if( TARGET_CPU_PPC || TARGET_CPU_PPC64 || TARGET_CPU_X86 || TARGET_CPU_X86_64 )
-	#define	TARGET_NEEDS_NATURAL_ALIGNMENT		0
-#else
-	#define	TARGET_NEEDS_NATURAL_ALIGNMENT		1
-#endif
-
-// 32-bit and 64-bit support to avoid relying on platform-specific conditionals in code outside of this file.
-// See also <http://msdn.microsoft.com/msdnmag/issues/06/05/x64/default.aspx> for Windows 64 bit stuff.
-
-#if( !defined( TARGET_RT_64_BIT ) )
-	#if( __LP64__ || defined( _WIN64 ) || defined( EFI64 ) || defined( EFIX64 ) || TARGET_CPU_X86_64 || TARGET_CPU_PPC64 )
-		#define	TARGET_RT_64_BIT		1
-	#else
-		#define	TARGET_RT_64_BIT		0
-	#endif
-#endif
-
-#if( !defined( TARGET_RT_32_BIT ) )
-	#if( TARGET_RT_64_BIT )
-		#define	TARGET_RT_32_BIT		0
-	#else
-		#define	TARGET_RT_32_BIT		1
-	#endif
-#endif
-
-#if 0
-#pragma mark == Byte Order ==
-#endif
-
-//===========================================================================================================================
-//	Byte Order
-//===========================================================================================================================
-#define TARGET_RT_LITTLE_ENDIAN  1
-#if( !defined( TARGET_RT_LITTLE_ENDIAN ) && !defined( TARGET_RT_BIG_ENDIAN ) )
-	#error byte order not specified. Update platform include makefile appropriately 
-#endif
-
-#if( !defined( TARGET_RT_BIG_ENDIAN ) && defined( TARGET_RT_LITTLE_ENDIAN ) && TARGET_RT_LITTLE_ENDIAN )
-	#define TARGET_RT_BIG_ENDIAN		0
-#endif
-#if( !defined( TARGET_RT_LITTLE_ENDIAN ) && defined( TARGET_RT_BIG_ENDIAN ) && TARGET_RT_BIG_ENDIAN )
-	#define TARGET_RT_LITTLE_ENDIAN		0
-#endif
-
-// TARGET_RT_BYTE_ORDER
-
-#if( !defined( TARGET_RT_BYTE_ORDER_BIG_ENDIAN ) )
-	#define	TARGET_RT_BYTE_ORDER_BIG_ENDIAN			1234
-#endif
-
-#if( !defined( TARGET_RT_BYTE_ORDER_LITTLE_ENDIAN ) )
-	#define	TARGET_RT_BYTE_ORDER_LITTLE_ENDIAN		4321
-#endif
-
-#if( !defined( TARGET_RT_BYTE_ORDER ) )
-	#if( TARGET_RT_LITTLE_ENDIAN )
-		#define	TARGET_RT_BYTE_ORDER				TARGET_RT_BYTE_ORDER_LITTLE_ENDIAN
-	#else
-		#define	TARGET_RT_BYTE_ORDER				TARGET_RT_BYTE_ORDER_BIG_ENDIAN
-	#endif
-#endif
-
-//===========================================================================================================================
-//	Alignment safe read/write/swap macros
-//===========================================================================================================================
-
-// Big endian reading
-
-#define	ReadBig16( PTR ) \
-	( (uint16_t)( \
-		( ( (uint16_t)( (uint8_t *)(PTR) )[ 0 ] ) << 8 ) | \
-		  ( (uint16_t)( (uint8_t *)(PTR) )[ 1 ] ) ) )
-
-#define	ReadBig32( PTR ) \
-	( (uint32_t)( \
-		( ( (uint32_t)( (uint8_t *)(PTR) )[ 0 ] ) << 24 ) | \
-		( ( (uint32_t)( (uint8_t *)(PTR) )[ 1 ] ) << 16 ) | \
-		( ( (uint32_t)( (uint8_t *)(PTR) )[ 2 ] ) <<  8 ) | \
-		  ( (uint32_t)( (uint8_t *)(PTR) )[ 3 ] ) ) )
-
-#define	ReadBig48( PTR ) \
-	( (uint64_t)( \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 0 ] ) << 40 ) | \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 1 ] ) << 32 ) | \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 2 ] ) << 24 ) | \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 3 ] ) << 16 ) | \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 4 ] ) <<  8 ) | \
-		  ( (uint64_t)( (uint8_t *)(PTR) )[ 5 ] ) ) )
-
-#define	ReadBig64( PTR ) \
-	( (uint64_t)( \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 0 ] ) << 56 ) | \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 1 ] ) << 48 ) | \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 2 ] ) << 40 ) | \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 3 ] ) << 32 ) | \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 4 ] ) << 24 ) | \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 5 ] ) << 16 ) | \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 6 ] ) <<  8 ) | \
-		  ( (uint64_t)( (uint8_t *)(PTR) )[ 7 ] ) ) )
-
-// Big endian wWriting
-
-#define	WriteBig16( PTR, X ) \
-	do \
-	{ \
-		( (uint8_t *)(PTR) )[ 0 ] = (uint8_t)( ( (X) >>  8 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 1 ] = (uint8_t)(   (X)         & 0xFF ); \
-	\
-	}	while( 0 )
-
-#define	WriteBig32( PTR, X ) \
-	do \
-	{ \
-		( (uint8_t *)(PTR) )[ 0 ] = (uint8_t)( ( (X) >> 24 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 1 ] = (uint8_t)( ( (X) >> 16 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 2 ] = (uint8_t)( ( (X) >>  8 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 3 ] = (uint8_t)(   (X)         & 0xFF ); \
-	\
-	}	while( 0 )
-
-#define	WriteBig48( PTR, X ) \
-	do \
-	{ \
-		( (uint8_t *)(PTR) )[ 0 ] = (uint8_t)( ( (X) >> 40 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 1 ] = (uint8_t)( ( (X) >> 32 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 2 ] = (uint8_t)( ( (X) >> 24 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 3 ] = (uint8_t)( ( (X) >> 16 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 4 ] = (uint8_t)( ( (X) >>  8 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 5 ] = (uint8_t)(   (X)         & 0xFF ); \
-	\
-	}	while( 0 )
-
-#define	WriteBig64( PTR, X ) \
-	do \
-	{ \
-		( (uint8_t *)(PTR) )[ 0 ] = (uint8_t)( ( (X) >> 56 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 1 ] = (uint8_t)( ( (X) >> 48 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 2 ] = (uint8_t)( ( (X) >> 40 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 3 ] = (uint8_t)( ( (X) >> 32 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 4 ] = (uint8_t)( ( (X) >> 24 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 5 ] = (uint8_t)( ( (X) >> 16 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 6 ] = (uint8_t)( ( (X) >>  8 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 7 ] = (uint8_t)(   (X)         & 0xFF ); \
-	\
-	}	while( 0 )
-
-// Little endian reading
-
-#define	ReadLittle16( PTR ) \
-	( (uint16_t)( \
-		  ( (uint16_t)( (uint8_t *)(PTR) )[ 0 ] ) | \
-		( ( (uint16_t)( (uint8_t *)(PTR) )[ 1 ] ) <<  8 ) ) )
-
-#define	ReadLittle32( PTR ) \
-	( (uint32_t)( \
-		  ( (uint32_t)( (uint8_t *)(PTR) )[ 0 ] ) | \
-		( ( (uint32_t)( (uint8_t *)(PTR) )[ 1 ] ) <<  8 ) | \
-		( ( (uint32_t)( (uint8_t *)(PTR) )[ 2 ] ) << 16 ) | \
-		( ( (uint32_t)( (uint8_t *)(PTR) )[ 3 ] ) << 24 ) ) )
-
-#define	ReadLittle48( PTR ) \
-	( (uint64_t)( \
-		  ( (uint64_t)( (uint8_t *)(PTR) )[ 0 ] )			| \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 1 ] ) <<  8 )	| \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 2 ] ) << 16 )	| \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 3 ] ) << 24 )	| \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 4 ] ) << 32 )	| \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 5 ] ) << 40 ) ) )
-
-#define	ReadLittle64( PTR ) \
-	( (uint64_t)( \
-		  ( (uint64_t)( (uint8_t *)(PTR) )[ 0 ] )			| \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 1 ] ) <<  8 )	| \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 2 ] ) << 16 )	| \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 3 ] ) << 24 )	| \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 4 ] ) << 32 )	| \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 5 ] ) << 40 )	| \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 6 ] ) << 48 )	| \
-		( ( (uint64_t)( (uint8_t *)(PTR) )[ 7 ] ) << 56 ) ) )
-
-// Little endian writing
-
-#define	WriteLittle16( PTR, X ) \
-	do \
-	{ \
-		( (uint8_t *)(PTR) )[ 0 ] = (uint8_t)(   (X)         & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 1 ] = (uint8_t)( ( (X) >>  8 ) & 0xFF ); \
-	\
-	}	while( 0 )
-
-#define	WriteLittle32( PTR, X ) \
-	do \
-	{ \
-		( (uint8_t *)(PTR) )[ 0 ] = (uint8_t)(   (X)         & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 1 ] = (uint8_t)( ( (X) >>  8 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 2 ] = (uint8_t)( ( (X) >> 16 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 3 ] = (uint8_t)( ( (X) >> 24 ) & 0xFF ); \
-	\
-	}	while( 0 )
-
-#define	WriteLittle48( PTR, X ) \
-	do \
-	{ \
-		( (uint8_t *)(PTR) )[ 0 ] = (uint8_t)(   (X)         & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 1 ] = (uint8_t)( ( (X) >>  8 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 2 ] = (uint8_t)( ( (X) >> 16 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 3 ] = (uint8_t)( ( (X) >> 24 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 4 ] = (uint8_t)( ( (X) >> 32 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 5 ] = (uint8_t)( ( (X) >> 40 ) & 0xFF ); \
-	\
-	}	while( 0 )
-
-#define	WriteLittle64( PTR, X ) \
-	do \
-	{ \
-		( (uint8_t *)(PTR) )[ 0 ] = (uint8_t)(   (X)         & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 1 ] = (uint8_t)( ( (X) >>  8 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 2 ] = (uint8_t)( ( (X) >> 16 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 3 ] = (uint8_t)( ( (X) >> 24 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 4 ] = (uint8_t)( ( (X) >> 32 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 5 ] = (uint8_t)( ( (X) >> 40 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 6 ] = (uint8_t)( ( (X) >> 48 ) & 0xFF ); \
-		( (uint8_t *)(PTR) )[ 7 ] = (uint8_t)( ( (X) >> 56 ) & 0xFF ); \
-	\
-	}	while( 0 )
-
-// Host order read/write
-
-#define Read8( PTR )					( ( (const uint8_t *)(PTR) )[ 0 ] )
-#define Write8( PTR, X )				( ( (uint8_t *)(PTR) )[ 0 ] = (X) )
-
-#if( TARGET_RT_BIG_ENDIAN )
-	#define ReadHost16( PTR )			ReadBig16( (PTR) )
-	#define ReadHost32( PTR )			ReadBig32( (PTR) )
-	#define ReadHost48( PTR )			ReadBig48( (PTR) )
-	#define ReadHost64( PTR )			ReadBig64( (PTR) )
-	
-	#define WriteHost16( PTR, X )		WriteBig16( (PTR), (X) )
-	#define WriteHost32( PTR, X )		WriteBig32( (PTR), (X) )
-	#define WriteHost48( PTR, X )		WriteBig48( (PTR), (X) )
-	#define WriteHost64( PTR, X )		WriteBig64( (PTR), (X) )
-#else
-	#define ReadHost16( PTR )			ReadLittle16( (PTR) )
-	#define ReadHost32( PTR )			ReadLittle32( (PTR) )
-	#define ReadHost48( PTR )			ReadLittle48( (PTR) )
-	#define ReadHost64( PTR )			ReadLittle64( (PTR) )
-	
-	#define WriteHost16( PTR, X )		WriteLittle16( (PTR), (X) )
-	#define WriteHost32( PTR, X )		WriteLittle32( (PTR), (X) )
-	#define WriteHost48( PTR, X )		WriteLittle48( (PTR), (X) )
-	#define WriteHost64( PTR, X )		WriteLittle64( (PTR), (X) )
-#endif
-
-// Unconditional swap read/write.
-
-#if( TARGET_RT_BIG_ENDIAN )
-	#define ReadSwap16( PTR )			ReadLittle16( (PTR) )
-	#define ReadSwap32( PTR )			ReadLittle32( (PTR) )
-	#define ReadSwap48( PTR )			ReadLittle48( (PTR) )
-	#define ReadSwap64( PTR )			ReadLittle64( (PTR) )
-	
-	#define WriteSwap16( PTR, X )		WriteLittle16( (PTR), (X) )
-	#define WriteSwap32( PTR, X )		WriteLittle32( (PTR), (X) )
-	#define WriteSwap48( PTR, X )		WriteLittle48( (PTR), (X) )
-	#define WriteSwap64( PTR, X )		WriteLittle64( (PTR), (X) )
-#else
-	#define ReadSwap16( PTR )			ReadBig16( (PTR) )
-	#define ReadSwap32( PTR )			ReadBig32( (PTR) )
-	#define ReadSwap48( PTR )			ReadBig48( (PTR) )
-	#define ReadSwap64( PTR )			ReadBig64( (PTR) )
-	
-	#define WriteSwap16( PTR, X )		WriteBig16( (PTR), (X) )
-	#define WriteSwap32( PTR, X )		WriteBig32( (PTR), (X) )
-	#define WriteSwap48( PTR, X )		WriteBig48( (PTR), (X) )
-	#define WriteSwap64( PTR, X )		WriteBig64( (PTR), (X) )
-#endif
-
-// Memory swaps
-
-#if( TARGET_RT_BIG_ENDIAN )
-	#define HostToBig16Mem( SRC, LEN, DST )			do {} while( 0 )
-	#define BigToHost16Mem( SRC, LEN, DST )			do {} while( 0 )
-	
-	#define LittleToHost16Mem( SRC, LEN, DST )		Swap16Mem( (SRC), (LEN), (DST) )
-	#define LittleToHost16Mem( SRC, LEN, DST )		Swap16Mem( (SRC), (LEN), (DST) )
-#else
-	#define HostToBig16Mem( SRC, LEN, DST )			Swap16Mem( (SRC), (LEN), (DST) )
-	#define BigToHost16Mem( SRC, LEN, DST )			Swap16Mem( (SRC), (LEN), (DST) )
-	
-	#define HostToLittle16Mem( SRC, LEN, DST )		do {} while( 0 )
-	#define LittleToHost16Mem( SRC, LEN, DST )		do {} while( 0 )
-#endif
-
-// Unconditional endian swaps
-
-#define	Swap16( X ) \
-	( (uint16_t)( \
-		( ( ( (uint16_t)(X) ) << 8 ) & UINT16_C( 0xFF00 ) ) | \
-		( ( ( (uint16_t)(X) ) >> 8 ) & UINT16_C( 0x00FF ) ) ) )
-
-#define	Swap32( X ) \
-	( (uint32_t)( \
-		( ( ( (uint32_t)(X) ) << 24 ) & UINT32_C( 0xFF000000 ) ) | \
-		( ( ( (uint32_t)(X) ) <<  8 ) & UINT32_C( 0x00FF0000 ) ) | \
-		( ( ( (uint32_t)(X) ) >>  8 ) & UINT32_C( 0x0000FF00 ) ) | \
-		( ( ( (uint32_t)(X) ) >> 24 ) & UINT32_C( 0x000000FF ) ) ) )
-
-#define Swap64( X ) \
-	( (uint64_t)( \
-		( ( ( (uint64_t)(X) ) << 56 ) & UINT64_C( 0xFF00000000000000 ) ) | \
-		( ( ( (uint64_t)(X) ) << 40 ) & UINT64_C( 0x00FF000000000000 ) ) | \
-		( ( ( (uint64_t)(X) ) << 24 ) & UINT64_C( 0x0000FF0000000000 ) ) | \
-		( ( ( (uint64_t)(X) ) <<  8 ) & UINT64_C( 0x000000FF00000000 ) ) | \
-		( ( ( (uint64_t)(X) ) >>  8 ) & UINT64_C( 0x00000000FF000000 ) ) | \
-		( ( ( (uint64_t)(X) ) >> 24 ) & UINT64_C( 0x0000000000FF0000 ) ) | \
-		( ( ( (uint64_t)(X) ) >> 40 ) & UINT64_C( 0x000000000000FF00 ) ) | \
-		( ( ( (uint64_t)(X) ) >> 56 ) & UINT64_C( 0x00000000000000FF ) ) ) )
-
-// Host<->Network/Big endian swaps
-
-#if( TARGET_RT_BIG_ENDIAN )
-	#define hton16( X )		(X)
-	#define ntoh16( X )		(X)
-	
-	#define hton32( X )		(X)
-	#define ntoh32( X )		(X)
-	
-	#define hton64( X )		(X)
-	#define ntoh64( X )		(X)
-#else
-	#define hton16( X )		Swap16( X )
-	#define ntoh16( X )		Swap16( X )
-	
-	#define hton32( X )		Swap32( X )
-	#define ntoh32( X )		Swap32( X )
-	
-	#define hton64( X )		Swap64( X )
-	#define ntoh64( X )		Swap64( X )
-#endif
-
-#if 0
-#pragma mark == Compile Time Asserts ==
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	check_compile_time
-	@abstract	Performs a compile-time check of something such as the size of an int.
-	@discussion
-	
-	This declares an array with a size that is determined by a compile-time expression. If the expression evaluates 
-	to 0, the array has a size of -1, which is illegal and generates a compile-time error.
-	
-	For example:
-	
-	check_compile_time( sizeof( int ) == 4 );
-	
-	Note: This only works with compile-time expressions.
-	Note: This only works in places where extern declarations are allowed (e.g. global scope).
-	
-	References:
-	
-	<http://www.jaggersoft.com/pubs/CVu11_3.html>
-	<http://www.jaggersoft.com/pubs/CVu11_5.html>
-	
-	Note: The following macros differ from the macros on the www.jaggersoft.com web site because those versions do not
-	work with GCC due to GCC allowing a zero-length array. Using a -1 condition turned out to be more portable.
-*/
-#undef check_compile_time
-#if( !defined( check_compile_time ) )
-	#if( defined( __cplusplus ) )
-		#define	check_compile_time( X )		extern "C" int compile_time_assert_failed[ (X) ? 1 : -1 ]
-	#else
-		#define	check_compile_time( X )		extern int compile_time_assert_failed[ (X) ? 1 : -1 ]
-	#endif
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	check_compile_time_code
-	@abstract	Perform a compile-time check, suitable for placement in code, of something such as the size of an int.
-	@discussion
-	
-	This creates a switch statement with an existing case for 0 and an additional case using the result of a 
-	compile-time expression. A switch statement cannot have two case labels with the same constant so if the
-	compile-time expression evaluates to 0, it is illegal and generates a compile-time error. If the compile-time
-	expression does not evaluate to 0, the resulting value is used as the case label and it compiles without error.
-
-	For example:
-	
-	check_compile_time_code( sizeof( int ) == 4 );
-	
-	Note: This only works with compile-time expressions.
-	Note: This does not work in a global scope so it must be inside a function.
-	
-	References:
-	
-	<http://www.jaggersoft.com/pubs/CVu11_3.html>
-	<http://www.jaggersoft.com/pubs/CVu11_5.html>
-*/
-#undef check_compile_time_code
-#if( !defined( check_compile_time_code ) )
-		#define	check_compile_time_code( X )	switch( 0 ) { case 0: case X:; }
-#endif
-
-#if 0
-#pragma mark == Constants ==
-#endif
-
-//===========================================================================================================================
-//	Constants
-//===========================================================================================================================
-
-// Note: "CR" cannot be defined because Darwin, EFI, and others define it for another purpose.
-
-#define LF			'\n'
-#define	CRSTR		"\r"
-#define	LFSTR		"\n"
-#define CRLF		"\r\n"
-//#define CRCR 		"\r\r"
-
-#if 0
-#pragma mark == Types ==
-#endif
-
-//===========================================================================================================================
-//	Standard Types
-//===========================================================================================================================
-
-// Primitive types
-
-#if( !defined( INT8_MIN ) && !defined( _INT8_T_DECLARED ) && !defined( __MWERKS__ ) && !defined( __intptr_t_defined ) )
-#include <stdint.h>
-	//#define INT8_MIN					SCHAR_MIN
-//#ifdef int8_t
-//#undef int8_t
-//#endif
-//typedef char int8_t;
-#ifdef int16_t
-#undef int16_t
-#endif
-typedef short int16_t;
-	
-	//typedef int8_t						int_least8_t;
-	typedef int16_t						int_least16_t;
-	//typedef int32_t						int_least32_t;
-	typedef int64_t						int_least64_t;
-
-	typedef uint8_t						uint_least8_t;
-	typedef uint16_t					uint_least16_t;
-	typedef uint32_t					uint_least32_t;
-	typedef uint64_t					uint_least64_t;
-	
-		//typedef int8_t					int_fast8_t;
-		//typedef int16_t					int_fast16_t;
-		//typedef int32_t					int_fast32_t;
-		typedef int64_t					int_fast64_t;
-		
-		//typedef uint8_t					uint_fast8_t;
-		//typedef uint16_t				uint_fast16_t;
-		//typedef uint32_t				uint_fast32_t;
-		typedef uint64_t				uint_fast64_t;
-#if 0	
-		#if( !defined( intptr_t ) )
-			typedef long				intptr_t;
-		#endif
-		#if( !defined( uintptr_t ) )
-			typedef unsigned long		uintptr_t;
-		#endif
-#endif
-#endif
-
-// int128 support
-
-typedef struct
-{
-	int64_t		hi;
-	uint64_t	lo;
-	
-}	int128_compat;
-
-typedef struct
-{
-	uint64_t	hi;
-	uint64_t	lo;
-
-}	uint128_compat;
-
-#if( TARGET_RT_64_BIT && ( COMPILER_CLANG >= 30100 ) )
-	#define TARGET_HAS_NATIVE_INT128		1
-	typedef __int128						int128_t;
-	typedef unsigned __int128				uint128_t;
-#elif( TARGET_RT_64_BIT && __GNUC__ )
-	#if( __SIZEOF_INT128__ )
-		#define TARGET_HAS_NATIVE_INT128	1
-		typedef __int128					int128_t;
-		typedef unsigned __int128			uint128_t;
-	#elif( COMPILER_GCC >= 40400 )
-		#define TARGET_HAS_NATIVE_INT128	1
-		typedef signed						int128_t  __attribute__( ( mode( TI ) ) );
-		typedef unsigned					uint128_t __attribute__( ( mode( TI ) ) );
-	#endif
-#endif
-
-// Limits
-
-#if( !defined( SCHAR_MIN ) )
-	#define SCHAR_MIN		( -128 )
-#endif
-
-#if( !defined( UCHAR_MAX ) )
-	#define UCHAR_MAX		255
-#endif
-
-#if( !defined( SHRT_MIN ) )
-	#define SHRT_MIN		( -32768 )
-#endif
-
-#if( !defined( USHRT_MAX ) )
-	#define USHRT_MAX		65535
-#endif
-
-#if( !defined( UINT_MAX ) )
-	#define UINT_MAX		0xFFFFFFFFU
-#endif
-
-#if( !defined( INT8_MAX ) )
-	#define INT8_MAX		127
-#endif
-#if( !defined( INT16_MAX ) )
-	#define INT16_MAX		32767
-#endif
-#if( !defined( INT32_MAX ) )
-	#define INT32_MAX		2147483647
-#endif
-#if( !defined( INT64_MAX ) )
-	#define INT64_MAX		 INT64_C( 9223372036854775807 )
-#endif
-
-#if( !defined( INT8_MIN ) )
-	#define INT8_MIN		( -128 )
-#endif
-#if( !defined( INT16_MIN ) )
-	#define INT16_MIN		( -32768 )
-#endif
-#if( !defined( INT32_MIN ) )
-	#define INT32_MIN		( -INT32_MAX - 1 )
-#endif
-#if( !defined( INT64_MIN ) )
-	#define INT64_MIN        (-INT64_MAX - 1 )
-#endif
-
-#if( !defined( UINT8_MAX ) )
-	#define UINT8_MAX		255
-#endif
-#if( !defined( UINT16_MAX ) )
-	#define UINT16_MAX		65535
-#endif
-#if( !defined( UINT32_MAX ) )
-	#define UINT32_MAX		UINT32_C( 4294967295 )
-#endif
-#if( !defined( UINT64_MAX ) )
-	#define UINT64_MAX		UINT64_C( 18446744073709551615 )
-#endif
-
-#if( !defined( __MACTYPES__ ) && !defined( __MACTYPES_H__ ) && !defined( __COREFOUNDATION_CFBASE__ ) )
-	typedef float		Float32; // 32 bit IEEE float: 1 sign bit, 8 exponent bits, 23 fraction bits.
-	typedef double		Float64; // 64 bit IEEE float: 1 sign bit, 11 exponent bits, 52 fraction bits.
-	
-	check_compile_time( sizeof( Float32 ) == 4 );
-	check_compile_time( sizeof( Float64 ) == 8 );
-#endif
-
-// Old MacTypes for emulating with Mac-ish APIs (unfortunately, UInt32 isn't exactly uint32_t so we have to provide this).
-
-#if( !defined( __MACTYPES__ ) && !defined( _OS_OSTYPES_H ) )
-	#if( __LP64__ )
-		typedef unsigned int		UInt32;
-		typedef signed int			SInt32;
-	#else
-		typedef unsigned long		UInt32;
-		typedef signed long			SInt32;
-	#endif
-#endif
-
-// Macros for minimum-width integer constants
-
-#if( !defined( INT8_C ) )
-	#define INT8_C( value )			value
-#endif
-
-#if( !defined( INT16_C ) )
-	#define INT16_C( value )		value
-#endif
-
-#if( !defined( INT32_C ) )
-	#define INT32_C( value )		value
-#endif
-
-#define INT64_C_safe( value )		INT64_C( value )
-#if( !defined( INT64_C ) )
-		#define INT64_C( value )	value ## LL
-#endif
-
-#define UINT8_C_safe( value )		UINT8_C( value )
-#if( !defined( UINT8_C ) )
-	#define UINT8_C( value )		value ## U
-#endif
-
-#define UINT16_C_safe( value )		UINT16_C( value )
-#if( !defined( UINT16_C ) )
-	#define UINT16_C( value )		value ## U
-#endif
-
-#define UINT32_C_safe( value )		UINT32_C( value )
-#if( !defined( UINT32_C ) )
-	#define UINT32_C( value )		value ## U
-#endif
-
-#define UINT64_C_safe( value )		UINT64_C( value )
-#if( !defined( UINT64_C ) )
-		#define UINT64_C( value )	value ## ULL
-#endif
-
-#if( !defined( INT_MIN ) )
-	#define INT_MIN		( -2147483647 - 1 )
-#endif
-
-#if( !defined( INT_MAX ) )
-	#define INT_MAX		2147483647
-#endif
-
-#if( !defined( SIZE_MAX ) )
-	#define SIZE_MAX	2147483647
-#endif
-
-// Value16 -- 16-bit union of a bunch of types.
-
-typedef union
-{
-	char		c[ 2 ];
-	uint8_t		u8[ 2 ];
-	int8_t		s8[ 2 ];
-	uint16_t	u16;
-	int16_t		s16;
-	
-}	Value16;
-
-check_compile_time( sizeof( Value16 ) == 2 );
-
-// Value32 -- 32-bit union of a bunch of types.
-
-typedef union
-{
-	char		c[ 4 ];
-	uint8_t		u8[ 4 ];
-	int8_t		s8[ 4 ];
-	uint16_t	u16[ 2 ];
-	int16_t		s16[ 2 ];
-	uint32_t	u32;
-	int32_t		s32;
-	Float32		f32;
-	
-}	Value32;
-
-check_compile_time( sizeof( Value32 ) == 4 );
-
-// Value64 -- 64-bit union of a bunch of types.
-
-typedef union
-{
-	char		c[ 8 ];
-	uint8_t		u8[ 8 ];
-	int8_t		s8[ 8 ];
-	uint16_t	u16[ 4 ];
-	int16_t		s16[ 4 ];
-	uint32_t	u32[ 2 ];
-	int32_t		s32[ 2 ];
-	uint64_t	u64;
-	int64_t		s64;
-	Float32		f32[ 2 ];
-	Float64		f64;
-	
-}	Value64;
-
-check_compile_time( sizeof( Value64 ) == 8 );
-
-// timespec
-
-// timeval
-
-#if 0
-#pragma mark == Compatibility ==
-#endif
-
-//===========================================================================================================================
-//	Compatibility
-//===========================================================================================================================
-
-#if( !defined( __BEGIN_DECLS ) )
-	#if( defined( __cplusplus ) )
-		#define __BEGIN_DECLS	extern "C" {
-		#define __END_DECLS		}
-	#else
-		#define __BEGIN_DECLS
-		#define __END_DECLS
-	#endif
-#endif
-
-// Macros to allow the same code to work on Windows and other sockets API-compatible platforms.
-
-		typedef int		SocketRef;
-	
-		#define	IsValidSocket( X )					( (X) >= 0 )
-		#define	kInvalidSocketRef					-1
-		#define	close_compat( X )					close( X )
-		#define	read_compat( SOCK, BUF, LEN )		read(  (SOCK), (BUF), (LEN) )
-		#define	write_compat( SOCK, BUF, LEN )		write( (SOCK), (BUF), (LEN) )
-	
-		#define	errno_compat()				errno
-		#define	set_errno_compat( X )		do { errno = (X); } while( 0 )
-	#if( defined( SHUT_WR ) )
-		#define	SHUT_WR_COMPAT		SHUT_WR
-	#else
-		#define	SHUT_WR_COMPAT		1
-	#endif
-
-	#define errno_safe()	( errno_compat() ? errno_compat() : kUnknownErr )
-
-// iovec
-
-		typedef struct iovec		iovec_t;
-
-#if( !defined( SETIOV ) )
-	#define SETIOV( IOV, PTR, LEN ) \
-		do \
-		{ \
-			(IOV)->iov_base = (void *)(PTR); \
-			(IOV)->iov_len  = (LEN); \
-		\
-		}	while( 0 )
-#endif
-
-// Path Delimiters
-
-#define kHFSPathDelimiterChar				':'
-#define kHFSPathDelimiterString				":"
-
-#define	kPOSIXPathDelimiterChar				'/'
-#define	kPOSIXPathDelimiterString			"/"
-
-#define	kWindowsPathDelimiterChar			'\\'
-#define	kWindowsPathDelimiterString			"\\"
-
-	#define kNativePathDelimiterChar		kPOSIXPathDelimiterChar
-	#define kNativePathDelimiterString		kPOSIXPathDelimiterString
-
-// FDRef for File Handles/Descriptors
-
-	#define TARGET_HAVE_FDREF		1
-	
-	typedef int			FDRef;
-	
-	#define IsValidFD( X )				( (X) >= 0 )
-	#define kInvalidFD					-1
-	#define CloseFD( X )				close( X )
-	#define ReadFD( FD, PTR, LEN )		read( FD, PTR, LEN )
-	#define WriteFD( FD, PTR, LEN )		write( FD, PTR, LEN )
-
-// socklen_t is not defined on the following platforms so emulate it if not defined:
-//
-// - Pre-Panther Mac OS X. Panther defines SO_NOADDRERR so trigger off that.
-// - Windows SDK prior to 2003. 2003+ SDK's define EAI_AGAIN so trigger off that.
-// - VxWorks prior to PNE 2.2.1/IPv6.
-// - EFI when not building with GCC.
-
-	#if( ( TARGET_OS_DARWIN && !defined( SO_NOADDRERR ) )	|| \
-		 ( TARGET_OS_WINDOWS && !defined( EAI_AGAIN ) )		|| \
-		 ( TARGET_OS_VXWORKS && ( TORNADO_VERSION < 221 ) )	|| \
-		 TARGET_OS_EFI && !defined( __GNUC__ ) )
-		typedef int		socklen_t;
-	#endif
-
-// EFI doesn't have stdarg.h or string.h, but it does have some equivalents so map them to the standard names.
-
-// Darwin Kernel mappings.
-
-// NetBSD Kernel mappings.
-
-// Windows CE doesn't have strdup and Visual Studio 2005 marks strdup, stricmp, and strnicmp as a deprecated so map 
-// them to their underscore variants on Windows so code can use the standard names on all platforms.
-
-// Windows doesn't have snprintf/vsnprintf, but it does have _snprintf/_vsnprintf.
-// Additionally, Visual Studio 2005 and later have deprecated these functions and replaced them with
-// versions with an _s suffix (supposedly more secure). So just map the standard functions to those.
-
-// Generic mappings.
-
-#if( !MALLOC_COMPAT_DEFINED )
-	#define malloc_compat( SIZE )		tls_mem_alloc( (SIZE ) )
-	#define free_compat( PTR )			tls_mem_free( (PTR) )
-#endif
-
-#if 0
-#pragma mark -
-#pragma mark == Compatibility - Compiler ==
-#endif
-
-//===========================================================================================================================
-//	Compatibility - Compiler
-//===========================================================================================================================
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	__builtin_expect
-	@abstract	Compatibility macro for GCC branch prediction.
-	@discussion
-	
-	GCC supports explicit branch prediction so that the CPU back-end can hint the processor and also so that code 
-	blocks can be reordered such that the predicted path sees a more linear flow, thus improving cache behavior, etc.
-	See <http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html> for info
-	
-	Here's an example of using it when "x == 0" is unlikely:
-	
-	if( __builtin_expect( x == 0, 0 ) ) // Programmer predicts that the result of "x == 0" is likely to be 0 (i.e. false).
-	{
-		// x == 0, but this should be unlikely.
-	}
-	
-	Or to reverse the prediction such that "x == 0" is likely:
-	
-	if( __builtin_expect( x == 0, 1 ) ) // Programmer predicts that the result of "x == 0" is likely to be 1 (i.e. true).
-	{
-		// x == 0, the likely situation.
-	}
-	
-	Note: since GCC only supports integer expressions for the expected result, if you are doing pointer comparisons, 
-	you have to do the test inside the expression and test it for 1 or 0, like this:
-	
-	if( __builtin_expect( ptr != NULL, 1 ) ) // Programmer predicts that ptr is likely to be non-NULL.
-	{
-		// ptr != NULL, the likely situation.
-	}
-*/
-
-// Note: the RealView ARM compiler says it supports __builtin_expect, but it doesn't seem to work so exclude it too.
-
-#if( !defined( __builtin_expect ) && ( !defined( __GNUC__ ) || ( __GNUC__ < 3 ) || __ARMCC_VERSION ) )
-	#define __builtin_expect( EXPRESSSION, EXPECTED_RESULT )		( EXPRESSSION )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	likely/unlikely
-	@abstract	Macro for Linux-style branch prediction.
-	@discussion
-	
-	Use these macros like this:
-	
-	if( likely( ptr != NULL ) )
-	{
-		// This code path happens frequently (ptr is usually non-NULL).
-	}
-	else
-	{
-		// This code path rarely happens (ptr is rarely NULL).
-	}
-	
-	if( unlikely( err != kNoErr ) )
-	{
-		// This code path rarely happens (errors rarely occur).
-	}
-	else
-	{
-		// This code path happens frequently (normally kNoErr).
-	}
-*/
-#if( !defined( likely ) )
-	#define likely( EXPRESSSION )		__builtin_expect( !!(EXPRESSSION), 1 )
-#endif
-
-#if( !defined( unlikely ) )
-	#define unlikely( EXPRESSSION )		__builtin_expect( !!(EXPRESSSION), 0 )
-#endif
-
-// C99's _Pragma operator is not yet supported with Visual Studio, but Visual Studio does support __pragma so use that.
-
-// PRAGMA_PACKPUSH	- Compiler supports: #pragma pack(push, n)/pack(pop)
-// PRAGMA_PACK		- Compiler supports: #pragma pack(n)
-//
-// Here's the common way to use these before declaring structures:
-/*
-	#if( PRAGMA_PACKPUSH )
-		#pragma pack( push, 2 )
-	#elif( PRAGMA_PACK )
-		#pragma pack( 2 )
-	#else
-		#warning "FIX ME: packing not supported by this compiler"
-	#endif
-	
-	Then after the declaring structures:
-	
-	#if( PRAGMA_PACKPUSH )
-		#pragma pack( pop )
-	#elif( PRAGMA_PACK )
-		#pragma pack()
-	#else
-		#warning "FIX ME: packing not supported by this compiler"
-	#endif
-*/
-
-#if( _MSC_VER || ( defined( __GNUC__ ) && TARGET_OS_DARWIN ) || defined( __ghs__ ) )
-	#define PRAGMA_PACKPUSH		1
-#else
-	#define PRAGMA_PACKPUSH		0
-#endif
-
-#if( defined( __GNUC__ ) || _MSC_VER || defined( __MWERKS__ ) || defined( __ghs__ ) )
-	#define PRAGMA_PACK			1
-#else
-	#define PRAGMA_PACK			0
-#endif
-
-#if( !defined( PRAGMA_STRUCT_PACKPUSH ) )
-	#define PRAGMA_STRUCT_PACKPUSH		PRAGMA_PACKPUSH
-#endif
-
-#if( !defined( PRAGMA_STRUCT_PACK ) )
-	#define PRAGMA_STRUCT_PACK			PRAGMA_PACK
-#endif
-
-// TARGET_HAS_BUILTIN_CLZ - Compiler supports __builtin_clz to count the number of leading zeros in an integer.
-
-#if  ( __clang__ || ( __GNUC__ >= 4 ) )
-	#define TARGET_HAS_BUILTIN_CLZ		1
-#else
-	#define TARGET_HAS_BUILTIN_CLZ		0
-#endif
-
-// static_analyzer_cfretained -- Tells the static analyzer that a CF object was retained (e.g. by a called function).
-// static_analyzer_cfreleased -- Tells the static analyzer that a CF object will be released (e.g. passed to a releasing function).
-// Remove this when clang does inter-procedural analysis <rdar://problem/8178274>.
-
-#ifdef __clang_analyzer__
-	#define static_analyzer_cfretained( X )		CFRetain( (X) )
-	#define static_analyzer_cfreleased( X )		CFRelease( (X) )
-#else
-	#define static_analyzer_cfretained( X )
-	#define static_analyzer_cfreleased( X )
-#endif
-
-// static_analyzer_malloc_freed -- Tells the static analyzer that malloc'd memory will be freed (e.g. by a called function).
-// Remove this when clang does inter-procedural analysis <rdar://problem/10925331>.
-
-#ifdef __clang_analyzer__
-	#define static_analyzer_malloc_freed( X )	free( (X) )
-#else
-	#define static_analyzer_malloc_freed( X )
-#endif
-
-// static_analyzer_nsretained -- Tells the static analyzer that an NS object was retained (e.g. by a called function).
-// static_analyzer_nsreleased -- Tells the static analyzer that an NS object will be released (e.g. passed to a releasing function).
-// Remove this when clang does inter-procedural analysis <rdar://problem/8178274>.
-
-#ifdef __clang_analyzer__
-	#define static_analyzer_nsretained( X )		[(X) retain]
-	#define static_analyzer_nsreleased( X )		[(X) release]
-#else
-	#define static_analyzer_nsretained( X )
-	#define static_analyzer_nsreleased( X )
-#endif
-
-#if 0
-#pragma mark -
-#pragma mark == Compatibility - Includes ==
-#endif
-
-//===========================================================================================================================
-//	Compatibility - Includes
-//===========================================================================================================================
-
-// AUDIO_CONVERTER_HEADER -- Header file to include for AudioConverter support.
-
-	#define AUDIO_CONVERTER_HEADER		"AudioConverterLite.h"
-	
-	#if( !defined( AUDIO_CONVERTER_LITE_ENABLED ) )
-		#define AUDIO_CONVERTER_LITE_ENABLED		1
-	#endif
-
-// COREAUDIO_HEADER -- Header file to include for CoreAudio types.
-
-	#define COREAUDIO_HEADER		"APSCommonServices.h"
-
-// CF_HEADER -- Header file to include for CoreFoundation support.
-
-	#define CF_HEADER		"CFCompat.h"
-
-// CF_RUNTIME_HEADER -- Header file to include for CoreFoundation's runtime support.
-
-	#define CF_RUNTIME_HEADER		"CFCompat.h"
-
-// CMSYNC_HEADER -- Header file to include for CoreMedia's clock APIs.
-
-// LIBDISPATCH_HEADER -- Header file to include for libdispatch/GCD support.
-
-	#define LIBDISPATCH_HEADER		"DispatchLite.h"
-
-// MD5_HEADER -- Header file to include for MD5 support.
-
-#if( TARGET_HAS_COMMON_CRYPTO_DIGEST )
-	#define MD5_HEADER		<CommonCrypto/CommonDigest.h>
-#elif( TARGET_HAS_MOCANA_SSL )
-	#define MD5_HEADER		"MD5Utils.h"
-#elif( TARGET_HAS_USSL )
-	#define MD5_HEADER		"wiced_security.h"
-#elif( TARGET_HAS_MD5_UTILS )
-	#define MD5_HEADER		"MD5Utils.h"
-#elif( !TARGET_NO_OPENSSL )
-	#define MD5_HEADER		<openssl/md5.h>
-#else
-	#define MD5_HEADER		"APSCommonServices.h" // Can't think of a better way without messy #if's at the call site.
-#endif
-
-// SHA_HEADER -- Header file to include for SHA support.
-
-#if( TARGET_HAS_COMMON_CRYPTO_DIGEST )
-	#define SHA_HEADER		<CommonCrypto/CommonDigest.h>
-#elif( TARGET_HAS_MOCANA_SSL )
-	#define SHA_HEADER		"SHAUtils.h"
-#elif( TARGET_HAS_USSL )
-	#define SHA_HEADER		"wiced_security.h"
-#elif( TARGET_HAS_SHA_UTILS )
-	#define SHA_HEADER		"SHAUtils.h"
-#elif( !TARGET_NO_OPENSSL )
-	#define SHA_HEADER		<openssl/sha.h>
-#else
-	#define SHA_HEADER		"APSCommonServices.h" // Can't think of a better way without messy #if's at the call site.
-#endif
-
-#if 0
-#pragma mark -
-#pragma mark == Compatibility - Networking ==
-#endif
-
-//===========================================================================================================================
-//	Compatibility - Networking
-//===========================================================================================================================
-
-#if( !defined( AF_UNSPEC ) && !TARGET_NETWORK_NETX_DUO )
-	#define AF_UNSPEC		0
-	#define AF_INET			4
-	//#define AF_INET6		6
-	#define AF_LINK			7
-	
-	#define LLADDR( X )		( (X)->sdl_data + (X)->sdl_nlen )
-#endif
-
-#if( !defined( SO_REUSEPORT ) )
-	#define SO_REUSEPORT		SO_REUSEADDR
-#endif
-
-// sockaddr
-
-// sockaddr_in
-
-// sockaddr_in6
-
-// sockaddr_dl
-
-// sockaddr_ip -- like sockaddr_storage, but only for IPv4 and IPv6, doesn't require casts, and saves space.
-
-#if( TARGET_LANGUAGE_C_LIKE && !TARGET_NETWORK_NETX_DUO && !defined( __TCP_CONNECTION_H__ ) )
-
-typedef unsigned char UCHAR;
-typedef unsigned short USHORT;
-typedef USHORT ADDRESS_FAMILY;
-//
-// IPv6 Internet address (RFC 2553)
-// This is an 'on-wire' format structure.
-//
-/*
-typedef struct in6_addr {
-    union {
-        UCHAR       s6_bytes[16];
-        USHORT      Word[8];
-    } u;
-} IN6_ADDR, *PIN6_ADDR;*/
-
-typedef struct in6_addr IN6_ADDR, *PIN6_ADDR;
-
-typedef struct {
-    union {
-        struct {
-            ULONG Zone : 28;
-            ULONG Level : 4;
-        };
-        ULONG Value;
-    };
-} SCOPE_ID, *PSCOPE_ID;
-/*typedef struct sockaddr_in6 {
-    ADDRESS_FAMILY sin6_family; // AF_INET6.
-    USHORT sin6_port;           // Transport level port number.
-    ULONG  sin6_flowinfo;       // IPv6 flow information.
-    IN6_ADDR sin6_addr;         // IPv6 address.
-    union {
-        ULONG sin6_scope_id;     // Set of interfaces for a scope.
-        SCOPE_ID sin6_scope_struct; 
-    };
-} SOCKADDR_IN6_LH, *PSOCKADDR_IN6_LH;
-*/
-typedef struct sockaddr_in6 SOCKADDR_IN6_LH, *PSOCKADDR_IN6_LH;
-
-	typedef union
-	{
-		struct sockaddr				sa;
-		struct sockaddr_in			v4;
-	#if TLS_CONFIG_IPV6
-		#if( defined( AF_INET6 ) )
-			struct sockaddr_in6		v6;
-		#endif
-	#endif
-		
-	}	sockaddr_ip;
-#endif
-
-// Macros to workaround sin_len, etc. not being present on some platforms. SIN6_LEN seems like a reasonable indictor.
-
-#if( !defined( SUN_LEN_SET ) )
-	#if( defined( SIN6_LEN ) )
-		#define	SUN_LEN_SET( X )	(X)->sun_len = (unsigned char) SUN_LEN( (X) )
-	#else
-		#define	SUN_LEN_SET( X )	do {} while( 0 )
-	#endif
-#endif
-
-#if( !defined( SIN_LEN_SET ) )
-	#if( defined( SIN6_LEN ) )
-		#define	SIN_LEN_SET( X )	(X)->sin_len = (unsigned char) sizeof( struct sockaddr_in )
-	#else
-		#define	SIN_LEN_SET( X )	do {} while( 0 )
-	#endif
-#endif
-
-#if( !defined( SIN6_LEN_SET ) )
-	#if( defined( SIN6_LEN ) )
-		#define	SIN6_LEN_SET( X )	(X)->sin6_len = (unsigned char) sizeof( struct sockaddr_in6 )
-	#else
-		#define	SIN6_LEN_SET( X )	do {} while( 0 )
-	#endif
-#endif
-
-// Determines if a sockaddr is a link-local address whether IPv6 is supported or not.
-
-#if( defined( AF_INET6 ) )
-	#define	SockAddrIsLinkLocal( X )	( SockAddrIsIPv4LinkLocal( (X) ) || SockAddrIsIPv6LinkLocal( (X) ) )
-#else
-	#define	SockAddrIsLinkLocal( X )	SockAddrIsIPv4LinkLocal( (X) )
-#endif
-
-#define	SockAddrIsIPv4LinkLocal( X ) \
-		( ( ( (const struct sockaddr *)(X) )->sa_family == AF_INET ) \
-		  ? ( ( ( (uint8_t *)( &( (const struct sockaddr_in *)(X) )->sin_addr ) )[ 0 ] == 169 ) && \
-			  ( ( (uint8_t *)( &( (const struct sockaddr_in *)(X) )->sin_addr ) )[ 1 ] == 254 ) ) \
-		  : 0 )
-
-#define	SockAddrIsIPv6LinkLocal( X ) \
-		( ( ( (const struct sockaddr *)(X) )->sa_family == AF_INET6 ) \
-		  ? IN6_IS_ADDR_LINKLOCAL( &( (const struct sockaddr_in6 *)(X) )->sin6_addr ) : 0 )
-
-#if( !defined( IN6_IS_ADDR_LINKLOCAL ) )
-	#define IN6_IS_ADDR_LINKLOCAL( a )	( ( (a)->s6_addr[ 0 ] == 0xfe ) && ( ( (a)->s6_addr[ 1 ] & 0xc0 ) == 0x80 ) )
-#endif
-
-// Determines if a sockaddr is a loopback address whether IPv6 is supported or not.
-
-#if( defined( AF_INET6 ) )
-	#define	SockAddrIsLoopBack( X ) \
-		( ( ( (const struct sockaddr *)(X) )->sa_family == AF_INET ) \
-		  ? ( ( (const struct sockaddr_in *)(X) )->sin_addr.s_addr == htonl( INADDR_LOOPBACK ) ) \
-		  : ( ( (const struct sockaddr *)(X) )->sa_family == AF_INET6 ) \
-			? IN6_IS_ADDR_LOOPBACK( &( (const struct sockaddr_in6 *)(X) )->sin6_addr ) \
-			: 0 )
-#else
-	#define	SockAddrIsLoopBack( X ) \
-		( ( ( (const struct sockaddr *)(X) )->sa_family == AF_INET ) \
-		  ? ( ( (const struct sockaddr_in *)(X) )->sin_addr.s_addr == htonl( INADDR_LOOPBACK ) ) \
-		  : 0 )
-#endif
-
-// Determines if a sockaddr is a multicast address whether IPv6 is supported or not.
-
-#if( defined( AF_INET6 ) )
-	#define	SockAddrIsMulticast( X ) \
-		( ( ( (const struct sockaddr *)(X) )->sa_family == AF_INET ) \
-		  ? ( ( ( (uint8_t *)( &( (const struct sockaddr_in *)(X) )->sin_addr ) )[ 0 ] & 0xF0 ) == 0xE0 ) \
-		  : ( ( (const struct sockaddr *)(X) )->sa_family == AF_INET6 ) \
-			? IN6_IS_ADDR_MULTICAST( &( (const struct sockaddr_in6 *)(X) )->sin6_addr ) \
-			: 0 )
-#else
-	#define	SockAddrIsMulticast( X ) \
-		( ( ( (const struct sockaddr *)(X) )->sa_family == AF_INET ) \
-		  ? ( ( ( (uint8_t *)( &( (const struct sockaddr_in *)(X) )->sin_addr ) )[ 0 ] & 0xF0 ) == 0xE0 ) \
-		  : 0 )
-#endif
-
-// Maps a sockaddr family to a string.
-
-#if( defined( AF_INET6 ) && defined( AF_LINK ) )
-	#define	SockAddrFamilyToString( X ) \
-		( ( (X) == AF_INET )	? "AF_INET"  : \
-		( ( (X) == AF_INET6 )	? "AF_INET6" : \
-		( ( (X) == AF_LINK )	? "AF_LINK"  : \
-								  "UNKNOWN" ) ) )
-#elif( defined( AF_INET6 ) )
-	#define	SockAddrFamilyToString( X ) \
-		( ( (X) == AF_INET )	? "AF_INET"  : \
-		( ( (X) == AF_INET6 )	? "AF_INET6" : \
-								  "UNKNOWN" ) )
-#elif( defined( AF_LINK ) )
-	#define	SockAddrFamilyToString( X ) \
-		( ( (X) == AF_INET )	? "AF_INET"  : \
-		( ( (X) == AF_LINK )	? "AF_LINK"  : \
-								  "UNKNOWN" ) )
-#else
-	#define	SockAddrFamilyToString( X ) \
-		( ( (X) == AF_INET )	? "AF_INET"  : \
-								  "UNKNOWN" )
-#endif
-
-// Determines if a 16-byte IPv6 address is an IPv4-mapped IPv6 address.
-
-#define	IsIPv4MappedIPv6Address( A ) \
-	(	( ( (const uint8_t *)(A) )[  0 ] == 0 )		&& \
-		( ( (const uint8_t *)(A) )[  1 ] == 0 )		&& \
-		( ( (const uint8_t *)(A) )[  2 ] == 0 )		&& \
-		( ( (const uint8_t *)(A) )[  3 ] == 0 )		&& \
-		( ( (const uint8_t *)(A) )[  4 ] == 0 )		&& \
-		( ( (const uint8_t *)(A) )[  5 ] == 0 )		&& \
-		( ( (const uint8_t *)(A) )[  6 ] == 0 )		&& \
-		( ( (const uint8_t *)(A) )[  7 ] == 0 )		&& \
-		( ( (const uint8_t *)(A) )[  8 ] == 0 )		&& \
-		( ( (const uint8_t *)(A) )[  9 ] == 0 )		&& \
-		( ( (const uint8_t *)(A) )[ 10 ] == 0xFF )	&& \
-		( ( (const uint8_t *)(A) )[ 11 ] == 0xFF ) )
-
-// Determines if a 16-byte IPv6 address is an IPv4-compatible IPv6 address.
-
-#define	IsIPv4CompatibleIPv6Address( A ) \
-	(	(	( ( (const uint8_t *)(A) )[  0 ] == 0 )		&& \
-			( ( (const uint8_t *)(A) )[  1 ] == 0 )		&& \
-			( ( (const uint8_t *)(A) )[  2 ] == 0 )		&& \
-			( ( (const uint8_t *)(A) )[  3 ] == 0 )		&& \
-			( ( (const uint8_t *)(A) )[  4 ] == 0 )		&& \
-			( ( (const uint8_t *)(A) )[  5 ] == 0 )		&& \
-			( ( (const uint8_t *)(A) )[  6 ] == 0 )		&& \
-			( ( (const uint8_t *)(A) )[  7 ] == 0 )		&& \
-			( ( (const uint8_t *)(A) )[  8 ] == 0 )		&& \
-			( ( (const uint8_t *)(A) )[  9 ] == 0 )		&& \
-			( ( (const uint8_t *)(A) )[ 10 ] == 0 )		&& \
-			( ( (const uint8_t *)(A) )[ 11 ] == 0 ) )	&& \
-		!(	( ( (const uint8_t *)(A) )[ 12 ] == 0 )		&& \
-			( ( (const uint8_t *)(A) )[ 13 ] == 0 )		&& \
-			( ( (const uint8_t *)(A) )[ 14 ] == 0 )		&& \
-			( ( (const uint8_t *)(A) )[ 15 ] == 0 ) )	&& \
-		!(	( ( (const uint8_t *)(A) )[ 12 ] == 0 )		&& \
-			( ( (const uint8_t *)(A) )[ 13 ] == 0 )		&& \
-			( ( (const uint8_t *)(A) )[ 14 ] == 0 )		&& \
-			( ( (const uint8_t *)(A) )[ 15 ] == 1 ) ) )
-
-#define kDNSServiceFlagsUnicastResponse_compat		0x400000	// Added in version 393 of dns_sd.h.
-#define kDNSServiceFlagsThresholdOne_compat			0x2000000	// Added in version 504 of dns_sd.h
-#define kDNSServiceFlagsThresholdReached_compat		0x2000000	// Added in version 504 of dns_sd.h
-
-#if 0
-#pragma mark -
-#pragma mark == Compatibility - CoreAudio ==
-#endif
-
-//===========================================================================================================================
-//	Compatibility - CoreAudio
-//===========================================================================================================================
-
-#if( TARGET_RT_BIG_ENDIAN )
-	#define kAudioFormatFlagsNativeEndian			kAudioFormatFlagIsBigEndian
-#else
-	#define kAudioFormatFlagsNativeEndian			0
-#endif
-#define kAudioFormatFlagIsFloat						( 1 << 0 )
-#define kAudioFormatFlagIsBigEndian					( 1 << 1 )
-#define kAudioFormatFlagIsPacked					( 1 << 3 )
-#define kAudioFormatFlagIsSignedInteger				( 1 << 2 )
-#define kAudioFormatFlagIsAlignedHigh				( 1 << 4 )
-#define kAudioFormatFlagIsNonInterleaved			( 1 << 5 )
-#define kAudioFormatFlagIsNonMixable				( 1 << 6 )
-
-#define kAudioConverterDecompressionMagicCookie		0x646D6763 // 'dmgc'
-
-#define kAudioFormatAppleLossless					0x616C6163 // 'alac'
-	#define kAppleLosslessFormatFlag_16BitSourceData	1
-	#define kAppleLosslessFormatFlag_20BitSourceData	2
-	#define kAppleLosslessFormatFlag_24BitSourceData	3
-	#define kAppleLosslessFormatFlag_32BitSourceData	4
-#define kAudioFormatLinearPCM						0x6C70636D // 'lpcm'
-	#define kLinearPCMFormatFlagIsFloat					kAudioFormatFlagIsFloat
-	#define kLinearPCMFormatFlagIsBigEndian				kAudioFormatFlagIsBigEndian
-	#define kLinearPCMFormatFlagIsSignedInteger			kAudioFormatFlagIsSignedInteger
-	#define kLinearPCMFormatFlagIsPacked				kAudioFormatFlagIsPacked
-	#define kLinearPCMFormatFlagIsAlignedHigh			kAudioFormatFlagIsAlignedHigh
-	#define kLinearPCMFormatFlagIsNonInterleaved		kAudioFormatFlagIsNonInterleaved
-	#define kLinearPCMFormatFlagIsNonMixable			kAudioFormatFlagIsNonMixable
-	#define kLinearPCMFormatFlagsSampleFractionShift	7
-	#define kLinearPCMFormatFlagsSampleFractionMask		( 0x3F << kLinearPCMFormatFlagsSampleFractionShift )
-
-#define kAudioFormatMPEG4AAC						0x61616320 // 'aac '
-#define kAudioFormatMPEG4AAC_ELD					0x61616365 // 'aace'
-
-typedef struct
-{
-	uint32_t		mSampleRate;
-	uint32_t		mFormatID;
-	uint32_t		mFormatFlags;
-	uint32_t		mBytesPerPacket;
-	uint32_t		mFramesPerPacket;
-	uint32_t		mBytesPerFrame;
-	uint32_t		mChannelsPerFrame;
-	uint32_t		mBitsPerChannel;
-	uint32_t		mReserved;
-	
-}	AudioStreamBasicDescription;
-
-#define kAudioSamplesPerPacket_AAC_ELD				480
-#define kAudioSamplesPerPacket_AAC_LC				1024
-#define kAudioSamplesPerPacket_ALAC_Small			352  // Sized for sending one frame per UDP packet.
-#define kAudioSamplesPerPacket_ALAC_Default			4096
-
-#define ASBD_FillAAC_ELD( FMT, RATE, CHANNELS ) \
-	do \
-	{ \
-		(FMT)->mSampleRate			= (RATE); \
-		(FMT)->mFormatID			= kAudioFormatMPEG4AAC_ELD; \
-		(FMT)->mFormatFlags			= 0; \
-		(FMT)->mBytesPerPacket		= 0; \
-		(FMT)->mFramesPerPacket		= kAudioSamplesPerPacket_AAC_ELD; \
-		(FMT)->mBytesPerFrame		= 0; \
-		(FMT)->mChannelsPerFrame	= (CHANNELS); \
-		(FMT)->mBitsPerChannel		= 0; \
-		(FMT)->mReserved			= 0; \
-		\
-	}	while( 0 )
-
-#define ASBD_FillAAC_LC( FMT, RATE, CHANNELS ) \
-	do \
-	{ \
-		(FMT)->mSampleRate			= (RATE); \
-		(FMT)->mFormatID			= kAudioFormatMPEG4AAC; \
-		(FMT)->mFormatFlags			= 0; \
-		(FMT)->mBytesPerPacket		= 0; \
-		(FMT)->mFramesPerPacket		= kAudioSamplesPerPacket_AAC_LC; \
-		(FMT)->mBytesPerFrame		= 0; \
-		(FMT)->mChannelsPerFrame	= (CHANNELS); \
-		(FMT)->mBitsPerChannel		= 0; \
-		(FMT)->mReserved			= 0; \
-		\
-	}	while( 0 )
-
-#define ASBD_FillALAC( FMT, RATE, BITS, CHANNELS ) \
-	do \
-	{ \
-		(FMT)->mSampleRate			= (RATE); \
-		(FMT)->mFormatID			= kAudioFormatAppleLossless; \
-		(FMT)->mFormatFlags			= ( (BITS) == 16 ) ? kAppleLosslessFormatFlag_16BitSourceData : \
-									  ( (BITS) == 20 ) ? kAppleLosslessFormatFlag_20BitSourceData : \
-									  ( (BITS) == 24 ) ? kAppleLosslessFormatFlag_24BitSourceData : 0; \
-		(FMT)->mBytesPerPacket		= 0; \
-		(FMT)->mFramesPerPacket		= kAudioSamplesPerPacket_ALAC_Small; \
-		(FMT)->mBytesPerFrame		= 0; \
-		(FMT)->mChannelsPerFrame	= (CHANNELS); \
-		(FMT)->mBitsPerChannel		= 0; \
-		(FMT)->mReserved			= 0; \
-		\
-	}	while( 0 )
-
-#define ASBD_FillAUCanonical( FMT, CHANNELS ) \
-	do \
-	{ \
-		(FMT)->mSampleRate			= 48000; \
-		(FMT)->mFormatID			= kAudioFormatLinearPCM; \
-		(FMT)->mFormatFlags			= kAudioFormatFlagIsFloat | \
-									  kAudioFormatFlagsNativeEndian | \
-									  kAudioFormatFlagIsPacked | \
-									  kAudioFormatFlagIsNonInterleaved; \
-		(FMT)->mBytesPerPacket		= 4; \
-		(FMT)->mFramesPerPacket		= 1; \
-		(FMT)->mBytesPerFrame		= 4; \
-		(FMT)->mChannelsPerFrame	= (CHANNELS); \
-		(FMT)->mBitsPerChannel		= 32; \
-		(FMT)->mReserved			= 0; \
-		\
-	}	while( 0 )
-
-#define ASBD_FillPCM( FMT, RATE, VALID_BITS, TOTAL_BITS, CHANNELS ) \
-	do \
-	{ \
-		(FMT)->mSampleRate			= (RATE); \
-		(FMT)->mFormatID			= kAudioFormatLinearPCM; \
-		(FMT)->mFormatFlags			= kAudioFormatFlagsNativeEndian   | \
-									  kAudioFormatFlagIsSignedInteger | \
-									  ( ( (VALID_BITS) == (TOTAL_BITS) ) ? \
-									  	kAudioFormatFlagIsPacked : \
-									  	kAudioFormatFlagIsAlignedHigh ); \
-		(FMT)->mBytesPerPacket		= (CHANNELS) * ( (TOTAL_BITS) / 8 ); \
-		(FMT)->mFramesPerPacket		= 1; \
-		(FMT)->mBytesPerFrame		= (CHANNELS) * ( (TOTAL_BITS) / 8 ); \
-		(FMT)->mChannelsPerFrame	= (CHANNELS); \
-		(FMT)->mBitsPerChannel		= (VALID_BITS); \
-		(FMT)->mReserved			= 0; \
-		\
-	}	while( 0 )
-
-#define ASBD_MakePCM( RATE, VALID_BITS, TOTAL_BITS, CHANNELS ) \
-	{ \
-		/* mSampleRate			*/	(RATE), \
-		/* mFormatID			*/	kAudioFormatLinearPCM, \
-		/* mFormatFlags 		*/	kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsSignedInteger | \
-									( ( (VALID_BITS) == (TOTAL_BITS) ) ? \
-										kAudioFormatFlagIsPacked : \
-										kAudioFormatFlagIsAlignedHigh ), \
-		/* mBytesPerPacket		*/	(CHANNELS) * ( (TOTAL_BITS) / 8 ), \
-		/* mFramesPerPacket		*/	1, \
-		/* mBytesPerFrame		*/	(CHANNELS) * ( (TOTAL_BITS) / 8 ), \
-		/* mChannelsPerFrame	*/	(CHANNELS), \
-		/* mBitsPerChannel		*/	(VALID_BITS), \
-		/* mReserved			*/	0 \
-	}
-
-typedef struct // From ACAppleLosslessCodec.h.
-{
-	uint32_t		frameLength;		// Note: AudioConverter expects this in big endian byte order.
-	uint8_t			compatibleVersion;
-	uint8_t			bitDepth;			// max 32
-	uint8_t			pb;					// 0 <= pb <= 255
-	uint8_t			mb;
-	uint8_t			kb;
-	uint8_t			numChannels;
-	uint16_t		maxRun;				// Note: AudioConverter expects this in big endian byte order.
-	uint32_t		maxFrameBytes;		// Note: AudioConverter expects this in big endian byte order.
-	uint32_t		avgBitRate;			// Note: AudioConverter expects this in big endian byte order.
-	uint32_t		sampleRate;			// Note: AudioConverter expects this in big endian byte order.
-	
-}	ALACParams;
-
-#if 0
-#pragma mark -
-#pragma mark == Compatibility - Other ==
-#endif
-
-//===========================================================================================================================
-//	Compatibility - Other
-//===========================================================================================================================
-
-// _beginthreadex and _endthreadex are not supported on Windows CE 2.1 or later (the C runtime issues with leaking 
-// resources have apparently been resolved and they seem to have just ripped out support for the API) so map it to 
-// CreateThread on Windows CE.
-
-// GetProcAddress takes a char string on normal Windows, but a TCHAR string on Windows CE so hide this in a macro.
-
-// Calling conventions
-
-#if( !defined( CALLBACK_COMPAT ) )
-		#define	CALLBACK_COMPAT
-#endif
-
-// CFEqual that's safe to call with NULL parameters.
-#define CFEqualNullSafe( A, B )		( ( (A) == (B) ) || ( (A) && (B) && CFEqual( (A), (B) ) ) )
-
-// CFEqual that's safe to call with NULL parameters and treats NULL and kCFNull as equal.
-#define CFEqualNullSafeEx( A, B )	( ( (A) == (B) ) || CFEqual( (A) ? (A) : kCFNull, (B) ? (B) : kCFNull ) )
-
-// Null-safe macro to make CF type checking easier.
-#define CFIsType( OBJ, TYPE )		( (OBJ) && ( CFGetTypeID( (OBJ) ) == TYPE##GetTypeID() ) )
-
-// CFRelease that's safe to call with NULL.
-#define CFReleaseNullSafe( X )		do { if( (X) ) CFRelease( (X) ); } while( 0 )
-
-// CFRetain that's safe to call with NULL.
-#define CFRetainNullSafe( X )		do { if( (X) ) CFRetain( (X) ); } while( 0 )
-
-// CFString comparison with all the right options for sorting the way humans expect it.
-	#define CFStringLocalizedStandardCompare( A, B ) \
-		CFStringCompare( (A), (B), kCFCompareCaseInsensitive | kCFCompareNumerically )
-
-// HAS_CF_DISTRIBUTED_NOTIFICATIONS
-
-#if( !defined( HAS_CF_DISTRIBUTED_NOTIFICATIONS ) )
-		#define HAS_CF_DISTRIBUTED_NOTIFICATIONS		0
-#endif
-
-// NetBSD uses a uintptr_t for the udata field of the kevent structure, but other platforms use a void * so map it on NetBSD.
-
-	#define	EV_SET_compat( kevp, a, b, c, d, e, f )	EV_SET( kevp, a, b, c, d, e, f )
-
-// MAP_ANONYMOUS is preferred on Linux and some other platforms so map MAP_ANON to that.
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	RandomRange
-	@abstract	Returns a random number that's >= MIN and <= MAX (i.e. it's inclusive). MIN must be <= MAX.
-*/
-#define RandomRange( MIN, MAX )		( (MIN) + ( Random32() % ( ( (MAX) - (MIN) ) + 1 ) ) )
-#define RandomRangeF( MIN, MAX )	( ( ( Random32() / 4294967295.0 ) * ( (MAX) - (MIN) ) ) + (MIN) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	Random32
-	@abstract	Returns a random number that usually has 30-32 bits of randomness and is reasonably fast.
-*/
-	#define Random32()		( (uint32_t) rand() )
-
-#if 0
-#pragma mark -
-#pragma mark == Misc ==
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	PRINTF_STYLE_FUNCTION
-	@abstract	Some compilers allow you to mark printf-style functions so their format string and argument list 
-				is checked by the compiler. Adding PRINTF_STYLE_FUNCTION to a function enables this functionality.
-	
-	@param		FORMAT_INDEX		1's-based index of the format string (e.g. if the 2nd param is the format string, use 2).
-	@param		ARGS_INDEX			1's-based index of the first arg. The function takes a va_list, use 0.
-	
-	@discussion	
-	
-	Here's an example of using it:
-	
-	void MyPrintF( const char *inFormat, ... ) PRINTF_STYLE_FUNCTION( 1, 2 );
-	
-	Many of the printf-style function provide more format string features than supported by GCC's printf checking
-	(e.g. dlog supports %.4a for printing IPv4 addresses). GCC will flag these as errors so by default, printf-style
-	function checking is disabled. To enable it, #define CHECK_PRINTF_STYLE_FUNCTIONS to 1.
-*/
-#if( CHECK_PRINTF_STYLE_FUNCTIONS && defined( __GNUC__ ) )
-	#define PRINTF_STYLE_FUNCTION( FORMAT_INDEX, ARGS_INDEX )	__attribute__( ( format( printf, FORMAT_INDEX, ARGS_INDEX ) ) )
-#else
-	#define PRINTF_STYLE_FUNCTION( FORMAT_INDEX, ARGS_INDEX )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	EXPORT_PACKAGE
-	@abstract	Macro to mark a function as exported to other code within the same package.
-*/
-	#define	EXPORT_PACKAGE
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	EXPORT_GLOBAL
-	@abstract	Macro to mark a function as exported outside of the package.
-	@discussion	
-	
-	GCC 4.0 and later have improved support for marking all symbols __private_extern__ automatically so you can
-	explicitly mark only the functions you actually want exported. To make this work portably, EXPORT_GLOBAL lets 
-	you mark a symbol globally when it is supported by the compiler. Only really needed for IOKit drivers and DLL.
-	
-	To export a class as global, declare it like this:
-	
-	class EXPORT_GLOBAL MyClass
-	{
-		... normal class declaration stuff
-	};
-	
-	To export a function as global:
-	
-	EXPORT_GLOBAL void	MyFunction( void );
-*/
-#if( ( __GNUC__ > 4 ) || ( ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ >= 0 ) ) )
-	#define EXPORT_GLOBAL		__attribute__( ( visibility( "default" ) ) )
-#else
-	#define EXPORT_GLOBAL
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	EXPORT_GLOBAL_DATA
-	@abstract	Macro to mark a variable as exported outside of the package.
-	@discussion	
-	
-	Microsoft's linker requires that data imported from dll's be marked with "_declspec( dllimport )"
-	
-	To export a variable as global, declare it like this:
-	
-	EXPORT_GLOBAL_DATA int	gMyVariable;
-*/
-	#define EXPORT_GLOBAL_DATA extern
-
-#if 0
-#pragma mark == ctype safe macros ==
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@group		ctype safe macros
-	@abstract	Wrappers for the ctype.h macros make them safe when used with signed characters.
-	@discussion
-	
-	Some implementations of the ctype.h macros use the character value to directly index into a table.
-	This can lead to crashes and other problems when used with signed characters if the character value
-	is greater than 127 because the values 128-255 will appear to be negative if viewed as a signed char.
-	A negative subscript to an array causes it to index before the beginning and access invalid memory.
-	
-	To work around this, these *_safe wrappers mask the value and cast it to an unsigned char.
-*/
-#define isalnum_safe( X )		isalnum(  ( (unsigned char)( (X) & 0xFF ) ) )
-#define isalpha_safe( X )		isalpha(  ( (unsigned char)( (X) & 0xFF ) ) )
-#define iscntrl_safe( X )		iscntrl(  ( (unsigned char)( (X) & 0xFF ) ) )
-#define isdigit_safe( X )		isdigit(  ( (unsigned char)( (X) & 0xFF ) ) )
-#define isgraph_safe( X )		isgraph(  ( (unsigned char)( (X) & 0xFF ) ) )
-#define islower_safe( X )		islower(  ( (unsigned char)( (X) & 0xFF ) ) )
-#define isoctal_safe( X )		isoctal(  ( (unsigned char)( (X) & 0xFF ) ) )
-#define isprint_safe( X )		isprint(  ( (unsigned char)( (X) & 0xFF ) ) )
-#define ispunct_safe( X )		ispunct(  ( (unsigned char)( (X) & 0xFF ) ) )
-#define isspace_safe( X )		isspace(  ( (unsigned char)( (X) & 0xFF ) ) )
-#define isupper_safe( X )		isupper(  ( (unsigned char)( (X) & 0xFF ) ) )
-#define isxdigit_safe( X )		isxdigit( ( (unsigned char)( (X) & 0xFF ) ) )
-#define tolower_safe( X )		tolower(  ( (unsigned char)( (X) & 0xFF ) ) )
-#define toupper_safe( X )		toupper(  ( (unsigned char)( (X) & 0xFF ) ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@group		CoreFoundation object creation/subclassing.
-	@abstract	Macros to make it easier to create CFType subclasses.
-	@example
-	
-	struct MyClass
-	{
-		CFRuntimeBase		base; // CF type info. Must be first.
-		
-		... put any other fields you need here.
-	};
-	
-	CF_CLASS_DEFINE( MyClass )
-	
-	OSStatus	MyClassCreate( MyClassRef *outObj )
-	{
-		OSStatus		err;
-		MyClassRef		me;
-		
-		CF_OBJECT_CREATE( MyClass, me, err, exit );
-		
-		... object will be zero'd, but do any non-zero init you need here.
-		
-		*outObj = me;
-		err = kNoErr;
-		
-	exit:
-		return( err );
-	}
-	
-	static void	_MyClassFinalize( CFTypeRef inCF )
-	{
-		MyClassRef const		me = (MyClassRef) inCF;
-		
-		... do any finalization you need here. Don't free the object itself (that's handled by CF after this returns).
-	}
-*/
-#define CF_CLASS_DEFINE( NAME ) \
-	static void	_ ## NAME ## Finalize( CFTypeRef inCF ); \
-	\
-	static dispatch_once_t			g ## NAME ## InitOnce = 0; \
-	static CFTypeID					g ## NAME ## TypeID = _kCFRuntimeNotATypeID; \
-	static const CFRuntimeClass		k ## NAME ## Class = \
-	{ \
-		0,						/* version */ \
-		# NAME,					/* className */ \
-		NULL,					/* init */ \
-		NULL,					/* copy */ \
-		_ ## NAME ## Finalize,	/* finalize */ \
-		NULL,					/* equal -- NULL means pointer equality. */ \
-		NULL,					/* hash  -- NULL means pointer hash. */ \
-		NULL,					/* copyFormattingDesc */ \
-		NULL,					/* copyDebugDesc */ \
-		NULL,					/* reclaim */ \
-		NULL					/* refcount */ \
-	}; \
-	\
-	static void _ ## NAME ## GetTypeID( void *inContext ) \
-	{ \
-		(void) inContext; \
-		\
-		g ## NAME ## TypeID = _CFRuntimeRegisterClass( &k ## NAME ## Class ); \
-		check( g ## NAME ## TypeID != _kCFRuntimeNotATypeID ); \
-	} \
-	\
-	CFTypeID	NAME ## GetTypeID( void ) \
-	{ \
-		dispatch_once_f( &g ## NAME ## InitOnce, NULL, _ ## NAME ## GetTypeID ); \
-		return( g ## NAME ## TypeID ); \
-	} \
-	\
-	check_compile_time( sizeof_field( struct NAME ## Private, base ) == sizeof( CFRuntimeBase ) ); \
-	check_compile_time( offsetof( struct NAME ## Private, base ) == 0 )
-
-#define CF_OBJECT_CREATE( NAME, OBJ, ERR, EXIT_LABEL ) \
-	do \
-	{ \
-		size_t		extraLen; \
-		\
-		extraLen = sizeof( *OBJ ) - sizeof( OBJ->base ); \
-		OBJ = (NAME ## Ref) _CFRuntimeCreateInstance( NULL, NAME ## GetTypeID(), (CFIndex) extraLen, NULL ); \
-		require_action( OBJ, EXIT_LABEL, ERR = kNoMemoryErr ); \
-		memset( ( (uint8_t *) OBJ ) + sizeof( OBJ->base ), 0, extraLen ); \
-		\
-	}	while( 0 )
-
-#if 0
-#pragma mark == Macros ==
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	kSizeCString
-	@abstract	A meta-value to pass to supported routines to indicate the size should be calculated with strlen.
-*/
-#define	kSizeCString		( (size_t) -1 )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	countof
-	@abstract	Determines the number of elements in an array.
-*/
-#define	countof( X )						( sizeof( X ) / sizeof( X[ 0 ] ) )
-#define	countof_field( TYPE, FIELD )		countof( ( (TYPE *) 0 )->FIELD )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	offsetof
-	@abstract	Number of bytes from the beginning of the type to the specified field.
-*/
-#if( !defined( offsetof ) )
-	#define offsetof( TYPE, FIELD )		( (size_t)(uintptr_t)( &( (TYPE *) 0 )->FIELD ) )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	sizeof_element
-	@abstract	Determines the size of an array element.
-*/
-#define	sizeof_element( X )		sizeof( X[ 0 ] )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	sizeof_field
-	@abstract	Determines the size of a field of a type.
-*/
-#define	sizeof_field( TYPE, FIELD )		sizeof( ( ( (TYPE *) 0 )->FIELD ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	sizeof_string
-	@abstract	Determines the size of a constant C string, excluding the null terminator.
-*/
-#define	sizeof_string( X )		( sizeof( (X) ) - 1 )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	AbsoluteDiff
-	@abstract	Returns the absolute value of the difference between two values.
-*/
-#define	AbsoluteDiff( X, Y )		( ( (X) < (Y) ) ? ( (Y) - (X) ) : ( (X) - (Y) ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	AbsoluteValue
-	@abstract	Returns the absolute value of a value.
-*/
-#define	AbsoluteValue( X )		( ( (X) < 0 ) ? -(X) : (X) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	RoundDown
-	@abstract	Rounds VALUE down to the nearest multiple of MULTIPLE.
-*/
-#define	RoundDown( VALUE, MULTIPLE )		( ( (VALUE) / (MULTIPLE) ) * (MULTIPLE) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	RoundUp
-	@abstract	Rounds VALUE up to the nearest multiple of MULTIPLE.
-*/
-#define	RoundUp( VALUE, MULTIPLE )		( ( ( (VALUE) + ( (MULTIPLE) - 1 ) ) / (MULTIPLE) ) * (MULTIPLE) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	RoundTo
-	@abstract	Rounds a value to a specific precision.
-	@discussion
-	
-	This can round to any arbitrary precision. To round to a specific number of decimal digits, use a precision that is 
-	pow( 10, -digits ). For example, for 2 decimal places, pow( 10, -2 ) -> .01 and RoundTo( 1.234, .01 ) -> 1.23. This
-	can also be used to round to other precisions, such as 1/8: RoundTo( 1.3, 1.0 / 8.0 ) -> 1.25.
-*/
-#define RoundTo( VALUE, PRECISION )		( floor( ( (VALUE) / (PRECISION) ) + 0.5 ) * (PRECISION) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	IsAligned
-	@abstract	Returns non-zero if X is aligned to a Y byte boundary and 0 if not. Y must be a power of 2.
-*/
-#define	IsAligned( X, Y )		( ( (X) & ( (Y) - 1 ) ) == 0 )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	IsFieldAligned
-	@abstract	Returns non-zero if FIELD of type TYPE is aligned to a Y byte boundary and 0 if not. Y must be a power of 2.
-*/
-#define	IsFieldAligned( X, TYPE, FIELD, Y )		IsAligned( ( (uintptr_t)(X) ) + offsetof( TYPE, FIELD ), (Y) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	PtrsOverlap
-	@abstract	Returns true if the two ptr/len pairs overlap each other.
-*/
-#define	PtrsOverlap( PTR1, LEN1, PTR2, LEN2 ) \
-	( !( ( ( ( (uintptr_t)(PTR1) ) + (LEN1) )	<=   ( (uintptr_t)(PTR2) ) ) || \
-	       ( ( (uintptr_t)(PTR1) )				>= ( ( (uintptr_t)(PTR2) ) + (LEN2) ) ) ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	IsPtrAligned
-	@abstract	Returns non-zero if PTR is aligned to a Y byte boundary and 0 if not. Y must be a power of 2.
-*/
-#define	IsPtrAligned( PTR, Y )		( ( ( (uintptr_t)(PTR) ) & ( (Y) - 1 ) ) == 0 )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	AlignDown
-	@abstract	Aligns X down to a Y byte boundary. Y must be a power of 2.
-*/
-#define	AlignDown( X, Y )		( (X) & ~( (Y) - 1 ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	AlignUp
-	@abstract	Aligns X up to a Y byte boundary. Y must be a power of 2.
-*/
-#define	AlignUp( X, Y )		( ( (X) + ( (Y) - 1 ) ) & ~( (Y) - 1 ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	AlignedBuffer
-	@abstract	Specifies a buffer of a specific number of bytes that is aligned to the strictest C alignment.
-	@discussion
-	
-	This is useful for things like defining a buffer on the stack that can be cast to structures that may need alignment.
-	For example, the following allocates a 128 byte buffer on the stack that is safe to cast as a uint64_t:
-	
-	AlignedBuffer( 128 )		buf;
-	uint64_t *					ptr;
-	
-	ptr = (uint64_t *) &buf; // This is safe because the buffer is guaranteed to be aligned for the largest type.
-*/
-#define	AlignedBuffer( SIZE ) \
-	union \
-	{ \
-		uintmax_t		align; \
-		uint8_t			buf[ SIZE ]; \
-	}
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@group		Logical and arithmetic shifts on signed values.
-	@abstract	These work around undefined behavior in C for shifts of signed values.
-	
-	ASR = Arithmetic Shift Right. The sign bit is replicated to fill in vacant positions (e.g. 0x80 >> 1 = 0xC0).
-	LSR = Logical Shift Right. Zero bits fill in vacant positions (e.g. 0x80 >> 1 = 0x40).
-	X is the value and N is the number of bits to shift. The return value contains the result.
-	
-	Warning: shifting a signed value to the right is not the same as dividing because shifts round down instead of 
-	toward zero so -1 >> 1 = -1 instead of 0. If you care about the low bit then you'll need something better.
-*/
-#define HighOnes32( N )		( ~( (uint32_t) 0 ) << ( 32 - (N) ) )
-#define HighOnes64( N )		( ~( (uint64_t) 0 ) << ( 64 - (N) ) )
-
-#define LSR32( X, N )		( (int32_t)(   ( (uint32_t)(X) ) >> (N) ) )
-#define ASR32( X, N )		( (int32_t)( ( ( (uint32_t)(X) ) >> (N) ) ^ ( ( ( (int32_t)(X) ) < 0 ) ? HighOnes32( (N) ) : 0 ) ) )
-
-#define LSR64( X, N )		( (int64_t)( (   (uint64_t)(X) ) >> (N) ) )
-#define ASR64( X, N )		( (int64_t)( ( ( (uint64_t)(X) ) >> (N) ) ^ ( ( ( (int64_t)(X) ) < 0 ) ? HighOnes64( (N) ) : 0 ) ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@group		BitRotates
-	@abstract	Rotates X COUNT bits to the left or right.
-*/
-#define ROTL( X, N, SIZE )			( ( (X) << (N) ) | ( (X) >> ( (SIZE) - N ) ) )
-#define ROTR( X, N, SIZE )			( ( (X) >> (N) ) | ( (X) << ( (SIZE) - N ) ) )
-
-#define ROTL32( X, N )				ROTL( (X), (N), 32 )
-#define ROTR32( X, N )				ROTR( (X), (N), 32 )
-
-#define ROTL64( X, N )				ROTL( (X), (N), 64 )
-#define ROTR64( X, N )				ROTR( (X), (N), 64 )
-
-#define	RotateBitsLeft( X, N )		ROTL( (X), (N), sizeof( (X) ) * 8 )
-#define	RotateBitsRight( X, N )		ROTR( (X), (N), sizeof( (X) ) * 8 )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	IsOdd
-	@abstract	Returns non-zero if the value is odd and 0 if it is even.
-*/
-#define	IsOdd( X )			( ( (X) & 1 ) != 0 )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	IsEven
-	@abstract	Returns non-zero if the value is even and 0 if it is odd.
-*/
-#define	IsEven( X )			( ( (X) & 1 ) == 0 )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	IsPowerOf2
-	@abstract	Returns non-zero if the value is a power of 2 and 0 if it is not. 0 and 1 are not considered powers of 2.
-*/
-#define	IsPowerOf2( X )		( ( (X) > 1 ) && ( ( (X) & ( (X) - 1 ) ) == 0 ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	MinPowerOf2BytesForValue
-	@abstract	Returns the minimum number of power-of-2 bytes needed to hold a specific value.
-*/
-#define MinPowerOf2BytesForValue( X )	( \
-	( (X) & UINT64_C( 0xFFFFFFFF00000000 ) ) ? 8 : \
-	( (X) & UINT64_C( 0x00000000FFFF0000 ) ) ? 4 : \
-	( (X) & UINT64_C( 0x000000000000FF00 ) ) ? 2 : \
-											   1 )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	IsMultipleOf
-	@abstract	Returns non-zero if X is a multiple of Y.
-*/
-#define IsMultipleOf( X, Y )		( ( ( (X) / (Y) ) * (Y) ) == (X) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	Min
-	@abstract	Returns the lesser of X and Y.
-*/
-#if( !defined( Min ) )
-	#define	Min( X, Y )		( ( (X) < (Y) ) ? (X) : (Y) )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	Max
-	@abstract	Returns the greater of X and Y.
-*/
-#if( !defined( Max ) )
-	#define	Max( X, Y )		( ( (X) > (Y) ) ? (X) : (Y) )
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	Clamp
-	@abstract	Clamps a value to no less than "a" and no greater than "b".
-*/
-#define Clamp( x, a, b )		Max( (a), Min( (b), (x) ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	increment_wrap
-	@abstract	Increments VAR and if it wraps to 0, set VAR to WRAP.
-*/
-#define	increment_wrap( VAR, WRAP )		do { ++(VAR); if( (VAR) == 0 ) { (VAR) = (WRAP); } } while( 0 )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	increment_saturate
-	@abstract	Increments VAR unless doing so would cause it to exceed MAX.
-*/
-#define	increment_saturate( VAR, MAX )		do { if( (VAR) < (MAX) ) { ++(VAR); } } while( 0 )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	add_saturate
-	@abstract	Adds VALUE to VAR. If the result would go over MAX, VAR is capped to MAX.
-*/
-#define	add_saturate( VAR, VALUE, MAX ) \
-	do \
-	{ \
-		if( (VAR) < ( (MAX) - (VALUE) ) ) \
-		{ \
-			(VAR) += (VALUE); \
-		} \
-		else \
-		{ \
-			(VAR) = (MAX); \
-		} \
-		\
-	}	while( 0 )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	median_of_3
-	@abstract	Returns the median (middle) value given 3 values.
-*/
-#define median_of_3( x0, x1, x2 ) \
-	( ( (x0) > (x1) ) ? \
-		( (x1) > (x2) ) ? (x1) : ( (x2) > (x0) ) ? (x0) : (x2) : \
-		( (x1) < (x2) ) ? (x1) : ( (x2) < (x0) ) ? (x0) : (x2) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	median_of_5
-	@abstract	Returns the median (middle) value given 5 values.
-*/
-#define median_of_5( a, b, c, d, e ) \
-		( (b) < (a) ? (d) < (c) ? (b) < (d) ? (a) < (e) ? (a) < (d) ? (e) < (d) ? (e) \
-		: (d) \
-		: (c) < (a) ? (c) : (a) \
-		: (e) < (d) ? (a) < (d) ? (a) : (d) \
-		: (c) < (e) ? (c) : (e) \
-		: (c) < (e) ? (b) < (c) ? (a) < (c) ? (a) : (c) \
-		: (e) < (b) ? (e) : (b) \
-		: (b) < (e) ? (a) < (e) ? (a) : (e) \
-		: (c) < (b) ? (c) : (b) \
-		: (b) < (c) ? (a) < (e) ? (a) < (c) ? (e) < (c) ? (e) : (c) \
-		: (d) < (a) ? (d) : (a) \
-		: (e) < (c) ? (a) < (c) ? (a) : (c) \
-		: (d) < (e) ? (d) : (e) \
-		: (d) < (e) ? (b) < (d) ? (a) < (d) ? (a) : (d) \
-		: (e) < (b) ? (e) : (b) \
-		: (b) < (e) ? (a) < (e) ? (a) : (e) \
-		: (d) < (b) ? (d) : (b) \
-		: (d) < (c) ? (a) < (d) ? (b) < (e) ? (b) < (d) ? (e) < (d) ? (e) : (d) \
-		: (c) < (b) ? (c) : (b) \
-		: (e) < (d) ? (b) < (d) ? (b) : (d) \
-		: (c) < (e) ? (c) : (e) \
-		: (c) < (e) ? (a) < (c) ? (b) < (c) ? (b) : (c) \
-		: (e) < (a) ? (e) : (a) \
-		: (a) < (e) ? (b) < (e) ? (b) : (e) \
-		: (c) < (a) ? (c) : (a) \
-		: (a) < (c) ? (b) < (e) ? (b) < (c) ? (e) < (c) ? (e) : (c) \
-		: (d) < (b) ? (d) : (b) \
-		: (e) < (c) ? (b) < (c) ? (b) : (c) \
-		: (d) < (e) ? (d) : (e) \
-		: (d) < (e) ? (a) < (d) ? (b) < (d) ? (b) : (d) \
-		: (e) < (a) ? (e) : (a) \
-		: (a) < (e) ? (b) < (e) ? (b) : (e) \
-		: (d) < (a) ? (d) : (a) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	append_decimal_string
-	@abstract	Appends a decimal string to a buffer.
-	
-	@param		X		Unsigned decimal number to convert to a string. It will be modified by this macro.
-	@param		DST		Pointer to write string to. Will point to end of string on return.
-	
-	@discussion
-	
-	Example usage:
-	
-	char		str[ 32 ];
-	char *		dst;
-	int			x;
-	
-	strcpy( str, "test" );
-	dst = str + 4;
-	
-	x = 1234;
-	append_decimal_string( x, dst );
-	strcpy( dst, "end" );
-	
-	... str is "test1234end".
-*/
-#define	append_decimal_string( X, DST ) \
-	do \
-	{ \
-		char		_adsBuf[ 32 ]; \
-		char *		_adsPtr; \
-		\
-		_adsPtr = _adsBuf; \
-		do \
-		{ \
-			*_adsPtr++ = (char)( '0' + ( (X) % 10 ) ); \
-			(X) /= 10; \
-		\
-		}	while( (X) > 0 ); \
- 		\
-		while( _adsPtr > _adsBuf ) \
-		{ \
-			*(DST)++ = *( --_adsPtr ); \
-		} \
-		\
-	}	while( 0 )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	BitArray
-	@abstract	Macros for working with bit arrays.
-	@discussion
-	
-	This treats bit numbers starting from the left so bit 0 is 0x80 in byte 0, bit 1 is 0x40 in bit 0, 
-	bit 8 is 0x80 in byte 1, etc. For example, the following ASCII art shows how the bits are arranged:
-	
-			                     1 1 1 1 1 1 1 1 1 1 2 2 2 2 
-	Bit		 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 
-			+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-			|    x          |x              |  x           x| = 0x20 0x80 0x41 (bits 2, 8, 17, and 23).
-			+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-	Byte	0				1				2
-*/
-#define BitArray_MinBytes( ARRAY, N_BYTES )			memrlen( (ARRAY), (N_BYTES) )
-#define BitArray_MaxBytes( BITS )					( ( (BITS) + 7 ) / 8 )
-#define BitArray_MaxBits( ARRAY_BYTES )				( (ARRAY_BYTES) * 8 )
-#define BitArray_Clear( ARRAY_PTR, ARRAY_BYTES )	memset( (ARRAY_PTR), 0, (ARRAY_BYTES) );
-#define BitArray_GetBit( PTR, LEN, BIT ) \
-	( ( (BIT) < BitArray_MaxBits( (LEN) ) ) && ( (PTR)[ (BIT) / 8 ] & ( 1 << ( 7 - ( (BIT) & 7 ) ) ) ) )
-#define BitArray_SetBit( ARRAY, BIT )				( (ARRAY)[ (BIT) / 8 ] |=  ( 1 << ( 7 - ( (BIT) & 7 ) ) ) )
-#define BitArray_ClearBit( ARRAY, BIT )				( (ARRAY)[ (BIT) / 8 ] &= ~( 1 << ( 7 - ( (BIT) & 7 ) ) ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	InsertBits
-	@abstract	Inserts BITS (both 0 and 1 bits) into X, controlled by MASK and SHIFT, and returns the result.
-	@discussion
-	
-	MASK is the bitmask of the bits in the final position.
-	SHIFT is the number of bits to shift left for 1 to reach the first bit position of MASK.
-	
-	For example, if you wanted to insert 0x3 into the leftmost 4 bits of a 32-bit value:
-	
-	InsertBits( 0, 0x3, 0xF0000000U, 28 ) == 0x30000000
-*/
-#define	InsertBits( X, BITS, MASK, SHIFT )		( ( (X) & ~(MASK) ) | ( ( (BITS) << (SHIFT) ) & (MASK) ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	ExtractBits
-	@abstract	Extracts bits from X, controlled by MASK and SHIFT, and returns the result.
-	@discussion
-	
-	MASK is the bitmask of the bits in the final position.
-	SHIFT is the number of bits to shift right to right justify MASK.
-	
-	For example, if you had a 32-bit value (e.g. 0x30000000) wanted the left-most 4 bits (e.g. 3 in this example):
-	
-	ExtractBits( 0x30000000U, 0xF0000000U, 28 ) == 0x3
-*/
-#define	ExtractBits( X, MASK, SHIFT )			( ( (X) >> (SHIFT) ) & ( (MASK) >> (SHIFT) ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	SetOrClearBits
-	@abstract	Sets bits if the test is non-zero or clears bits if the test is zero.
-	@discussion
-	
-	int		x;
-	
-	SetOrClearBits( &x, 0x7, true  ); // Sets   bits 0, 1, 2
-	SetOrClearBits( &x, 0x7, false ); // Clears bits 0, 1, 2
-*/
-#define SetOrClearBits( VALUE_PTR, BITS, TEST ) \
-	do { *(VALUE_PTR) = (TEST) ? ( *(VALUE_PTR) | (BITS) ) : ( *(VALUE_PTR) & ~(BITS) ); } while( 0 )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	Stringify
-	@abstract	Stringify's an expression.
-	@discussion
-	
-	Stringify macros to process raw text passed via -D options to C string constants. The double-wrapping is necessary 
-	because the C preprocessor doesn't perform its normal argument expansion pre-scan with stringified macros so the 
-	-D macro needs to be expanded once via the wrapper macro then stringified so the raw text is stringified. Otherwise, 
-	the replacement value would be used instead of the symbolic name (only for preprocessor symbols like #defines).
-	
-	For example:
-	
-		#define	kMyConstant		1
-		
-		printf( "%s", Stringify( kMyConstant ) );			// Prints "kMyConstant"
-		printf( "%s", StringifyExpansion( kMyConstant ) );	// Prints "1"
-		
-	Non-preprocessor symbols do not have this issue. For example:
-	
-		enum
-		{
-			kMyConstant = 1
-		};
-		
-		printf( "%s", Stringify( kMyConstant ) );			// Prints "kMyConstant"
-		printf( "%s", StringifyExpansion( kMyConstant ) );	// Prints "kMyConstant"
-	
-	See <http://gcc.gnu.org/onlinedocs/cpp/Argument-Prescan.html> for more info on C preprocessor pre-scanning.
-*/
-#define	Stringify( X )				# X
-#define	StringifyExpansion( X )		Stringify( X )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	Forget macros
-	@abstract	These take a pointer and if what it points to is valid, it gets rid of it and marks it invalid.
-*/
-#define	ForgetCustom( X, DELETER )				do { if( *(X) ) { DELETER( *(X) ); *(X) = NULL; } } while( 0 )
-#define ForgetCustomEx( X, STOPPER, DELETER )	do { if( *(X) ) { STOPPER( *(X) ); DELETER( *(X) ); *(X) = NULL; } } while( 0 )
-
-#define AudioConverterForget( X )		ForgetCustom( X, AudioConverterDispose )
-#define	dispatch_forget( X )			ForgetCustom( X, dispatch_release )
-#define	DNSServiceForget( X )			ForgetCustom( X, DNSServiceRefDeallocate )
-#define	ForgetBlock( X )				ForgetCustom( X, Block_release )
-#define	ForgetCF( X )					ForgetCustom( X, CFRelease )
-#define	ForgetIOKitKernelObject( X )	do { if( *(X) ) { ( *(X) )->release(); *(X) = NULL; } } while( 0 )
-#define	ForgetMem( X )					ForgetCustom( X, free_compat )
-#define	ForgetObjectiveCObject( X )		do { [*(X) release]; *(X) = nil; } while( 0 )
-#define	ForgetVxSem( X )				do { if( *(X) ) { semDelete( *(X) ); *(X) = 0; } } while( 0 )
-#define	ForgetWinHandle( X )			do { if( *(X) ) { CloseHandle( *(X) ); *(X) = 0; } } while( 0 )
-#define	ForgetWinRegKey( X )			ForgetCustom( X, RegCloseKey )
-#define	IONotificationPortForget( X )	ForgetCustom( X, IONotificationPortDestroy )
-#define SRP_forget( X )					ForgetCustom( X, SRP_free )
-#define SRP_cstr_forget( X )			ForgetCustom( X, cstr_free )
-#define	xpc_forget( X )					ForgetCustom( X, xpc_release )
-
-#define dispatch_socket_forget( SOURCE, SOCK_PTR, SUSPENDED ) \
-	do \
-	{ \
-		if( (SOURCE) ) \
-		{ \
-			dispatch_source_cancel( (SOURCE) ); \
-			if( (SUSPENDED) ) dispatch_resume( (SOURCE) ); \
-			dispatch_release( (SOURCE) ); \
-		} \
-		else \
-		{ \
-			ForgetSocket( (SOCK_PTR) ); \
-		} \
-		\
-	}	while( 0 )
-
-#define	dispatch_source_forget( X ) \
-	do \
-	{ \
-		if( *(X) ) \
-		{ \
-			dispatch_source_cancel( *(X) ); \
-			dispatch_release( *(X) ); \
-			*(X) = NULL; \
-		} \
-		\
-	}	while( 0 )
-
-#define	dispatch_source_forget_ex( SOURCE_PTR, SUSPENDED_PTR ) \
-	do \
-	{ \
-		if( *(SOURCE_PTR) ) \
-		{ \
-			dispatch_source_cancel( *(SOURCE_PTR) ); \
-			if( (SUSPENDED_PTR) && *(SUSPENDED_PTR) ) \
-			{ \
-				dispatch_resume( *(SOURCE_PTR) ); \
-				*(SUSPENDED_PTR) = false; \
-			} \
-			dispatch_release( *(SOURCE_PTR) ); \
-			*(SOURCE_PTR) = NULL; \
-		} \
-		\
-	}	while( 0 )
-
-#define dispatch_resume_if_suspended( SOURCE, SUSPENDED_PTR ) \
-	do \
-	{ \
-		if( *(SUSPENDED_PTR) ) \
-		{ \
-			*(SUSPENDED_PTR) = false; \
-			dispatch_resume( (SOURCE) ); \
-		} \
-		\
-	}	while( 0 )
-
-#define dispatch_suspend_if_resumed( SOURCE, SUSPENDED_PTR ) \
-	do \
-	{ \
-		if( !*(SUSPENDED_PTR) ) \
-		{ \
-			*(SUSPENDED_PTR) = true; \
-			dispatch_suspend( (SOURCE) ); \
-		} \
-		\
-	}	while( 0 )
-
-#define	ForgetANSIFile( X ) \
-	do \
-	{ \
-		if( *(X) ) \
-		{ \
-			OSStatus		ForgetANSIFileErr; \
-			\
-			ForgetANSIFileErr = fclose( *(X) ); \
-			ForgetANSIFileErr = map_noerr_errno( ForgetANSIFileErr ); \
-			check_noerr( ForgetANSIFileErr ); \
-			*(X) = NULL; \
-		} \
- 		\
-	}	while( 0 )
-
-#define ForgetFD( X ) \
-	do \
-	{ \
-		if( IsValidFD( *(X) ) ) \
-		{ \
-			OSStatus		ForgetFDErr; \
-			\
-			ForgetFDErr = CloseFD( *(X) ); \
-			ForgetFDErr = map_global_noerr_errno( ForgetFDErr ); \
-			check_noerr( ForgetFDErr ); \
-			*(X) = kInvalidFD; \
-		} \
-		\
-	}	while( 0 )
-
-#define	notify_forget( X ) \
-	do \
-	{ \
-		if( *(X) != -1 ) \
-		{ \
-			OSStatus		notify_forget_err_; \
-			\
-			notify_forget_err_ = notify_cancel( *(X) ); \
-			check_noerr( notify_forget_err_ ); \
-			*(X) = -1; \
-		} \
-		\
-	}	while( 0 )
-
-#define pthread_cond_forget( X ) \
-	do \
-	{ \
-		if( *(X) ) \
-		{ \
-			int		pthread_cond_forget_err_; \
-			\
-			DEBUG_USE_ONLY( pthread_cond_forget_err_ ); \
-			\
-			pthread_cond_forget_err_ = pthread_cond_destroy( *(X) ); \
-			check_noerr( pthread_cond_forget_err_ ); \
-			*(X) = NULL; \
-		} \
-		\
-	}	while( 0 )
-
-#define pthread_mutex_forget( X ) \
-	do \
-	{ \
-		if( *(X) ) \
-		{ \
-			int		pthread_mutex_forget_err_; \
-			\
-			DEBUG_USE_ONLY( pthread_mutex_forget_err_ ); \
-			\
-			pthread_mutex_forget_err_ = pthread_mutex_destroy( *(X) ); \
-			check_noerr( pthread_mutex_forget_err_ ); \
-			*(X) = NULL; \
-		} \
-		\
-	}	while( 0 )
-
-#define ForgetSocket( X ) \
-	do \
-	{ \
-		if( IsValidSocket( *(X) ) ) \
-		{ \
-			OSStatus		ForgetSocketErr; \
-			\
-			ForgetSocketErr = close_compat( *(X) ); \
-			ForgetSocketErr = map_socket_noerr_errno( *(X), ForgetSocketErr ); \
-			check_noerr( ForgetSocketErr ); \
-			*(X) = kInvalidSocketRef; \
-		} \
-		\
-	}	while( 0 )
-
-#define IOObjectForget( X ) \
-	do \
-	{ \
-		if( *(X) != IO_OBJECT_NULL ) \
-		{ \
-			IOReturn		IOObjectForgetErr; \
-			\
-			IOObjectForgetErr = IOObjectRelease( *(X) ); \
-			check_noerr( IOObjectForgetErr ); \
-			*(X) = IO_OBJECT_NULL; \
-		} \
-		\
-	}	while( 0 )
-
-#define	xpc_connection_forget( X ) \
-	do \
-	{ \
-		if( *(X) ) \
-		{ \
-			xpc_connection_cancel( *(X) ); \
-			xpc_release( *(X) ); \
-			*(X) = NULL; \
-		} \
-		\
-	}	while( 0 )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	Replace macros
-	@abstract	These retain/copy/etc the new thing and release/free/etc the old thing (if the old thing is valid).
-*/
-#define ReplaceBlock( BLOCK_PTR, NEW_BLOCK ) \
-	do \
-	{ \
-		__typeof( (NEW_BLOCK) )		ReplaceBlock_TempBlock = (NEW_BLOCK); \
-		\
-		if( ReplaceBlock_TempBlock ) \
-		{ \
-			ReplaceBlock_TempBlock = Block_copy( ReplaceBlock_TempBlock ); \
-			check( ReplaceBlock_TempBlock ); \
-		} \
-		if( *(BLOCK_PTR) ) Block_release( *(BLOCK_PTR) ); \
-		*(BLOCK_PTR) = ReplaceBlock_TempBlock; \
-		\
-	}	while( 0 )
-
-#define ReplaceCF( OBJECT_PTR, NEW_OBJECT ) \
-	do \
-	{ \
-		CFTypeRef *		ReplaceCF_objectPtr = (CFTypeRef *)(OBJECT_PTR); \
-		CFTypeRef		ReplaceCF_oldObject = *ReplaceCF_objectPtr; \
-		CFTypeRef		ReplaceCF_newObject =  (NEW_OBJECT); \
-		\
-		if( ReplaceCF_newObject ) CFRetain( ReplaceCF_newObject ); \
-		*ReplaceCF_objectPtr = ReplaceCF_newObject; \
-		if( ReplaceCF_oldObject ) CFRelease( ReplaceCF_oldObject ); \
-		\
-	}	while( 0 )
-
-#define ReplaceDispatchQueue( QUEUE_PTR, NEW_QUEUE ) \
-	do \
-	{ \
-		dispatch_queue_t		ReplaceDispatchQueue_TempQueue = (NEW_QUEUE); \
-		\
-		if( !ReplaceDispatchQueue_TempQueue ) ReplaceDispatchQueue_TempQueue = dispatch_get_main_queue(); \
-		dispatch_retain( ReplaceDispatchQueue_TempQueue ); \
-		if( *(QUEUE_PTR) ) dispatch_release( *(QUEUE_PTR) ); \
-		*(QUEUE_PTR) = ReplaceDispatchQueue_TempQueue; \
-		\
-	}	while( 0 )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	MemEqual
-	@abstract	Returns non-zero if two ptr/len pairs are equal and 0 otherwise.
-*/
-
-#define MemEqual( PTR1, LEN1, PTR2, LEN2 ) \
-	( ( ( LEN1 ) == ( LEN2 ) ) && ( memcmp( ( PTR1 ), ( PTR2 ), ( LEN1 ) ) == 0 ) )
-
-#define MemIEqual( PTR1, LEN1, PTR2, LEN2 ) \
-	( ( ( LEN1 ) == ( LEN2 ) ) && ( memicmp( ( PTR1 ), ( PTR2 ), ( LEN1 ) ) == 0 ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	DECLARE_QSORT_FUNC / DEFINE_QSORT_FUNC
-	@abstract	Declares/defines a qsort-compatible sort function for numeric types.
-	@abstract
-	
-	Use it like this in your header file:
-	
-		DECLARE_QSORT_NUMERIC_COMPARATOR( cmp_double );
-	
-	Then in your source file:
-	
-		DEFINE_QSORT_NUMERIC_COMPARATOR( double, cmd_double );
-	
-	Then to use it in code:
-	
-		qsort( array, count, elementSize, cmd_double );
-*/
-
-#define DECLARE_QSORT_NUMERIC_COMPARATOR( NAME )	int	NAME( const void *a, const void *b )
-
-#define DEFINE_QSORT_NUMERIC_COMPARATOR( TYPE, NAME ) \
-	int	NAME( const void *a, const void *b ) \
-	{ \
-		TYPE const		aa = *( (const TYPE *) a ); \
-		TYPE const		bb = *( (const TYPE *) b ); \
-		\
-		return( ( aa > bb ) - ( aa < bb ) ); \
-	}
-
-DECLARE_QSORT_NUMERIC_COMPARATOR( qsort_cmp_int8 );
-DECLARE_QSORT_NUMERIC_COMPARATOR( qsort_cmp_uint8 );
-DECLARE_QSORT_NUMERIC_COMPARATOR( qsort_cmp_int16 );
-DECLARE_QSORT_NUMERIC_COMPARATOR( qsort_cmp_uint16 );
-DECLARE_QSORT_NUMERIC_COMPARATOR( qsort_cmp_int32 );
-DECLARE_QSORT_NUMERIC_COMPARATOR( qsort_cmp_uint32 );
-DECLARE_QSORT_NUMERIC_COMPARATOR( qsort_cmp_int64 );
-DECLARE_QSORT_NUMERIC_COMPARATOR( qsort_cmp_uint64 );
-DECLARE_QSORT_NUMERIC_COMPARATOR( qsort_cmp_float );
-DECLARE_QSORT_NUMERIC_COMPARATOR( qsort_cmp_double );
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	HAS_FEATURE
-	@abstract	Performs a compile-time check for a feature flag and fails to compile if the feature is not defined.
-	@discussion
-	
-	This can be used to detect if a feature is defined to 1 (feature enabled) or defined 0 (feature not enabled) or
-	it fails to compile if the feature flag is not defined at all. This can help catch errors when you're testing
-	for a feature, but typed it wrong, forgot to include the right header file, or passed the wrong -D compile flags.
-	Here's how you use it:
-	
-	#if( HAS_FEATURE( COOL_FEATURE ) )
-		... code to relate to COOL_FEATURE.
-	#endif
-*/
-#define HAS_FEATURE_CAT( a, b )		a ## b 
-#define HAS_FEATURE_CAT2( a, b )	HAS_FEATURE_CAT( a, b ) 
-#define HAS_FEATURE_CHECK_0			1 
-#define HAS_FEATURE_CHECK_1			1 
-#define HAS_FEATURE( X )			( X / HAS_FEATURE_CAT2( HAS_FEATURE_CHECK_, X ) ) 
-
-#if 0
-#pragma mark == Fixed-Point Math ==
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@group		Fixed-point math
-	@abstract	Macros to work with Q32.32 numbers. <http://en.wikipedia.org/wiki/Q_(number_format)>.
-	@discussion
-	
-	- Addition and subtraction with other Q32.32 numbers can use the normal + and - operators, respectively.
-	- Multiplication by other Q32.32 numbers needs to use the normal * then right shift the result by 32.
-	  Warning: Due to the lack of a standard int128_t, multiplication will overflow if either value is >= 1 (and other cases).
-	- Negation can use the normal unary - operator.
-	- Negative numbers can be detected using a normal < 0 check.
-	- Setting to 0 can be by simply assigning 0.
-*/
-	typedef int32_t		Q16x16;
-	typedef int64_t		Q32x32;
-
-#define kQ16_1pt0		0x00010000 // 1.0 in 16.16 fixed format.
-#define kQ16_0pt5		0x00008000 // 0.5 in 16.16 fixed format.
-
-#define FloatToQ32x32( X )					( (int64_t)( (X) * ( (double) UINT32_C( 0xFFFFFFFF ) ) ) )
-#define Q32x32ToFloat( X )					( ( (double)(X) ) / ( (double)( UINT32_C( 0xFFFFFFFF ) ) ) )
-
-#define Q32x32_Integer( a )					( ( (Q32x32)(a) ) << 32 )
-
-#define Q32x32_GetInteger( x )				( (int32_t)( ( (x) < 0 ) ? ( -( -(x) >> 32 ) ) : ( (x) >> 32 ) ) )
-#define Q32x32_SetInteger( x, a )			( (x) = ( (Q32x32)(a) ) << 32 )
-#define Q32x32_GetFraction( x )				( (uint32_t)( (x) & UINT32_C( 0xFFFFFFFF ) ) )
-
-#define Q32x32_AddInteger( x, a )			( (x) += ( ( (Q32x32)(a) ) << 32 ) )
-#define Q32x32_MultiplyByInteger( x, a )	( (x) *= (a) )
-#define Q32x32_RightShift( x, a ) \
-	do \
-	{ \
-		if( (x) < 0 )	(x) = -( -(x) >> (a) ); \
-		else			(x) =     (x) >> (a); \
-	\
-	}	while ( 0 )
-
-#if 0
-#pragma mark -
-#pragma mark == Modular Math ==
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@group		Modular math
-	@abstract	AKA Serial Number Arithmetic per RFC 1982). See <http://en.wikipedia.org/wiki/Serial_number_arithmetic>.
-	@discussion
-	
-	EQ:   Returns non-zero if A == B.
-	LT:   Returns non-zero if A <  B.
-	LE:   Returns non-zero if A <= B.
-	GT:   Returns non-zero if A >  B.
-	GE:   Returns non-zero if A >= B.
-	Cmp:  Returns 0 if A == B, < 0 if A < B, and > 0 if A > B. Do not compare against -1 or 1...use < 0 or > 0, respectively.
-	Diff: Returns the absolute value of the difference between A and B (e.g. Mod8_Diff( 5, 10 ) == 5 and Mod8_Diff( 10, 5 ) == 5).
-*/
-
-// 8-bit modular math. Note: these only work if the difference is less than 2^7.
-
-#if( !defined( Mod8_EQ ) )
-	#define	Mod8_EQ( A, B )			( ( (uint8_t)(A) ) == ( (uint8_t)(B) ) )
-	#define	Mod8_LT( A, B )			( (int8_t)( ( (uint8_t)(A) ) - ( (uint8_t)(B) ) ) <   0 )
-	#define	Mod8_LE( A, B )			( (int8_t)( ( (uint8_t)(A) ) - ( (uint8_t)(B) ) ) <=  0 )
-	#define	Mod8_GT( A, B )			( (int8_t)( ( (uint8_t)(A) ) - ( (uint8_t)(B) ) ) >   0 )
-	#define	Mod8_GE( A, B )			( (int8_t)( ( (uint8_t)(A) ) - ( (uint8_t)(B) ) ) >=  0 )
-	#define	Mod8_Cmp( A, B )		( (int8_t)( ( (uint8_t)(A) ) - ( (uint8_t)(B) ) ) )
-	#define	Mod8_Diff( A, B )		( Mod8_LT( (A), (B) ) ? ( (B) - (A) ) : ( (A) - (B) ) )
-#endif
-
-// 16-bit modular math. Note: these only work if the difference is less than 2^15.
-
-#if( !defined( Mod16_LT ) )
-	#define	Mod16_EQ( A, B )		( ( (uint16_t)(A) ) == ( (uint16_t)(B) ) )
-	#define	Mod16_LT( A, B )		( (int16_t)( ( (uint16_t)(A) ) - ( (uint16_t)(B) ) ) <   0 )
-	#define	Mod16_LE( A, B )		( (int16_t)( ( (uint16_t)(A) ) - ( (uint16_t)(B) ) ) <=  0 )
-	#define	Mod16_GT( A, B )		( (int16_t)( ( (uint16_t)(A) ) - ( (uint16_t)(B) ) ) >   0 )
-	#define	Mod16_GE( A, B )		( (int16_t)( ( (uint16_t)(A) ) - ( (uint16_t)(B) ) ) >=  0 )
-	#define	Mod16_Cmp( A, B )		( (int16_t)( ( (uint16_t)(A) ) - ( (uint16_t)(B) ) ) )
-	#define	Mod16_Diff( A, B )		( Mod16_LT( (A), (B) ) ? ( (B) - (A) ) : ( (A) - (B) ) )
-#endif
-
-// 32-bit modular math. Note: these only work if the difference is less than 2^31.
-
-#if( !defined( Mod32_LT ) )
-	#define	Mod32_EQ( A, B )		( ( (uint32_t)(A) ) == ( (uint32_t)(B) ) )
-	#define	Mod32_LT( A, B )		( (int32_t)( ( (uint32_t)(A) ) - ( (uint32_t)(B) ) ) <   0 )
-	#define	Mod32_LE( A, B )		( (int32_t)( ( (uint32_t)(A) ) - ( (uint32_t)(B) ) ) <=  0 )
-	#define	Mod32_GT( A, B )		( (int32_t)( ( (uint32_t)(A) ) - ( (uint32_t)(B) ) ) >   0 )
-	#define	Mod32_GE( A, B )		( (int32_t)( ( (uint32_t)(A) ) - ( (uint32_t)(B) ) ) >=  0 )
-	#define	Mod32_Cmp( A, B )		( (int32_t)( ( (uint32_t)(A) ) - ( (uint32_t)(B) ) ) )
-	#define	Mod32_Diff( A, B )		( Mod32_LT( (A), (B) ) ? ( (B) - (A) ) : ( (A) - (B) ) )
-#endif
-
-#if 0
-#pragma mark -
-#pragma mark == Booleans ==
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@typedef	bool
-	@abstract	Standardized boolean type. Built-in with C99 and C++, but emulated elsewhere.
-	@discussion
-	
-	C++ defines bool, true, and false. Metrowerks allows this to be controlled by the "bool" option though.
-	C99 defines __bool_true_false_are_defined when bool, true, and false are defined.
-	MacTypes.h defines Boolean, true, and false.
-	VxWorks rwos.h defines _RWOS_H_ and defines bool, true, and false if bool is not already defined.
-	
-	Note: The Metrowerks has to be in its own block because Microsoft Visual Studio .NET does not completely 
-	short-circuit and gets confused by the option( bool ) portion of the conditional.
-	
-	The moral the story is just don't use "bool" unless you know you're using C++ and never want compatibility with C 
-	code. Otherwise, it's just too much of a pain. There are also binary compatibility issues because bool may be a
-	different size in different environments. Use Boolean instead (provided in this file if needed and always 1 byte).
-*/
-#if( defined( __MWERKS__ ) )
-	
-	// Note: The following test is done on separate lines because CodeWarrior doesn't like it all on one line.
-	
-	#if( !__bool_true_false_are_defined && ( !defined( __cplusplus ) || !__option( bool ) ) )
-		#define	COMMON_SERVICES_NEEDS_BOOL		1
-	#else
-		#define	COMMON_SERVICES_NEEDS_BOOL		0
-	#endif
-	
-	// Workaround when building with CodeWarrior, but using the Apple stdbool.h header, which uses _Bool.
-	
-	#if( __bool_true_false_are_defined && !defined( __cplusplus ) && !__option( c9x ) )
-		#define _Bool	int
-	#endif
-	
-	// Workaround when building with CodeWarrior for C++ with bool disabled and using the Apple stdbool.h header, 
-	// which defines true and false to map to C++ true and false (which are not enabled). Serenity Now!
-	
-	#if( __bool_true_false_are_defined && defined( __cplusplus ) && !__option( bool ) )
-		#define	true	1
-		#define	false	0
-	#endif
-#else
-	#if( !defined( __cplusplus ) && !__bool_true_false_are_defined && !defined( bool ) && !defined( _RWOS_H_ ) && !defined( __IOKIT_IOTYPES_H ) )
-		#define COMMON_SERVICES_NEEDS_BOOL		1
-	#else
-		#define COMMON_SERVICES_NEEDS_BOOL		0
-	#endif
-#endif
-
-#if( COMMON_SERVICES_NEEDS_BOOL )
-	
-//		typedef int		bool;
-	
-	#define	bool	bool
-	
-	#if( !defined( true ) )
-		#define	true	1
-	#endif
-	
-	#if( !defined( false ) )
-		#define	false	0
-	#endif
-	
-	#define __bool_true_false_are_defined		1
-#endif
-
-// IOKit IOTypes.h typedef's bool if TYPE_BOOL is not defined so define it here to prevent redefinition by IOTypes.h.
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@typedef	Boolean
-	@abstract	Mac-style Boolean type. Emulated on non-Mac platforms.
-*/
-
-// MacTypes.h (Carbon) and OSTypes.h (IOKit) typedef Boolean so only typedef if those haven't been included.
-// Others use __BOOLEAN_DEFINED__ when they typedef Boolean so check for that and define it if we typedef it.
-
-#if( !defined( __MACTYPES__ ) && !defined( _OS_OSTYPES_H ) && !defined( __BOOLEAN_DEFINED__ ) )
-		typedef uint8_t		Boolean;
-	
-	#define	__BOOLEAN_DEFINED__		1
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	TYPE_LONGLONG_NATIVE
-	@abstract	Defines whether long long (or its equivalent) is natively supported or requires special libraries.
-*/
-#if( !defined( TYPE_LONGLONG_NATIVE ) )
-	#if( !defined( __GNUC__ ) || ( ( __GNUC__ > 2 ) || ( ( __GNUC__ == 2 ) && ( __GNUC_MINOR__ >= 9 ) ) ) || defined( __ghs__ ) )
-		#define	TYPE_LONGLONG_NATIVE			1
-	#else
-		#define	TYPE_LONGLONG_NATIVE			0
-	#endif
-#endif
-
-#if 0
-#pragma mark -
-#pragma mark == Errors ==
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@group		OSStatus
-	@abstract	Status Code
-*/
-		typedef int32_t			OSStatus;
-		
-		#define OSSTATUS_DEFINED		1
-
-#define kNoErr						0		//! No error occurred.
-#define kInProgressErr				1		//! Operation in progress.
-
-// Generic error codes are in the range -6700 to -6779.
-
-#define kGenericErrorBase			-6700	//! Starting error code for all generic errors.
-
-#define kUnknownErr					-6700	//! Unknown error occurred.
-#define kOptionErr					-6701	//! Option was not acceptable.
-#define kSelectorErr				-6702	//! Selector passed in is invalid or unknown.
-#define kExecutionStateErr			-6703	//! Call made in the wrong execution state (e.g. called at interrupt time).
-#define kPathErr					-6704	//! Path is invalid, too long, or otherwise not usable.
-#define kParamErr					-6705	//! Parameter is incorrect, missing, or not appropriate.
-#define kUserRequiredErr			-6706	//! User interaction is required.
-#define kCommandErr					-6707	//! Command invalid or not supported.
-#define kIDErr						-6708	//! Unknown, invalid, or inappropriate identifier.
-#define kStateErr					-6709	//! Not in appropriate state to perform operation.
-#define kRangeErr					-6710	//! Index is out of range or not valid.
-#define kRequestErr					-6711	//! Request was improperly formed or not appropriate.
-#define kResponseErr				-6712	//! Response was incorrect or out of sequence.
-#define kChecksumErr				-6713	//! Checksum does not match the actual data.
-#define kNotHandledErr				-6714	//! Operation was not handled (or not handled completely).
-#define kVersionErr					-6715	//! Version is not correct or not compatible.
-#define kSignatureErr				-6716	//! Signature did not match what was expected.
-#define kFormatErr					-6717	//! Unknown, invalid, or inappropriate file/data format.
-#define kNotInitializedErr			-6718	//! Action request before needed services were initialized.
-#define kAlreadyInitializedErr		-6719	//! Attempt made to initialize when already initialized.
-#define kNotInUseErr				-6720	//! Object not in use (e.g. cannot abort if not already in use).
-#define kAlreadyInUseErr			-6721	//! Object is in use (e.g. cannot reuse active param blocks).
-#define kTimeoutErr					-6722	//! Timeout occurred.
-#define kCanceledErr				-6723	//! Operation canceled (successful cancel).
-#define kAlreadyCanceledErr			-6724	//! Operation has already been canceled.
-#define kCannotCancelErr			-6725	//! Operation could not be canceled (maybe already done or invalid).
-#define kDeletedErr					-6726	//! Object has already been deleted.
-#define kNotFoundErr				-6727	//! Something was not found.
-#define kNoMemoryErr				-6728	//! Not enough memory was available to perform the operation.
-#define kNoResourcesErr				-6729	//! Resources unavailable to perform the operation.
-#define kDuplicateErr				-6730	//! Duplicate found or something is a duplicate.
-#define kImmutableErr				-6731	//! Entity is not changeable.
-#define kUnsupportedDataErr			-6732	//! Data is unknown or not supported.
-#define kIntegrityErr				-6733	//! Data is corrupt.
-#define kIncompatibleErr			-6734	//! Data is not compatible or it is in an incompatible format.
-#define kUnsupportedErr				-6735	//! Feature or option is not supported.
-#define kUnexpectedErr				-6736	//! Error occurred that was not expected.
-#define kValueErr					-6737	//! Value is not appropriate.
-#define kNotReadableErr				-6738	//! Could not read or reading is not allowed.
-#define kNotWritableErr				-6739	//! Could not write or writing is not allowed.
-#define	kBadReferenceErr			-6740	//! An invalid or inappropriate reference was specified.
-#define	kFlagErr					-6741	//! An invalid, inappropriate, or unsupported flag was specified.
-#define	kMalformedErr				-6742	//! Something was not formed correctly.
-#define	kSizeErr					-6743	//! Size was too big, too small, or not appropriate.
-#define	kNameErr					-6744	//! Name was not correct, allowed, or appropriate.
-#define	kNotPreparedErr				-6745	//! Device or service is not ready.
-#define	kReadErr					-6746	//! Could not read.
-#define	kWriteErr					-6747	//! Could not write.
-#define	kMismatchErr				-6748	//! Something does not match.
-#define	kDateErr					-6749	//! Date is invalid or out-of-range.
-#define	kUnderrunErr				-6750	//! Less data than expected.
-#define	kOverrunErr					-6751	//! More data than expected.
-#define	kEndingErr					-6752	//! Connection, session, or something is ending.
-#define	kConnectionErr				-6753	//! Connection failed or could not be established.
-#define	kAuthenticationErr			-6754	//! Authentication failed or is not supported.
-#define	kOpenErr					-6755	//! Could not open file, pipe, device, etc.
-#define	kTypeErr					-6756	//! Incorrect or incompatible type (e.g. file, data, etc.).
-#define	kSkipErr					-6757	//! Items should be or was skipped.
-#define	kNoAckErr					-6758	//! No acknowledge.
-#define	kCollisionErr				-6759	//! Collision occurred (e.g. two on bus at same time).
-#define	kBackoffErr					-6760	//! Backoff in progress and operation intentionally failed.
-#define	kAddressErr					-6761	//! Bad address or no acknowledge of address.
-#define	kInternalErr				-6762	//! An error internal to the implementation occurred.
-#define	kNoSpaceErr					-6763	//! Not enough space to perform operation.
-#define	kCountErr					-6764	//! Count is incorrect.
-#define	kEndOfDataErr				-6765	//! Reached the end of the data (e.g. recv returned 0).
-#define	kWouldBlockErr				-6766	//! Would need to block to continue (e.g. non-blocking read/write).
-#define	kLookErr					-6767	//! Special case that needs to be looked at (e.g. interleaved data).
-#define	kSecurityRequiredErr		-6768	//! Security is required for the operation (e.g. must use encryption).
-#define	kOrderErr					-6769	//! Order is incorrect.
-#define	kUpgradeErr					-6770	//! Must upgrade.
-#define kAsyncNoErr					-6771	//! Async operation successfully started and is now in progress.
-#define kDeprecatedErr				-6772	//! Operation or data is deprecated.
-#define kPermissionErr				-6773	//! Permission denied.
-
-#define kGenericErrorEnd			-6779	//! Last generic error code (inclusive)
-
-// NSErrorCreateWithOSStatus -- Creates an NSError object from an OSStatus, following the convention of nil == noErr.
-
-#define NSErrorCreateWithOSStatus( ERR ) \
-	( (ERR) ? [[NSError alloc] initWithDomain:NSOSStatusErrorDomain code:(ERR) userInfo:nil] : nil )
-
-#if 0
-#pragma mark -
-#pragma mark == Misc ==
-#endif
-
-//===========================================================================================================================
-//	Misc
-//===========================================================================================================================
-
-// Seconds <-> Minutes <-> Hours <-> Days <-> Weeks <-> Months <-> Years conversions
-
-#define kAttosecondsPerSecond			1000000000000000000		// 1e-18 seconds.
-#define kFemtosecondsPerSecond			1000000000000000		// 1e-15 seconds.
-#define kPicosecondsPerSecond			1000000000000			// 1e-12 seconds.
-#define kNanosecondsPerMicrosecond		1000
-#define kNanosecondsPerMillisecond		1000000
-#define kNanosecondsPerSecond			1000000000				// 1e-9 seconds.
-#define kMicrosecondsPerSecond			1000000					// 1e-6 seconds.
-#define kMicrosecondsPerMillisecond		1000
-#define kMillisecondsPerSecond			1000
-#define kSecondsPerMinute				60
-#define kSecondsPerHour					( 60 * 60 )				// 3600
-#define kSecondsPerDay					( 60 * 60 * 24 )		// 86400
-#define kSecondsPerWeek					( 60 * 60 * 24 * 7 )	// 604800
-#define kSecondsPerMonth				( 60 * 60 * 24 * 30 )	// 2592000
-#define kSecondsPerYear					( 60 * 60 * 24 * 365 )	// 31536000
-#define kMinutesPerHour					60
-#define kMinutesPerDay					( 60 * 24 )				// 1440
-#define kHoursPerDay					24
-#define kDaysPerWeek					7
-#define kWeeksPerYear					52
-#define kMonthsPerYear					12
-
-#define	IsLeapYear( YEAR )		( !( ( YEAR ) % 4 ) && ( ( ( YEAR ) % 100 ) || !( ( YEAR ) % 400 ) ) )
-#define YearToDays( YEAR )		( ( (YEAR) * 365 ) + ( (YEAR) / 4 ) - ( (YEAR) / 100 ) + ( (YEAR) / 400 ) )
-#define MonthToDays( MONTH ) 	( ( ( (MONTH) * 3057 ) - 3007 ) / 100 )
-
-#define dispatch_time_milliseconds( MS )	dispatch_time( DISPATCH_TIME_NOW, (MS)   * UINT64_C_safe( kNanosecondsPerMillisecond ) )
-#define dispatch_time_seconds( SECS )		dispatch_time( DISPATCH_TIME_NOW, (SECS) * UINT64_C_safe( kNanosecondsPerSecond ) )
-
-// Bytes
-
-#define kBytesPerTeraByte		1099511627776
-#define kBytesPerGigaByte		1073741824
-#define kBytesPerMegaByte		1048576
-#define kBytesPerKiloByte		1024
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@group		NumVersion
-	@abstract	Mac-style version numbers represented by 32-bit numbers (e.g. 1.2.3b4 -> 0x01236004).
-*/
-#define	kVersionStageDevelopment		0x20	//! Development version.
-#define	kVersionStageAlpha				0x40	//! Alpha version (feature complete, possibly crashing bugs).
-#define	kVersionStageBeta				0x60	//! Beta version (feature complete, no crashing bugs).
-#define	kVersionStageFinal				0x80	//! Final version (f0 means GM).
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	NumVersionBuild
-	@abstract	Builds a 32-bit Mac-style NumVersion value (e.g. NumVersionBuild( 1, 2, 3, kVersionStageBeta, 4 ) -> 1.2.3b4).
-*/
-#define	NumVersionBuild( MAJOR, MINOR, BUGFIX, STAGE, REV ) \
-	( ( ( ( MAJOR )  & 0xFF ) << 24 ) | \
-	  ( ( ( MINOR )  & 0x0F ) << 20 ) | \
-	  ( ( ( BUGFIX ) & 0x0F ) << 16 ) | \
-	  ( ( ( STAGE )  & 0xFF ) <<  8 ) | \
-	  ( ( ( REV )    & 0xFF )       ) )
-
-#define	NumVersionExtractMajor( VERSION )				( (uint8_t)( ( ( VERSION ) >> 24 ) & 0xFF ) )
-#define	NumVersionExtractMinorAndBugFix( VERSION )		( (uint8_t)( ( ( VERSION ) >> 16 ) & 0xFF ) )
-#define	NumVersionExtractMinor( VERSION )				( (uint8_t)( ( ( VERSION ) >> 20 ) & 0x0F ) )
-#define	NumVersionExtractBugFix( VERSION )				( (uint8_t)( ( ( VERSION ) >> 16 ) & 0x0F ) )
-#define	NumVersionExtractStage( VERSION )				( (uint8_t)( ( ( VERSION ) >>  8 ) & 0xFF ) )
-#define	NumVersionExtractRevision( VERSION )			( (uint8_t)(   ( VERSION )         & 0xFF ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	NumVersionCompare
-	@abstract	Compares two NumVersion values and returns < 0 if A < B, 0 if A == B, or > 0 if A > B.
-*/
-#define	NumVersionCompare( A, B ) \
-	( ( ( (A) & 0xFFFFFF00U )  < ( (B) & 0xFFFFFF00U ) )	? -1 : \
-	  ( ( (A) & 0xFFFFFF00U )  > ( (B) & 0xFFFFFF00U ) )	?  1 : \
-	  ( ( ( (A) - 1 ) & 0xFF ) < ( ( (B) - 1 ) & 0xFF ) )	? -1 : \
-	  ( ( ( (A) - 1 ) & 0xFF ) > ( ( (B) - 1 ) & 0xFF ) )	?  1 : 0 )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@defined	SourceVersionToInteger
-	@abstract	Converts source version components to an integer.
-	@discussion	For example, source version 110.35 would be SourceVersionToInteger( 110, 35, 0 ) which is 1103500.
-*/
-#define SourceVersionToInteger( X, Y, Z )	( ( 10000 * (X) ) + ( 100 * (Y) ) + (Z) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@group		CharSets
-	@abstract	Useful character sets.
-*/
-#define kBinaryDigits				"01"
-#define kDecimalDigits				"0123456789"
-#define kHexDigitsUppercase			"0123456789ABCDEF"
-#define kHexDigitsLowercase			"0123456789abcdef"
-#define kOctalDigits				"01234567"
-
-#define kAlphaCharSet				"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
-#define kAlphaNumericCharSet		"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-#define kUnmistakableCharSet		"ACDEFGHJKMNPQRSTUVWXYZ2345679" // Avoids easily mistaken characters: 0/o, 1/l/i, B/8
-
-// AFP Volume names -- (0x20-0x7E, except ':').
-
-#define kAFPVolumeNameCharSet \
-	" !\"#$%&'()*+,-./" \
-	"0123456789" \
-	";<=>?@" \
-	"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
-	"[\\]^_`" \
-	"abcdefghijklmnopqrstuvwxyz" \
-	"{|}~"	
-
-// ASCII
-
-#define kASCII7BitCharSet \
-	"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" \
-	"\x00\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" \
-	" !\"#$%&'()*+,-./" \
-	"0123456789" \
-	":;<=>?@" \
-	"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
-	"[\\]^_`" \
-	"abcdefghijklmnopqrstuvwxyz" \
-	"{|}~\x7F"
-
-#define kASCIIPrintableCharSet \
-	"\t\n\x0B\x0C\r" \
-	" !\"#$%&'()*+,-./" \
-	"0123456789" \
-	":;<=>?@" \
-	"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
-	"[\\]^_`" \
-	"abcdefghijklmnopqrstuvwxyz" \
-	"{|}~"
-
-// Bonjour SubTypes -- restrict to lowercase letters, digits, '_', and '-'.
-
-#define kBonjourSubTypeCharSet		"abcdefghijklmnopqrstuvwxyz0123456789_-"
-
-// DNS names -- RFC 1034 says DNS names must consist of only letters, digits, dots, and hyphens.
-
-#define kDNSCharSet		"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-"
-
-// TXT record keys -- Printable ASCII (0x20-0x7E, except 0x3D '=').
-
-#define kTXTKeyCharSet \
-	" !\"#$%&'()*+,-./" \
-	"0123456789" \
-	":;<>?@" \
-	"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
-	"[\\]^_`" \
-	"abcdefghijklmnopqrstuvwxyz" \
-	"{|}~"	
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@group		Hex Char Testing and Conversions
-	@abstract	Macros for testing for hex chars and converting them to values and/or bytes.
-*/
-
-// Hex Char Testing and Conversions.
-
-#define HexCharToValue( X ) \
-	( ( ( (X) >= '0' ) && ( (X) <= '9' ) ) ? (        (X) - '0'   ) : \
-	  ( ( (X) >= 'A' ) && ( (X) <= 'F' ) ) ? ( 10 + ( (X) - 'A' ) ) : \
-	  ( ( (X) >= 'a' ) && ( (X) <= 'f' ) ) ? ( 10 + ( (X) - 'a' ) ) : 0 )
-
-#define IsHexPair( PTR ) \
-	( isxdigit_safe( ( (const unsigned char *)(PTR) )[ 0 ] ) && \
-	  isxdigit_safe( ( (const unsigned char *)(PTR) )[ 1 ] ) )
-
-#define HexPairToByte( PTR )	( (uint8_t)( \
-	( HexCharToValue( ( (const unsigned char *)(PTR) )[ 0 ] ) << 4 ) | \
-	  HexCharToValue( ( (const unsigned char *)(PTR) )[ 1 ] ) ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@group		Octal Char Testing and Conversions
-	@abstract	Macros for testing for octal chars and converting them to values and/or bytes.
-*/
-#define isoctal( X )				( ( (X) >= '0' ) && ( (X) <= '7' ) )
-#define OctalCharToValue( X )		( ( ( (X) >= '0' ) && ( (X) <= '7' ) ) ? ( (X) - '0' ) : 0 )
-
-#define IsOctalTriple( PTR ) \
-	( ( ( ( (const unsigned char *)(PTR) )[ 0 ] >= '0' ) && \
-	    ( ( (const unsigned char *)(PTR) )[ 0 ] <= '3' ) ) && \
-	  isoctal_safe( ( (const unsigned char *)(PTR) )[ 1 ] ) && \
-	  isoctal_safe( ( (const unsigned char *)(PTR) )[ 2 ] ) )
-
-#define OctalTripleToByte( PTR )	( (uint8_t)( \
-	( OctalCharToValue( ( (const unsigned char *)(PTR) )[ 0 ] ) * 64 ) | \
-	( OctalCharToValue( ( (const unsigned char *)(PTR) )[ 1 ] ) *  8 ) | \
-	  OctalCharToValue( ( (const unsigned char *)(PTR) )[ 2 ] ) ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	BCDByteToDecimal/DecimalByteToBCD
-	@abstract	Converts a byte to/from BSD (e.g. 0x50 -> 50).
-*/		
-#define	BCDByteToDecimal( X )	( ( ( ( (X) >> 4 ) & 0x0F ) * 10 ) + ( (X) & 0x0F ) )
-#define	DecimalByteToBCD( X )	( ( ( (X) / 10 ) << 4 ) | ( (X) % 10 ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@group		dB <-> linear Conversions
-	@discussion	Macros to convert between dB attentuation values and linear volume levels.
-	
-	dB		= 20log10( linear )
-	linear	= pow( 10, dB / 20 )
-	
-	See <http://en.wikipedia.org/wiki/Decibel> for details on the math behind this.
-*/
-#define DBtoLinear( DB )		( ( (DB)     <= -144.0f ) ?    0.0f : ( (DB)     >= 0.0f ) ? 1.0f : powf( 10, (DB) / 20 ) )
-#define LinearToDB( LINEAR )	( ( (LINEAR) <=    0.0f ) ? -144.0f : ( (LINEAR) >= 1.0f ) ? 0.0f : ( 20 * log10f( (LINEAR) ) ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@group		Q-format fixed-point number conversions
-	@abstract	Macros to convert between floating point and fixed-point Q-format numbers.
-	@discussion	See <http://en.wikipedia.org/wiki/Q_(number_format)> for details.
-	
-	N is number of fractional bits to use.
-*/
-#define FloatToQ( X, N )		( (int)( (X) * ( 1 << (N) ) ) )
-#define QToFloat( X, N )		( ( (float)(X) ) / ( (float)( 1 << (N) ) ) )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@typedef	dispatch_status_block_t
-	@abstract	Block type for a commonly used block with a status parameter.
-*/
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	memcmp_constant_time
-	@abstract	Compares memory so that the time it takes does not depend on the data being compared.
-	@discussion	This is needed to avoid certain timing attacks in cryptographic software.
-*/
-STATIC_INLINE int	memcmp_constant_time( const void *inA, const void *inB, size_t inLen )
-{
-	const uint8_t * const		a = (const uint8_t *) inA;
-	const uint8_t * const		b = (const uint8_t *) inB;
-	int							result = 0;
-	size_t						i;
-	
-	for( i = 0; i < inLen; ++i )
-	{
-		result |= ( a[ i ] ^ b[ i ] );
-	}
-	return( result );
-}
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	MemZeroSecure
-	@abstract	Zeros memory in a way that prevents the compiler from optimizing it out (as it could with memset).
-	@discussion	This is needed for cases such as clearing a buffer containing a cryptographic key.
-*/
-STATIC_INLINE void	MemZeroSecure( void *inPtr, size_t inLen )
-{
-	volatile unsigned char *		ptr = (volatile unsigned char *) inPtr;
-	
-	while( inLen-- ) *ptr++ = 0;
-}
-
-#if 0
-#pragma mark == Time96 ==
-#endif
-
-//===========================================================================================================================
-//	Time96
-//
-//	Support for 96-bit (32.64) binary time.
-//===========================================================================================================================
-
-typedef struct
-{
-	int32_t		secs; //! Number of seconds. Epoch depends on usage. 0, 1970-01-01 00:00:00 (Unix time), etc.
-	uint64_t	frac; //! Fraction of a second in units of 1/2^64.
-	
-}	Time96;
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	Time96ToDouble / DoubleToTime96
-	@abstract	Convert between Time96 and floating-point seconds values.
-*/
-#define Time96ToDouble( T96 )	( ( (double) (T96)->secs ) + ( ( (double) (T96)->frac ) * ( 1.0 / 18446744073709551615.0 ) ) )
-#define DoubleToTime96( D, T96 ) \
-	do \
-	{ \
-		double		_DoubleToTime96_secs; \
-		\
-		_DoubleToTime96_secs = floor( (D) ); \
-		(T96)->secs = (int32_t) _DoubleToTime96_secs; \
-		(T96)->frac = (uint64_t)( ( (D) - _DoubleToTime96_secs ) * 18446744073709551615.0 ); \
-		\
-	}	while( 0 )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	Time96ToNTP / NTPToTime96
-	@abstract	Convert between Time96 and NTP 32.32 values.
-*/
-#define Time96ToNTP( T96 )		( ( ( (uint64_t) (T96)->secs ) << 32 ) | ( (T96)->frac >> 32 ) )
-#define NTPToTime96( NTP, T96 ) \
-	do \
-	{ \
-		(T96)->secs = (int32_t)( (NTP) >> 32 ); \
-		(T96)->frac =          ( (NTP) << 32 ); \
-		\
-	}	while( 0 )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	Time96ToNTP / NTPToTime96
-	@abstract	Convert between Time96 and NTP 32.32 values.
-*/
-#define Time96ToNTP( T96 )		( ( ( (uint64_t) (T96)->secs ) << 32 ) | ( (T96)->frac >> 32 ) )
-#define NTPToTime96( NTP, T96 ) \
-	do \
-	{ \
-		(T96)->secs = (int32_t)( (NTP) >> 32 ); \
-		(T96)->frac =          ( (NTP) << 32 ); \
-		\
-	}	while( 0 )
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	Time96FracToNanoseconds / NanosecondsToTime96Frac
-	@abstract	Convert between Time96 fractional seconds and nanoseconds.
-*/
-#define Time96FracToNanoseconds( FRAC )		( ( UINT64_C( 1000000000 ) * (uint32_t)( (FRAC) >> 32 ) ) >> 32 )
-#define NanosecondsToTime96Frac( NS )		( (NS) * UINT64_C( 18446744073 ) ) // 2^64 / 1000000000 = 18446744073
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	Time96_AddFrac
-	@abstract	Adds a fractional seconds (1/2^64 units) value to a time.
-*/
-STATIC_INLINE void	Time96_AddFrac( Time96 *inTime, uint64_t inFrac )
-{
-	uint64_t		frac;
-	
-	frac = inTime->frac;
-	inTime->frac = frac + inFrac;
-	if( frac > inTime->frac ) inTime->secs += 1; // Increment seconds on fraction wrap.
-}
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	Time96_Add
-	@abstract	Adds one time to another time.
-*/
-STATIC_INLINE void	Time96_Add( Time96 *inTime, const Time96 *inAdd )
-{
-	uint64_t		frac;
-	
-	frac = inTime->frac;
-	inTime->frac = frac + inAdd->frac;
-	if( frac > inTime->frac ) inTime->secs += 1; // Increment seconds on fraction wrap.
-	inTime->secs += inAdd->secs;
-}
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@function	Time96_Sub
-	@abstract	Subtracts one time from another time.
-*/
-STATIC_INLINE void	Time96_Sub( Time96 *inTime, const Time96 *inSub )
-{
-	uint64_t	frac;
-	
-	frac = inTime->frac;
-	inTime->frac = frac - inSub->frac;
-	if( frac < inTime->frac ) inTime->secs -= 1; // Decrement seconds on fraction wrap.
-	inTime->secs -= inSub->secs;
-}
-
-#if 0
-#pragma mark -
-#pragma mark == timeval macros ==
-#endif
-
-//===========================================================================================================================
-//	timeval macros
-//===========================================================================================================================
-
-#define	TIMEVAL_USECS_PER_SEC		1000000
-
-// A == B
-#define	TIMEVAL_EQ( A, B )	( ( (A).tv_sec == (B).tv_sec ) && ( (A).tv_usec == (B).tv_usec ) )
-
-// A < B
-#define	TIMEVAL_LT( A, B )	(   ( (A).tv_sec  < (B).tv_sec ) || \
-							  ( ( (A).tv_sec == (B).tv_sec ) && ( (A).tv_usec < (B).tv_usec ) ) )
-
-// A <= B
-#define	TIMEVAL_LE( A, B )	(   ( (A).tv_sec  < (B).tv_sec ) || \
-							  ( ( (A).tv_sec == (B).tv_sec ) && ( (A).tv_usec <= (B).tv_usec ) ) )
-
-// A > B
-#define	TIMEVAL_GT( A, B )	(   ( (A).tv_sec  > (B).tv_sec ) || \
-							  ( ( (A).tv_sec == (B).tv_sec ) && ( (A).tv_usec > (B).tv_usec ) ) )
-
-// A >= B
-#define	TIMEVAL_GE( A, B )	(   ( (A).tv_sec  > (B).tv_sec ) || \
-							  ( ( (A).tv_sec == (B).tv_sec ) && ( (A).tv_usec >= (B).tv_usec ) ) )
-
-// A  < B = -1
-// A  > B =  1
-// A == B =  0
-#define	TIMEVAL_CMP( A, B ) \
-		( (A).tv_sec  < (B).tv_sec )  ? -1 : \
-		( (A).tv_sec  > (B).tv_sec )  ?  1 : \
-		( (A).tv_usec < (B).tv_usec ) ? -1 : \
-		( (A).tv_usec > (B).tv_usec ) ?  1 : 0
-
-// Non-zero if tv_usec is between 0 and (1000000 - 1).
-#define	TIMEVAL_VALID( X )		( ( (X).tv_usec >= 0 ) && ( (X).tv_usec < TIMEVAL_USECS_PER_SEC ) )
-
-// Sets X to 0 seconds and 0 microseconds.
-#define	TIMEVAL_ZERO( X )		TIMEVAL_SET( X, 0, 0 )
-
-// Sets X from secs and microseconds.
-#define	TIMEVAL_SET( X, SECS, USECS ) \
-	do \
-	{ \
-		(X).tv_sec  = ( SECS ); \
-		(X).tv_usec = ( USECS ); \
-	\
-	}	while( 0 )
-
-// A += B
-#define	TIMEVAL_ADD( A, B ) \
-	do \
-	{ \
-		(A).tv_sec  += (B).tv_sec; \
-		(A).tv_usec += (B).tv_usec; \
-		TIMEVAL_NORMALIZE( A ); \
-	\
-	}	while( 0 )
-
-// A += X. X is the number of microseconds to add.
-#define	TIMEVAL_ADD_USEC( A, X ) \
-	do \
-	{ \
-		(A).tv_usec += (X); \
-		TIMEVAL_NORMALIZE( A ); \
-	\
-	}	while( 0 )
-
-// X = A + B
-#define	TIMEVAL_ADD_COPY( X, A, B ) \
-	do \
-	{ \
-		(X) = (A); \
-		(X).tv_sec  += (B).tv_sec; \
-		(X).tv_usec += (B).tv_usec; \
-		TIMEVAL_NORMALIZE( X ); \
-	\
-	}	while( 0 )
-
-
-// A -= B
-#define	TIMEVAL_SUB( A, B ) \
-	do \
-	{ \
-		if( TIMEVAL_GT( A, B ) ) \
-		{ \
-			(A).tv_sec  -= (B).tv_sec; \
-			(A).tv_usec -= (B).tv_usec; \
-			TIMEVAL_NORMALIZE( A ); \
-		} \
-		else \
-		{ \
-			(A).tv_sec  = 0; \
-			(A).tv_usec = 0; \
-		} \
-	\
-	}	while( 0 )
-
-// X = A - B
-#define	TIMEVAL_SUB_COPY( X, A, B ) \
-	do \
-	{ \
-		(X) = (A); \
-		TIMEVAL_SUB( (X), (B) ); \
-	\
-	}	while( 0 )
-
-// A *= X. X must be a positive integer. X must be <= 2147 to avoid overflow.
-#define	TIMEVAL_MUL( A, X ) \
-	do \
-	{ \
-		(A).tv_sec  *= (X); \
-		(A).tv_usec *= (X); \
-		TIMEVAL_NORMALIZE( A ); \
-	\
-	}	while( 0 )
-
-// X = A * Y. Y must be a positive integer. Y must be <= 2147 to avoid overflow.
-#define	TIMEVAL_MUL_COPY( X, A, Y ) \
-	do \
-	{ \
-		(X) = (A); \
-		(X).tv_sec  *= (Y); \
-		(X).tv_usec *= (Y); \
-		TIMEVAL_NORMALIZE( X ); \
-	\
-	}	while( 0 )
-
-// Adjusts tv_sec and tv_usec so tv_usec is between 0 and (1000000 - 1).
-#define	TIMEVAL_NORMALIZE( X ) \
-	do \
-	{ \
-		for( ;; ) \
-		{ \
-			if( (X).tv_usec >= TIMEVAL_USECS_PER_SEC ) \
-			{ \
-				(X).tv_sec  += 1; \
-				(X).tv_usec -= TIMEVAL_USECS_PER_SEC; \
-			} \
-			else if( (X).tv_usec < 0 ) \
-			{ \
-				(X).tv_sec  -= 1; \
-				(X).tv_usec += TIMEVAL_USECS_PER_SEC; \
-			} \
-			else \
-			{ \
-				break; \
-			} \
-		} \
-		\
-	}	while( 0 )
-
-// X as single, unsigned 32-bit microseconds value. X must be <= 4294 to avoid overflow.
-#define	TIMEVAL_USEC32( X )				( ( ( (uint32_t)(X).tv_sec ) * TIMEVAL_USECS_PER_SEC ) + (X).tv_usec )
-
-// X as single, signed 64-bit microseconds value.
-#define	TIMEVAL_USEC64( X )				( ( ( (int64_t)(X).tv_sec ) * TIMEVAL_USECS_PER_SEC ) + (X).tv_usec )
-
-// A - B as single, signed 64-bit microseconds value (negative if A < B).
-#define	TIMEVAL_USEC64_DIFF( A, B )		( TIMEVAL_USEC64( A ) - TIMEVAL_USEC64( B ) )
-
-// X as a single, floating point seconds value.
-#define TIMEVAL_FP_SECS( X )			( ( (double)(X).tv_sec ) + ( ( (double)(X).tv_usec ) * ( 1.0 / 1000000.0 ) ) )
-
-#if 0
-#pragma mark == ANSI Escape Sequences ==
-#endif
-
-//---------------------------------------------------------------------------------------------------------------------------
-/*!	@group		ANSI Escape Sequences
-	@abstract	Escape sequences for use with printf/etc to terminal windows.
-	@discussion
-	
-	These are intended to be used either directly in a string or via %s in printf. For example:
-	
-	// Print "hello" in bold then reset it back to normal.
-	printf( kANSIBold "hello" kANSINormal "\n" );
-	
-	// Print "hello" in bold then reset it back to normal.
-	printf( "%s%s%s\n", kANSIBold, "hello", kANSINormal );
-*/
-#define kANSINormal					"\x1B[0m"  // all attributes off
-#define	kANSINormalIntensity		"\x1B[22m" // not bold and not faint.
-#define kANSIBold					"\x1B[1m"
-#define kANSIFaint					"\x1B[2m"  // not widely suppport.
-#define kANSIItalic					"\x1B[3m"  // not widely suppport. Sometimes treated as inverse.
-#define	kANSIUnderline				"\x1B[4m"  // not widely suppport.
-#define	kANSIUnderlineDouble		"\x1B[21m" // not widely suppport.
-#define	kANSIUnderlineOff			"\x1B[24m"
-#define	kANSIBlink					"\x1B[5m"  // less than 150 per minute.
-#define	kANSIBlinkRapid				"\x1B[6m"  // 150 per minute or more.
-#define	kANSIBlinkOff				"\x1B[25m" // not widely suppport.
-#define	kANSINegative				"\x1B[7m"  // inverse/reverse; swap foreground and background.
-#define	kANSIPositive				"\x1B[27m" // inverse of negative.
-#define	kANSIConceal				"\x1B[8m"  // not widely supported.
-#define	kANSIReveal					"\x1B[28m" // conceal off.
-
-// Foreground colors
-
-#define kANSIBlack					"\x1B[30m"
-#define kANSIGray					"\x1B[0;37m"
-#define kANSIRed					"\x1B[31m"
-#define kANSIGreen					"\x1B[32m"
-#define kANSIYellow					"\x1B[33m"
-#define kANSIBlue					"\x1B[34m"
-#define kANSIMagenta				"\x1B[35m"
-#define kANSICyan					"\x1B[36m"
-#define kANSIWhite					"\x1B[37m"
-#define kANSIForeReset				"\x1B[39m"
-
-// Background colors
-
-#define kANSIBackBlack				"\x1B[40m"
-#define kANSIBackRed				"\x1B[41m"
-#define kANSIBackGreen				"\x1B[42m"
-#define kANSIBackYellow				"\x1B[43m"
-#define kANSIBackBlue				"\x1B[44m"
-#define kANSIBackMagenta			"\x1B[45m"
-#define kANSIBackCyan				"\x1B[46m"
-#define kANSIBackWhite				"\x1B[47m"
-#define kANSIBackReset				"\x1B[49m"
-
-// High Intensity Foreground colors
-
-#define kANSIHighBlack				"\x1B[90m"
-#define kANSIHighRed				"\x1B[91m"
-#define kANSIHighGreen				"\x1B[92m"
-#define kANSIHighYellow				"\x1B[93m"
-#define kANSIHighBlue				"\x1B[94m"
-#define kANSIHighMagenta			"\x1B[95m"
-#define kANSIHighCyan				"\x1B[96m"
-#define kANSIHighWhite				"\x1B[97m"
-#define kANSIHighForeReset			"\x1B[99m"
-
-// High Intensity Background colors
-
-#define kANSIHighBackBlack			"\x1B[100m"
-#define kANSIHighBackRed			"\x1B[101m"
-#define kANSIHighBackGreen			"\x1B[102m"
-#define kANSIHighBackYellow			"\x1B[103m"
-#define kANSIHighBackBlue			"\x1B[104m"
-#define kANSIHighBackMagenta		"\x1B[105m"
-#define kANSIHighBackCyan			"\x1B[106m"
-#define kANSIHighBackWhite			"\x1B[107m"
-#define kANSIHighBackReset			"\x1B[109m"
-
-// Unit Test
-
-#define kANSIEscapeSequenceTest \
-	kANSINormal				"kANSINormal"				kANSINormal "\n" \
-	kANSIBold				"kANSIBold"					kANSINormal "\n" \
-	kANSIFaint				"kANSIFaint"				kANSINormal "\n" \
-	kANSIItalic				"kANSIItalic"				kANSINormal "\n" \
-	kANSIUnderline			"kANSIUnderline"			kANSINormal "\n" \
-	kANSIUnderlineDouble	"kANSIUnderlineDouble"		kANSINormal "\n" \
-	kANSIUnderlineOff		"kANSIUnderlineOff"			kANSINormal "\n" \
-	kANSIBlink				"kANSIBlink"				kANSINormal "\n" \
-	kANSIBlinkRapid			"kANSIBlinkRapid"			kANSINormal "\n" \
-	kANSIBlinkOff			"kANSIBlinkOff"				kANSINormal "\n" \
-	kANSINegative			"kANSINegative"				kANSINormal "\n" \
-	kANSIPositive			"kANSIPositive"				kANSINormal "\n" \
-	kANSIConceal			"kANSIConceal"				kANSINormal " (kANSIConceal)\n" \
-	kANSIReveal				"kANSIReveal"				kANSINormal "\n" \
-	\
-	kANSIBlack				"kANSIBlack"				kANSINormal " (kANSIBlack)\n" \
-	kANSIRed				"kANSIRed"					kANSINormal "\n" \
-	kANSIGreen				"kANSIGreen"				kANSINormal "\n" \
-	kANSIYellow				"kANSIYellow"				kANSINormal "\n" \
-	kANSIBlue				"kANSIBlue"					kANSINormal "\n" \
-	kANSIMagenta			"kANSIMagenta"				kANSINormal "\n" \
-	kANSICyan				"kANSICyan"					kANSINormal "\n" \
-	kANSIWhite				"kANSIWhite"				kANSINormal " (kANSIWhite)\n" \
-	kANSIForeReset			"kANSIForeReset"			kANSINormal "\n" \
-	\
-	kANSIBackBlack			"kANSIBackBlack"			kANSINormal "\n" \
-	kANSIBackRed			"kANSIBackRed"				kANSINormal "\n" \
-	kANSIBackGreen			"kANSIBackGreen"			kANSINormal "\n" \
-	kANSIBackYellow			"kANSIBackYellow"			kANSINormal "\n" \
-	kANSIBackBlue			"kANSIBackBlue"				kANSINormal "\n" \
-	kANSIBackMagenta		"kANSIBackMagenta"			kANSINormal "\n" \
-	kANSIBackCyan			"kANSIBackCyan"				kANSINormal "\n" \
-	kANSIBackWhite			"kANSIBackWhite"			kANSINormal "\n" \
-	kANSIBackReset			"kANSIBackReset"			kANSINormal "\n" \
-	\
-	kANSIHighBlack			"kANSIHighBlack"			kANSINormal "\n" \
-	kANSIHighRed			"kANSIHighRed"				kANSINormal "\n" \
-	kANSIHighGreen			"kANSIHighGreen"			kANSINormal "\n" \
-	kANSIHighYellow			"kANSIHighYellow"			kANSINormal "\n" \
-	kANSIHighBlue			"kANSIHighBlue"				kANSINormal "\n" \
-	kANSIHighMagenta		"kANSIHighMagenta"			kANSINormal "\n" \
-	kANSIHighCyan			"kANSIHighCyan"				kANSINormal "\n" \
-	kANSIHighWhite			"kANSIHighWhite"			kANSINormal " (kANSIHighWhite)\n" \
-	kANSIHighForeReset		"kANSIHighForeReset"		kANSINormal "\n" \
-	\
-	kANSIHighBackBlack		"kANSIHighBackBlack"		kANSINormal "\n" \
-	kANSIHighBackRed		"kANSIHighBackRed"			kANSINormal "\n" \
-	kANSIHighBackGreen		"kANSIHighBackGreen"		kANSINormal "\n" \
-	kANSIHighBackYellow		"kANSIHighBackYellow"		kANSINormal "\n" \
-	kANSIHighBackBlue		"kANSIHighBackBlue"			kANSINormal "\n" \
-	kANSIHighBackMagenta	"kANSIHighBackMagenta"		kANSINormal "\n" \
-	kANSIHighBackCyan		"kANSIHighBackCyan"			kANSINormal "\n" \
-	kANSIHighBackWhite		"kANSIHighBackWhite"		kANSINormal " (kANSIHighBackWhite)\n" \
-	kANSIHighBackReset		"kANSIHighBackReset"		kANSINormal "\n"
-
-#ifndef PATH_MAX
-#define PATH_MAX 512
-#endif
-
-#endif	// __APSCommonServices_h__

+ 0 - 7176
src/app/mDNS/mDNSCore/mDNS.c

@@ -1,7176 +0,0 @@
-/*
- * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
- *
- * This code is completely 100% portable C. It does not depend on any external header files
- * from outside the mDNS project -- all the types it expects to find are defined right here.
- * 
- * The previous point is very important: This file does not depend on any external
- * header files. It should complile on *any* platform that has a C compiler, without
- * making *any* assumptions about availability of so-called "standard" C functions,
- * routines, or types (which may or may not be present on any given platform).
-
- * Formatting notes:
- * This code follows the "Whitesmiths style" C indentation rules. Plenty of discussion
- * on C indentation can be found on the web, such as <http://www.kafejo.com/komp/1tbs.htm>,
- * but for the sake of brevity here I will say just this: Curly braces are not syntactially
- * part of an "if" statement; they are the beginning and ending markers of a compound statement;
- * therefore common sense dictates that if they are part of a compound statement then they
- * should be indented to the same level as everything else in that compound statement.
- * Indenting curly braces at the same level as the "if" implies that curly braces are
- * part of the "if", which is false. (This is as misleading as people who write "char* x,y;"
- * thinking that variables x and y are both of type "char*" -- and anyone who doesn't
- * understand why variable y is not of type "char*" just proves the point that poor code
- * layout leads people to unfortunate misunderstandings about how the C language really works.)
-
- Change History (most recent first):
-
- $Log: mDNS.c,v $
- Revision 1.1.1.1  2005/07/23 13:57:05  shiro
- raop_play project
-
- Revision 1.1.2.2  2004/09/25 04:54:13  shiro
- *** empty log message ***
-
- Revision 1.1.2.1  2004/09/18 03:29:20  shiro
- *** empty log message ***
-
- Revision 1.307.2.8  2004/04/03 05:18:19  bradley
- Added cast to fix signed/unsigned warning due to int promotion.
-
- Revision 1.307.2.7  2004/03/30 06:46:24  cheshire
- Compiler warning fixes from Don Woodward at Roku Labs
-
- Revision 1.307.2.6  2004/03/09 03:03:38  cheshire
- <rdar://problem/3581961> Don't take lock until after mDNS_Update() has validated that the data is good
-
- Revision 1.307.2.5  2004/03/02 02:55:24  cheshire
- <rdar://problem/3549576> Properly support "_services._dns-sd._udp" meta-queries
-
- Revision 1.307.2.4  2004/02/18 01:55:08  cheshire
- <rdar://problem/3553472>: Increase delay to 400ms when answering queries with multi-packet KA lists
-
- Revision 1.307.2.3  2004/01/28 23:08:45  cheshire
- <rdar://problem/3488559>: Hard code domain enumeration functions to return ".local" only
-
- Revision 1.307.2.2  2003/12/20 01:51:40  cheshire
- <rdar://problem/3515876>: Error putting additional records into packets
- Another fix from Rampi: responseptr needs to be updated inside the "for" loop,
- after every record, not once at the end.
-
- Revision 1.307.2.1  2003/12/03 11:20:27  cheshire
- <rdar://problem/3457718>: Stop and start of a service uses old ip address (with old port number)
-
- Revision 1.307  2003/09/09 20:13:30  cheshire
- <rdar://problem/3411105> Don't send a Goodbye record if we never announced it
- Ammend checkin 1.304: Off-by-one error: By this place in the function we've already decremented
- rr->AnnounceCount, so the check needs to be for InitialAnnounceCount-1, not InitialAnnounceCount
-
- Revision 1.306  2003/09/09 03:00:03  cheshire
- <rdar://problem/3413099> Services take a long time to disappear when switching networks.
- Added two constants: kDefaultReconfirmTimeForNoAnswer and kDefaultReconfirmTimeForCableDisconnect
-
- Revision 1.305  2003/09/09 02:49:31  cheshire
- <rdar://problem/3413975> Initial probes and queries not grouped on wake-from-sleep
-
- Revision 1.304  2003/09/09 02:41:19  cheshire
- <rdar://problem/3411105> Don't send a Goodbye record if we never announced it
-
- Revision 1.303  2003/09/05 19:55:02  cheshire
- <rdar://problem/3409533> Include address records when announcing SRV records
-
- Revision 1.302  2003/09/05 00:01:36  cheshire
- <rdar://problem/3407549> Don't accelerate queries that have large KA lists
-
- Revision 1.301  2003/09/04 22:51:13  cheshire
- <rdar://problem/3398213> Group probes and goodbyes better
-
- Revision 1.300  2003/09/03 02:40:37  cheshire
- <rdar://problem/3404842> mDNSResponder complains about '_'s
- Underscores are not supposed to be legal in standard DNS names, but IANA appears
- to have allowed them in previous service name registrations, so we should too.
-
- Revision 1.299  2003/09/03 02:33:09  cheshire
- <rdar://problem/3404795> CacheRecordRmv ERROR
- Don't update m->NewQuestions until *after* CheckCacheExpiration();
-
- Revision 1.298  2003/09/03 01:47:01  cheshire
- <rdar://problem/3319418> Rendezvous services always in a state of flux
- Change mDNS_Reconfirm_internal() minimum timeout from 5 seconds to 45-60 seconds
-
- Revision 1.297  2003/08/29 19:44:15  cheshire
- <rdar://problem/3400967> Traffic reduction: Eliminate synchronized QUs when a new service appears
- 1. Use m->RandomQueryDelay to impose a random delay in the range 0-500ms on queries
- that already have at least one unique answer in the cache
- 2. For these queries, go straight to QM, skipping QU
-
- Revision 1.296  2003/08/29 19:08:21  cheshire
- <rdar://problem/3400986> Traffic reduction: Eliminate huge KA lists after wake from sleep
- Known answers are no longer eligible to go in the KA list if they are more than half-way to their expiry time.
-
- Revision 1.295  2003/08/28 01:10:59  cheshire
- <rdar://problem/3396034> Add syslog message to report when query is reset because of immediate answer burst
-
- Revision 1.294  2003/08/27 02:30:22  cheshire
- <rdar://problem/3395909> Traffic Reduction: Inefficiencies in DNSServiceResolverResolve()
- One more change: "query->GotTXT" is now a straightforward bi-state boolean again
-
- Revision 1.293  2003/08/27 02:25:31  cheshire
- <rdar://problem/3395909> Traffic Reduction: Inefficiencies in DNSServiceResolverResolve()
-
- Revision 1.292  2003/08/21 19:27:36  cheshire
- <rdar://problem/3387878> Traffic reduction: No need to announce record for longer than TTL
-
- Revision 1.291  2003/08/21 18:57:44  cheshire
- <rdar://problem/3387140> Synchronized queries on the network
-
- Revision 1.290  2003/08/21 02:25:23  cheshire
- Minor changes to comments and debugf() messages
-
- Revision 1.289  2003/08/21 02:21:50  cheshire
- <rdar://problem/3386473> Efficiency: Reduce repeated queries
-
- Revision 1.288  2003/08/20 23:39:30  cheshire
- <rdar://problem/3344098> Review syslog messages, and remove as appropriate
-
- Revision 1.287  2003/08/20 20:47:18  cheshire
- Fix compiler warning
-
- Revision 1.286  2003/08/20 02:18:51  cheshire
- <rdar://problem/3344098> Cleanup: Review syslog messages
-
- Revision 1.285  2003/08/20 01:59:06  cheshire
- <rdar://problem/3384478> rdatahash and rdnamehash not updated after changing rdata
- Made new routine SetNewRData() to update rdlength, rdestimate, rdatahash and rdnamehash in one place
-
- Revision 1.284  2003/08/19 22:20:00  cheshire
- <rdar://problem/3376721> Don't use IPv6 on interfaces that have a routable IPv4 address configured
- More minor refinements
-
- Revision 1.283  2003/08/19 22:16:27  cheshire
- Minor fix: Add missing "mDNS_Unlock(m);" in mDNS_DeregisterInterface() error case.
-
- Revision 1.282  2003/08/19 06:48:25  cheshire
- <rdar://problem/3376552> Guard against excessive record updates
- Each record starts with 10 UpdateCredits.
- Every update consumes one UpdateCredit.
- UpdateCredits are replenished at a rate of one one per minute, up to a maximum of 10.
- As the number of UpdateCredits declines, the number of announcements is similarly scaled back.
- When fewer than 5 UpdateCredits remain, the first announcement is also delayed by an increasing amount.
-
- Revision 1.281  2003/08/19 04:49:28  cheshire
- <rdar://problem/3368159> Interaction between v4, v6 and dual-stack hosts not working quite right
- 1. A dual-stack host should only suppress its own query if it sees the same query from other hosts on BOTH IPv4 and IPv6.
- 2. When we see the first v4 (or first v6) member of a group, we re-trigger questions and probes on that interface.
- 3. When we see the last v4 (or v6) member of a group go away, we revalidate all the records received on that interface.
-
- Revision 1.280  2003/08/19 02:33:36  cheshire
- Update comments
-
- Revision 1.279  2003/08/19 02:31:11  cheshire
- <rdar://problem/3378386> mDNSResponder overenthusiastic with final expiration queries
- Final expiration queries now only mark the question for sending on the particular interface
- pertaining to the record that's expiring.
-
- Revision 1.278  2003/08/18 22:53:37  cheshire
- <rdar://problem/3382647> mDNSResponder divide by zero in mDNSPlatformTimeNow()
-
- Revision 1.277  2003/08/18 19:05:44  cheshire
- <rdar://problem/3382423> UpdateRecord not working right
- Added "newrdlength" field to hold new length of updated rdata
-
- Revision 1.276  2003/08/16 03:39:00  cheshire
- <rdar://problem/3338440> InterfaceID -1 indicates "local only"
-
- Revision 1.275  2003/08/16 02:51:27  cheshire
- <rdar://problem/3366590> mDNSResponder takes too much RPRVT
- Don't try to compute namehash etc, until *after* validating the name
-
- Revision 1.274  2003/08/16 01:12:40  cheshire
- <rdar://problem/3366590> mDNSResponder takes too much RPRVT
- Now that the minimum rdata object size has been reduced to 64 bytes, it is no longer safe to do a
- simple C structure assignment of a domainname, because that object is defined to be 256 bytes long,
- and in the process of copying it, the C compiler may run off the end of the rdata object into
- unmapped memory. All assignments of domainname objects of uncertain size are now replaced with a
- call to the macro AssignDomainName(), which is careful to copy only as many bytes as are valid.
-
- Revision 1.273  2003/08/15 20:16:02  cheshire
- <rdar://problem/3366590> mDNSResponder takes too much RPRVT
- We want to avoid touching the rdata pages, so we don't page them in.
- 1. RDLength was stored with the rdata, which meant touching the page just to find the length.
- Moved this from the RData to the ResourceRecord object.
- 2. To avoid unnecessarily touching the rdata just to compare it,
- compute a hash of the rdata and store the hash in the ResourceRecord object.
-
- Revision 1.272  2003/08/14 19:29:04  cheshire
- <rdar://problem/3378473> Include cache records in SIGINFO output
- Moved declarations of DNSTypeName() and GetRRDisplayString to mDNSClientAPI.h so daemon.c can use them
-
- Revision 1.271  2003/08/14 02:17:05  cheshire
- <rdar://problem/3375491> Split generic ResourceRecord type into two separate types: AuthRecord and CacheRecord
-
- Revision 1.270  2003/08/13 17:07:28  ksekar
- Bug #: <rdar://problem/3376458>: Extra RR linked to list even if registration fails - causes crash
- Added check to result of mDNS_Register() before linking extra record into list.
-
- Revision 1.269  2003/08/12 19:56:23  cheshire
- Update to APSL 2.0
-
- Revision 1.268  2003/08/12 15:01:10  cheshire
- Add comments
-
- Revision 1.267  2003/08/12 14:59:27  cheshire
- <rdar://problem/3374490> Rate-limiting blocks some legitimate responses
- When setting LastMCTime also record LastMCInterface. When checking LastMCTime to determine
- whether to suppress the response, also check LastMCInterface to see if it matches.
-
- Revision 1.266  2003/08/12 12:47:16  cheshire
- In mDNSCoreMachineSleep debugf message, display value of m->timenow
-
- Revision 1.265  2003/08/11 20:04:28  cheshire
- <rdar://problem/3366553> Improve efficiency by restricting cases where we have to walk the entire cache
-
- Revision 1.264  2003/08/09 00:55:02  cheshire
- <rdar://problem/3366553> mDNSResponder is taking 20-30% of the CPU
- Don't scan the whole cache after every packet.
-
- Revision 1.263  2003/08/09 00:35:29  cheshire
- Moved AnswerNewQuestion() later in the file, in preparation for next checkin
-
- Revision 1.262  2003/08/08 19:50:33  cheshire
- <rdar://problem/3370332> Remove "Cache size now xxx" messages
-
- Revision 1.261  2003/08/08 19:18:45  cheshire
- <rdar://problem/3271219> Only retrigger questions on platforms with the "PhantomInterfaces" bug
-
- Revision 1.260  2003/08/08 18:55:48  cheshire
- <rdar://problem/3370365> Guard against time going backwards
-
- Revision 1.259  2003/08/08 18:36:04  cheshire
- <rdar://problem/3344154> Only need to revalidate on interface removal on platforms that have the PhantomInterfaces bug
-
- Revision 1.258  2003/08/08 16:22:05  cheshire
- <rdar://problem/3335473> Need to check validity of TXT (and other) records
- Remove unneeded LogMsg
-
- Revision 1.257  2003/08/07 01:41:08  cheshire
- <rdar://problem/3367346> Ignore packets with invalid source address (all zeroes or all ones)
-
- Revision 1.256  2003/08/06 23:25:51  cheshire
- <rdar://problem/3290674> Increase TTL for A/AAAA/SRV from one minute to four
-
- Revision 1.255  2003/08/06 23:22:50  cheshire
- Add symbolic constants: kDefaultTTLforUnique (one minute) and kDefaultTTLforShared (two hours)
-
- Revision 1.254  2003/08/06 21:33:39  cheshire
- Fix compiler warnings on PocketPC 2003 (Windows CE)
-
- Revision 1.253  2003/08/06 20:43:57  cheshire
- <rdar://problem/3335473> Need to check validity of TXT (and other) records
- Created ValidateDomainName() and ValidateRData(), used by mDNS_Register_internal() and mDNS_Update()
-
- Revision 1.252  2003/08/06 20:35:47  cheshire
- Enhance debugging routine GetRRDisplayString() so it can also be used to display
- other RDataBody objects, not just the one currently attached the given ResourceRecord
-
- Revision 1.251  2003/08/06 19:07:34  cheshire
- <rdar://problem/3366251> mDNSResponder not inhibiting multicast responses as much as it should
- Was checking LastAPTime instead of LastMCTime
-
- Revision 1.250  2003/08/06 19:01:55  cheshire
- Update comments
-
- Revision 1.249  2003/08/06 00:13:28  cheshire
- Tidy up debugf messages
-
- Revision 1.248  2003/08/05 22:20:15  cheshire
- <rdar://problem/3330324> Need to check IP TTL on responses
-
- Revision 1.247  2003/08/05 00:56:39  cheshire
- <rdar://problem/3357075> mDNSResponder sending additional records, even after precursor record suppressed
-
- Revision 1.246  2003/08/04 19:20:49  cheshire
- Add kDNSQType_ANY to list in DNSTypeName() so it can be displayed in debugging messages
-
- Revision 1.245  2003/08/02 01:56:29  cheshire
- For debugging: log message if we ever get more than one question in a truncated packet
-
- Revision 1.244  2003/08/01 23:55:32  cheshire
- Fix for compiler warnings on Windows, submitted by Bob Bradley
-
- Revision 1.243  2003/07/25 02:26:09  cheshire
- Typo: FIxed missing semicolon
-
- Revision 1.242  2003/07/25 01:18:41  cheshire
- Fix memory leak on shutdown in mDNS_Close() (detected in Windows version)
-
- Revision 1.241  2003/07/23 21:03:42  cheshire
- Only show "Found record..." debugf message in verbose mode
-
- Revision 1.240  2003/07/23 21:01:11  cheshire
- <rdar://problem/3340584> Need Nagle-style algorithm to coalesce multiple packets into one
- After sending a packet, suppress further sending for the next 100ms.
-
- Revision 1.239  2003/07/22 01:30:05  cheshire
- <rdar://problem/3329099> Don't try to add the same question to the duplicate-questions list more than once
-
- Revision 1.238  2003/07/22 00:10:20  cheshire
- <rdar://problem/3337355> ConvertDomainLabelToCString() needs to escape escape characters
-
- Revision 1.237  2003/07/19 03:23:13  cheshire
- <rdar://problem/2986147> mDNSResponder needs to receive and cache larger records
-
- Revision 1.236  2003/07/19 03:04:55  cheshire
- Fix warnings; some debugf message improvements
-
- Revision 1.235  2003/07/19 00:03:32  cheshire
- <rdar://problem/3160248> ScheduleNextTask needs to be smarter after a no-op packet is received
- ScheduleNextTask is quite an expensive operation.
- We don't need to do all that work after receiving a no-op packet that didn't change our state.
-
- Revision 1.234  2003/07/18 23:52:11  cheshire
- To improve consistency of field naming, global search-and-replace:
- NextProbeTime    -> NextScheduledProbe
- NextResponseTime -> NextScheduledResponse
-
- Revision 1.233  2003/07/18 00:29:59  cheshire
- <rdar://problem/3268878> Remove mDNSResponder version from packet header and use HINFO record instead
-
- Revision 1.232  2003/07/18 00:11:38  cheshire
- Add extra case to switch statements to handle HINFO data for Get, Put and Display
- (In all but GetRDLength(), this is is just a fall-through to kDNSType_TXT)
-
- Revision 1.231  2003/07/18 00:06:37  cheshire
- To make code a little easier to read in GetRDLength(), search-and-replace "rr->rdata->u." with "rd->"
-
- Revision 1.230  2003/07/17 18:16:54  cheshire
- <rdar://problem/3319418> Rendezvous services always in a state of flux
- In preparation for working on this, made some debugf messages a little more selective
-
- Revision 1.229  2003/07/17 17:35:04  cheshire
- <rdar://problem/3325583> Rate-limit responses, to guard against packet flooding
-
- Revision 1.228  2003/07/16 20:50:27  cheshire
- <rdar://problem/3315761> Need to implement "unicast response" request, using top bit of qclass
-
- Revision 1.227  2003/07/16 05:01:36  cheshire
- Add fields 'LargeAnswers' and 'ExpectUnicastResponse' in preparation for
- <rdar://problem/3315761> Need to implement "unicast response" request, using top bit of qclass
-
- Revision 1.226  2003/07/16 04:51:44  cheshire
- Fix use of constant 'mDNSPlatformOneSecond' where it should have said 'InitialQuestionInterval'
-
- Revision 1.225  2003/07/16 04:46:41  cheshire
- Minor wording cleanup: The correct DNS term is "response", not "reply"
-
- Revision 1.224  2003/07/16 04:39:02  cheshire
- Textual cleanup (no change to functionality):
- Construct "c >= 'A' && c <= 'Z'" appears in too many places; replaced with macro "mDNSIsUpperCase(c)"
-
- Revision 1.223  2003/07/16 00:09:22  cheshire
- Textual cleanup (no change to functionality):
- Construct "((mDNSs32)rr->rroriginalttl * mDNSPlatformOneSecond)" appears in too many places;
- replace with macro "TicksTTL(rr)"
- Construct "rr->TimeRcvd + ((mDNSs32)rr->rroriginalttl * mDNSPlatformOneSecond)"
- replaced with macro "RRExpireTime(rr)"
-
- Revision 1.222  2003/07/15 23:40:46  cheshire
- Function rename: UpdateDupSuppressInfo() is more accurately called ExpireDupSuppressInfo()
-
- Revision 1.221  2003/07/15 22:17:56  cheshire
- <rdar://problem/3328394> mDNSResponder is not being efficient when doing certain queries
-
- Revision 1.220  2003/07/15 02:12:51  cheshire
- Slight tidy-up of debugf messages and comments
-
- Revision 1.219  2003/07/15 01:55:12  cheshire
- <rdar://problem/3315777> Need to implement service registration with subtypes
-
- Revision 1.218  2003/07/14 16:26:06  cheshire
- <rdar://problem/3324795> Duplicate query suppression not working right
- Refinement: Don't record DS information for a question in the first quarter second
- right after we send it -- in the case where a question happens to be accelerated by
- the maximum allowed amount, we don't want it to then be suppressed because the previous
- time *we* sent that question falls (just) within the valid duplicate suppression window.
-
- Revision 1.217  2003/07/13 04:43:53  cheshire
- <rdar://problem/3325169> Services on multiple interfaces not always resolving
- Minor refinement: No need to make address query broader than the original SRV query that provoked it
-
- Revision 1.216  2003/07/13 03:13:17  cheshire
- <rdar://problem/3325169> Services on multiple interfaces not always resolving
- If we get an identical SRV on a second interface, convert address queries to non-specific
-
- Revision 1.215  2003/07/13 02:28:00  cheshire
- <rdar://problem/3325166> SendResponses didn't all its responses
- Delete all references to RRInterfaceActive -- it's now superfluous
-
- Revision 1.214  2003/07/13 01:47:53  cheshire
- Fix one error and one warning in the Windows build
-
- Revision 1.213  2003/07/12 04:25:48  cheshire
- Fix minor signed/unsigned warnings
-
- Revision 1.212  2003/07/12 01:59:11  cheshire
- Minor changes to debugf messages
-
- Revision 1.211  2003/07/12 01:47:01  cheshire
- <rdar://problem/3324495> After name conflict, appended number should be higher than previous number
-
- Revision 1.210  2003/07/12 01:43:28  cheshire
- <rdar://problem/3324795> Duplicate query suppression not working right
- The correct cutoff time for duplicate query suppression is timenow less one-half the query interval.
- The code was incorrectly using the last query time plus one-half the query interval.
- This was only correct in the case where query acceleration was not in effect.
-
- Revision 1.209  2003/07/12 01:27:50  cheshire
- <rdar://problem/3320079> Hostname conflict naming should not use two hyphens
- Fix missing "-1" in RemoveLabelSuffix()
-
- Revision 1.208  2003/07/11 01:32:38  cheshire
- Syntactic cleanup (no change to funcationality): Now that we only have one host name,
- rename field "hostname1" to "hostname", and field "RR_A1" to "RR_A".
-
- Revision 1.207  2003/07/11 01:28:00  cheshire
- <rdar://problem/3161289> No more local.arpa
-
- Revision 1.206  2003/07/11 00:45:02  cheshire
- <rdar://problem/3321909> Client should get callback confirming successful host name registration
-
- Revision 1.205  2003/07/11 00:40:18  cheshire
- Tidy up debug message in HostNameCallback()
-
- Revision 1.204  2003/07/11 00:20:32  cheshire
- <rdar://problem/3320087> mDNSResponder should log a message after 16 unsuccessful probes
-
- Revision 1.203  2003/07/10 23:53:41  cheshire
- <rdar://problem/3320079> Hostname conflict naming should not use two hyphens
-
- Revision 1.202  2003/07/04 02:23:20  cheshire
- <rdar://problem/3311955> Responder too aggressive at flushing stale data
- Changed mDNSResponder to require four unanswered queries before purging a record, instead of two.
-
- Revision 1.201  2003/07/04 01:09:41  cheshire
- <rdar://problem/3315775> Need to implement subtype queries
- Modified ConstructServiceName() to allow three-part service types
-
- Revision 1.200  2003/07/03 23:55:26  cheshire
- Minor change to wording of syslog warning messages
-
- Revision 1.199  2003/07/03 23:51:13  cheshire
- <rdar://problem/3315652>:	Lots of "have given xxx answers" syslog warnings
- Added more detailed debugging information
-
- Revision 1.198  2003/07/03 22:19:30  cheshire
- <rdar://problem/3314346> Bug fix in 3274153 breaks TiVo
- Make exception to allow _tivo_servemedia._tcp.
-
- Revision 1.197  2003/07/02 22:33:05  cheshire
- <rdar://problem/2986146> mDNSResponder needs to start with a smaller cache and then grow it as needed
- Minor refinements:
- When cache is exhausted, verify that rrcache_totalused == rrcache_size and report if not
- Allow cache to grow to 512 records before considering it a potential denial-of-service attack
-
- Revision 1.196  2003/07/02 21:19:45  cheshire
- <rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
- Revision 1.195  2003/07/02 19:56:58  cheshire
- <rdar://problem/2986146> mDNSResponder needs to start with a smaller cache and then grow it as needed
- Minor refinement: m->rrcache_active was not being decremented when
- an active record was deleted because its TTL expired
-
- Revision 1.194  2003/07/02 18:47:40  cheshire
- Minor wording change to log messages
-
- Revision 1.193  2003/07/02 02:44:13  cheshire
- Fix warning in non-debug build
-
- Revision 1.192  2003/07/02 02:41:23  cheshire
- <rdar://problem/2986146> mDNSResponder needs to start with a smaller cache and then grow it as needed
-
- Revision 1.191  2003/07/02 02:30:51  cheshire
- HashSlot() returns an array index. It can't be negative; hence it should not be signed.
-
- Revision 1.190  2003/06/27 00:03:05  vlubet
- <rdar://problem/3304625> Merge of build failure fix for gcc 3.3
-
- Revision 1.189  2003/06/11 19:24:03  cheshire
- <rdar://problem/3287141> Crash in SendQueries/SendResponses when no active interfaces
- Slight refinement to previous checkin
-
- Revision 1.188  2003/06/10 20:33:28  cheshire
- <rdar://problem/3287141> Crash in SendQueries/SendResponses when no active interfaces
-
- Revision 1.187  2003/06/10 04:30:44  cheshire
- <rdar://problem/3286234> Need to re-probe/re-announce on configuration change
- Only interface-specific records were re-probing and re-announcing, not non-specific records.
-
- Revision 1.186  2003/06/10 04:24:39  cheshire
- <rdar://problem/3283637> React when we observe other people query unsuccessfully for a record that's in our cache
- Some additional refinements:
- Don't try to do this for unicast-response queries
- better tracking of Qs and KAs in multi-packet KA lists
-
- Revision 1.185  2003/06/10 03:52:49  cheshire
- Update comments and debug messages
-
- Revision 1.184  2003/06/10 02:26:39  cheshire
- <rdar://problem/3283516> mDNSResponder needs an mDNS_Reconfirm() function
- Make mDNS_Reconfirm() call mDNS_Lock(), like the other API routines
-
- Revision 1.183  2003/06/09 18:53:13  cheshire
- Simplify some debugf() statements (replaced block of 25 lines with 2 lines)
-
- Revision 1.182  2003/06/09 18:38:42  cheshire
- <rdar://problem/3285082> Need to be more tolerant when there are mDNS proxies on the network
- Only issue a correction if the TTL in the proxy packet is less than half the correct value.
-
- Revision 1.181  2003/06/07 06:45:05  cheshire
- <rdar://problem/3283666> No need for multiple machines to all be sending the same queries
-
- Revision 1.180  2003/06/07 06:31:07  cheshire
- Create little four-line helper function "FindIdenticalRecordInCache()"
-
- Revision 1.179  2003/06/07 06:28:13  cheshire
- For clarity, change name of "DNSQuestion q" to "DNSQuestion pktq"
-
- Revision 1.178  2003/06/07 06:25:12  cheshire
- Update some comments
-
- Revision 1.177  2003/06/07 04:50:53  cheshire
- <rdar://problem/3283637> React when we observe other people query unsuccessfully for a record that's in our cache
-
- Revision 1.176  2003/06/07 04:33:26  cheshire
- <rdar://problem/3283540> When query produces zero results, call mDNS_Reconfirm() on any antecedent records
- Minor change: Increment/decrement logic for q->CurrentAnswers should be in
- CacheRecordAdd() and CacheRecordRmv(), not AnswerQuestionWithResourceRecord()
-
- Revision 1.175  2003/06/07 04:11:52  cheshire
- Minor changes to comments and debug messages
-
- Revision 1.174  2003/06/07 01:46:38  cheshire
- <rdar://problem/3283540> When query produces zero results, call mDNS_Reconfirm() on any antecedent records
-
- Revision 1.173  2003/06/07 01:22:13  cheshire
- <rdar://problem/3283516> mDNSResponder needs an mDNS_Reconfirm() function
-
- Revision 1.172  2003/06/07 00:59:42  cheshire
- <rdar://problem/3283454> Need some randomness to spread queries on the network
-
- Revision 1.171  2003/06/06 21:41:10  cheshire
- For consistency, mDNS_StopQuery() should return an mStatus result, just like all the other mDNSCore routines
-
- Revision 1.170  2003/06/06 21:38:55  cheshire
- Renamed 'NewData' as 'FreshData' (The data may not be new data, just a refresh of data that we
- already had in our cache. This refreshes our TTL on the data, but the data itself stays the same.)
-
- Revision 1.169  2003/06/06 21:35:55  cheshire
- Fix mis-named macro: GetRRHostNameTarget is really GetRRDomainNameTarget
- (the target is a domain name, but not necessarily a host name)
-
- Revision 1.168  2003/06/06 21:33:31  cheshire
- Instead of using (mDNSPlatformOneSecond/2) all over the place, define a constant "InitialQuestionInterval"
-
- Revision 1.167  2003/06/06 21:30:42  cheshire
- <rdar://problem/3282962> Don't delay queries for shared record types
-
- Revision 1.166  2003/06/06 17:20:14  cheshire
- For clarity, rename question fields name/rrtype/rrclass as qname/qtype/qclass
- (Global search-and-replace; no functional change to code execution.)
-
- Revision 1.165  2003/06/04 02:53:21  cheshire
- Add some "#pragma warning" lines so it compiles clean on Microsoft compilers
-
- Revision 1.164  2003/06/04 01:25:33  cheshire
- <rdar://problem/3274950> Cannot perform multi-packet known-answer suppression messages
- Display time interval between first and subsequent queries
-
- Revision 1.163  2003/06/03 19:58:14  cheshire
- <rdar://problem/3277665> mDNS_DeregisterService() fixes:
- When forcibly deregistering after a conflict, ensure we don't send an incorrect goodbye packet.
- Guard against a couple of possible mDNS_DeregisterService() race conditions.
-
- Revision 1.162  2003/06/03 19:30:39  cheshire
- Minor addition refinements for
- <rdar://problem/3277080> Duplicate registrations not handled as efficiently as they should be
-
- Revision 1.161  2003/06/03 18:29:03  cheshire
- Minor changes to comments and debugf() messages
-
- Revision 1.160  2003/06/03 05:02:16  cheshire
- <rdar://problem/3277080> Duplicate registrations not handled as efficiently as they should be
-
- Revision 1.159  2003/06/03 03:31:57  cheshire
- <rdar://problem/3277033> False self-conflict when there are duplicate registrations on one machine
-
- Revision 1.158  2003/06/02 22:57:09  cheshire
- Minor clarifying changes to comments and log messages;
- IdenticalResourceRecordAnyInterface() is really more accurately called just IdenticalResourceRecord()
-
- Revision 1.157  2003/05/31 00:09:49  cheshire
- <rdar://problem/3274862> Add ability to discover what services are on a network
-
- Revision 1.156  2003/05/30 23:56:49  cheshire
- <rdar://problem/3274847> Crash after error in mDNS_RegisterService()
- Need to set "sr->Extras = mDNSNULL" before returning
-
- Revision 1.155  2003/05/30 23:48:00  cheshire
- <rdar://problem/3274832> Announcements not properly grouped
- Due to inconsistent setting of rr->LastAPTime at different places in the
- code, announcements were not properly grouped into a single packet.
- Fixed by creating a single routine called InitializeLastAPTime().
-
- Revision 1.154  2003/05/30 23:38:14  cheshire
- <rdar://problem/3274814> Fix error in IPv6 reverse-mapping PTR records
- Wrote buffer[32] where it should have said buffer[64]
-
- Revision 1.153  2003/05/30 19:10:56  cheshire
- <rdar://problem/3274153> ConstructServiceName needs to be more restrictive
-
- Revision 1.152  2003/05/29 22:39:16  cheshire
- <rdar://problem/3273209> Don't truncate strings in the middle of a UTF-8 character
-
- Revision 1.151  2003/05/29 06:35:42  cheshire
- <rdar://problem/3272221> mDNSCoreReceiveResponse() purging wrong record
-
- Revision 1.150  2003/05/29 06:25:45  cheshire
- <rdar://problem/3272218> Need to call CheckCacheExpiration() *before* AnswerNewQuestion()
-
- Revision 1.149  2003/05/29 06:18:39  cheshire
- <rdar://problem/3272217> Split AnswerLocalQuestions into CacheRecordAdd and CacheRecordRmv
-
- Revision 1.148  2003/05/29 06:11:34  cheshire
- <rdar://problem/3272214> Report if there appear to be too many "Resolve" callbacks
-
- Revision 1.147  2003/05/29 06:01:18  cheshire
- Change some debugf() calls to LogMsg() calls to help with debugging
-
- Revision 1.146  2003/05/28 21:00:44  cheshire
- Re-enable "immediate answer burst" debugf message
-
- Revision 1.145  2003/05/28 20:57:44  cheshire
- <rdar://problem/3271550> mDNSResponder reports "Cannot perform multi-packet
- known-answer suppression ..." This is a known issue caused by a bug in the OS X 10.2
- version of mDNSResponder, so for now we should suppress this warning message.
-
- Revision 1.144  2003/05/28 18:05:12  cheshire
- <rdar://problem/3009899> mDNSResponder allows invalid service registrations
- Fix silly mistake: old logic allowed "TDP" and "UCP" as valid names
-
- Revision 1.143  2003/05/28 04:31:29  cheshire
- <rdar://problem/3270733> mDNSResponder not sending probes at the prescribed time
-
- Revision 1.142  2003/05/28 03:13:07  cheshire
- <rdar://problem/3009899> mDNSResponder allows invalid service registrations
- Require that the transport protocol be _udp or _tcp
-
- Revision 1.141  2003/05/28 02:19:12  cheshire
- <rdar://problem/3270634> Misleading messages generated by iChat
- Better fix: Only generate the log message for queries where the TC bit is set.
-
- Revision 1.140  2003/05/28 01:55:24  cheshire
- Minor change to log messages
-
- Revision 1.139  2003/05/28 01:52:51  cheshire
- <rdar://problem/3270634> Misleading messages generated by iChat
-
- Revision 1.138  2003/05/27 22:35:00  cheshire
- <rdar://problem/3270277> mDNS_RegisterInterface needs to retrigger questions
-
- Revision 1.137  2003/05/27 20:04:33  cheshire
- <rdar://problem/3269900> mDNSResponder crash in mDNS_vsnprintf()
-
- Revision 1.136  2003/05/27 18:50:07  cheshire
- <rdar://problem/3269768> mDNS_StartResolveService doesn't inform client of port number changes
-
- Revision 1.135  2003/05/26 04:57:28  cheshire
- <rdar://problem/3268953> Delay queries when there are already answers in the cache
-
- Revision 1.134  2003/05/26 04:54:54  cheshire
- <rdar://problem/3268904> sprintf/vsprintf-style functions are unsafe; use snprintf/vsnprintf instead
- Accidentally deleted '%' case from the switch statement
-
- Revision 1.133  2003/05/26 03:21:27  cheshire
- Tidy up address structure naming:
- mDNSIPAddr         => mDNSv4Addr (for consistency with mDNSv6Addr)
- mDNSAddr.addr.ipv4 => mDNSAddr.ip.v4
- mDNSAddr.addr.ipv6 => mDNSAddr.ip.v6
-
- Revision 1.132  2003/05/26 03:01:26  cheshire
- <rdar://problem/3268904> sprintf/vsprintf-style functions are unsafe; use snprintf/vsnprintf instead
-
- Revision 1.131  2003/05/26 00:42:05  cheshire
- <rdar://problem/3268876> Temporarily include mDNSResponder version in packets
-
- Revision 1.130  2003/05/24 16:39:48  cheshire
- <rdar://problem/3268631> SendResponses also needs to handle multihoming better
-
- Revision 1.129  2003/05/23 02:15:37  cheshire
- Fixed misleading use of the term "duplicate suppression" where it should have
- said "known answer suppression". (Duplicate answer suppression is something
- different, and duplicate question suppression is yet another thing, so the use
- of the completely vague term "duplicate suppression" was particularly bad.)
-
- Revision 1.128  2003/05/23 01:55:13  cheshire
- <rdar://problem/3267127> After name change, mDNSResponder needs to re-probe for name uniqueness
-
- Revision 1.127  2003/05/23 01:02:15  ksekar
- Bug #: <rdar://problem/3032577>: mDNSResponder needs to include unique id in default name
-
- Revision 1.126  2003/05/22 02:29:22  cheshire
- <rdar://problem/2984918> SendQueries needs to handle multihoming better
- Complete rewrite of SendQueries. Works much better now :-)
-
- Revision 1.125  2003/05/22 01:50:45  cheshire
- Fix warnings, and improve log messages
-
- Revision 1.124  2003/05/22 01:41:50  cheshire
- DiscardDeregistrations doesn't need InterfaceID parameter
-
- Revision 1.123  2003/05/22 01:38:55  cheshire
- Change bracketing of #pragma mark
-
- Revision 1.122  2003/05/21 19:59:04  cheshire
- <rdar://problem/3148431> ER: Tweak responder's default name conflict behavior
- Minor refinements; make sure we don't truncate in the middle of a multi-byte UTF-8 character
-
- Revision 1.121  2003/05/21 17:54:07  ksekar
- Bug #: <rdar://problem/3148431> ER: Tweak responder's default name conflict behavior
- New rename behavior - domain name "foo" becomes "foo--2" on conflict, richtext name becomes "foo (2)"
-
- Revision 1.120  2003/05/19 22:14:14  ksekar
- <rdar://problem/3162914> mDNS probe denials/conflicts not detected unless conflict is of the same type
-
- Revision 1.119  2003/05/16 01:34:10  cheshire
- Fix some warnings
-
- Revision 1.118  2003/05/14 18:48:40  cheshire
- <rdar://problem/3159272> mDNSResponder should be smarter about reconfigurations
- More minor refinements:
- CFSocket.c needs to do *all* its mDNS_DeregisterInterface calls before freeing memory
- mDNS_DeregisterInterface revalidates cache record when *any* representative of an interface goes away
-
- Revision 1.117  2003/05/14 07:08:36  cheshire
- <rdar://problem/3159272> mDNSResponder should be smarter about reconfigurations
- Previously, when there was any network configuration change, mDNSResponder
- would tear down the entire list of active interfaces and start again.
- That was very disruptive, and caused the entire cache to be flushed,
- and caused lots of extra network traffic. Now it only removes interfaces
- that have really gone, and only adds new ones that weren't there before.
-
- Revision 1.116  2003/05/14 06:51:56  cheshire
- <rdar://problem/3027144> Rendezvous doesn't refresh server info if changed during sleep
-
- Revision 1.115  2003/05/14 06:44:31  cheshire
- Improve debugging message
-
- Revision 1.114  2003/05/07 01:47:03  cheshire
- <rdar://problem/3250330> Also protect against NULL domainlabels
-
- Revision 1.113  2003/05/07 00:28:18  cheshire
- <rdar://problem/3250330> Need to make mDNSResponder more defensive against bad clients
-
- Revision 1.112  2003/05/06 00:00:46  cheshire
- <rdar://problem/3248914> Rationalize naming of domainname manipulation functions
-
- Revision 1.111  2003/05/05 23:42:08  cheshire
- <rdar://problem/3245631> Resolves never succeed
- Was setting "rr->LastAPTime = timenow - rr->LastAPTime"
- instead of  "rr->LastAPTime = timenow - rr->ThisAPInterval"
-
- Revision 1.110  2003/04/30 21:09:59  cheshire
- <rdar://problem/3244727> mDNS_vsnprintf needs to be more defensive against invalid domain names
-
- Revision 1.109  2003/04/26 02:41:56  cheshire
- <rdar://problem/3241281> Change timenow from a local variable to a structure member
-
- Revision 1.108  2003/04/25 01:45:56  cheshire
- <rdar://problem/3240002> mDNS_RegisterNoSuchService needs to include a host name
-
- Revision 1.107  2003/04/25 00:41:31  cheshire
- <rdar://problem/3239912> Create single routine PurgeCacheResourceRecord(), to avoid bugs in future
-
- Revision 1.106  2003/04/22 03:14:45  cheshire
- <rdar://problem/3232229> Include Include instrumented mDNSResponder in panther now
-
- Revision 1.105  2003/04/22 01:07:43  cheshire
- <rdar://problem/3176248> DNSServiceRegistrationUpdateRecord should support a default ttl
- If TTL parameter is zero, leave record TTL unchanged
-
- Revision 1.104  2003/04/21 19:15:52  cheshire
- Fix some compiler warnings
-
- Revision 1.103  2003/04/19 02:26:35  cheshire
- Bug #: <rdar://problem/3233804> Incorrect goodbye packet after conflict
-
- Revision 1.102  2003/04/17 03:06:28  cheshire
- Bug #: <rdar://problem/3231321> No need to query again when a service goes away
- Set UnansweredQueries to 2 when receiving a "goodbye" packet
-
- Revision 1.101  2003/04/15 20:58:31  jgraessl
- Bug #: 3229014
- Added a hash to lookup records in the cache.
-
- Revision 1.100  2003/04/15 18:53:14  cheshire
- Bug #: <rdar://problem/3229064> Bug in ScheduleNextTask
- mDNS.c 1.94 incorrectly combined two "if" statements into one.
-
- Revision 1.99  2003/04/15 18:09:13  jgraessl
- Bug #: 3228892
- Reviewed by: Stuart Cheshire
- Added code to keep track of when the next cache item will expire so we can
- call TidyRRCache only when necessary.
-
- Revision 1.98  2003/04/03 03:43:55  cheshire
- <rdar://problem/3216837> Off-by-one error in probe rate limiting
-
- Revision 1.97  2003/04/02 01:48:17  cheshire
- <rdar://problem/3212360> mDNSResponder sometimes suffers false self-conflicts when it sees its own packets
- Additional fix pointed out by Josh:
- Also set ProbeFailTime when incrementing NumFailedProbes when resetting a record back to probing state
-
- Revision 1.96  2003/04/01 23:58:55  cheshire
- Minor comment changes
-
- Revision 1.95  2003/04/01 23:46:05  cheshire
- <rdar://problem/3214832> mDNSResponder can get stuck in infinite loop after many location cycles
- mDNS_DeregisterInterface() flushes the RR cache by marking all records received on that interface
- to expire in one second. However, if a mDNS_StartResolveService() call is made in that one-second
- window, it can get an SRV answer from one of those soon-to-be-deleted records, resulting in
- FoundServiceInfoSRV() making an interface-specific query on the interface that was just removed.
-
- Revision 1.94  2003/03/29 01:55:19  cheshire
- <rdar://problem/3212360> mDNSResponder sometimes suffers false self-conflicts when it sees its own packets
- Solution: Major cleanup of packet timing and conflict handling rules
-
- Revision 1.93  2003/03/28 01:54:36  cheshire
- Minor tidyup of IPv6 (AAAA) code
-
- Revision 1.92  2003/03/27 03:30:55  cheshire
- <rdar://problem/3210018> Name conflicts not handled properly, resulting in memory corruption, and eventual crash
- Problem was that HostNameCallback() was calling mDNS_DeregisterInterface(), which is not safe in a callback
- Fixes:
- 1. Make mDNS_DeregisterInterface() safe to call from a callback
- 2. Make HostNameCallback() use mDNS_DeadvertiseInterface() instead
- (it never really needed to deregister the interface at all)
-
- Revision 1.91  2003/03/15 04:40:36  cheshire
- Change type called "mDNSOpaqueID" to the more descriptive name "mDNSInterfaceID"
-
- Revision 1.90  2003/03/14 20:26:37  cheshire
- Reduce debugging messages (reclassify some "debugf" as "verbosedebugf")
-
- Revision 1.89  2003/03/12 19:57:50  cheshire
- Fixed typo in debug message
-
- Revision 1.88  2003/03/12 00:17:44  cheshire
- <rdar://problem/3195426> GetFreeCacheRR needs to be more willing to throw away recent records
-
- Revision 1.87  2003/03/11 01:27:20  cheshire
- Reduce debugging messages (reclassify some "debugf" as "verbosedebugf")
-
- Revision 1.86  2003/03/06 20:44:33  cheshire
- Comment tidyup
-
- Revision 1.85  2003/03/05 03:38:35  cheshire
- Bug #: 3185731 Bogus error message in console: died or deallocated, but no record of client can be found!
- Fixed by leaving client in list after conflict, until client explicitly deallocates
-
- Revision 1.84  2003/03/05 01:27:30  cheshire
- Bug #: 3185482 Different TTL for multicast versus unicast responses
- When building unicast responses, record TTLs are capped to 10 seconds
-
- Revision 1.83  2003/03/04 23:48:52  cheshire
- Bug #: 3188865 Double probes after wake from sleep
- Don't reset record type to kDNSRecordTypeUnique if record is DependentOn another
-
- Revision 1.82  2003/03/04 23:38:29  cheshire
- Bug #: 3099194 mDNSResponder needs performance improvements
- Only set rr->CRActiveQuestion to point to the
- currently active representative of a question set
-
- Revision 1.81  2003/02/21 03:35:34  cheshire
- Bug #: 3179007 mDNSResponder needs to include AAAA records in additional answer section
-
- Revision 1.80  2003/02/21 02:47:53  cheshire
- Bug #: 3099194 mDNSResponder needs performance improvements
- Several places in the code were calling CacheRRActive(), which searched the entire
- question list every time, to see if this cache resource record answers any question.
- Instead, we now have a field "CRActiveQuestion" in the resource record structure
-
- Revision 1.79  2003/02/21 01:54:07  cheshire
- Bug #: 3099194 mDNSResponder needs performance improvements
- Switched to using new "mDNS_Execute" model (see "Implementer Notes.txt")
-
- Revision 1.78  2003/02/20 06:48:32  cheshire
- Bug #: 3169535 Xserve RAID needs to do interface-specific registrations
- Reviewed by: Josh Graessley, Bob Bradley
-
- Revision 1.77  2003/01/31 03:35:59  cheshire
- Bug #: 3147097 mDNSResponder sometimes fails to find the correct results
- When there were *two* active questions in the list, they were incorrectly
- finding *each other* and *both* being marked as duplicates of another question
-
- Revision 1.76  2003/01/29 02:46:37  cheshire
- Fix for IPv6:
- A physical interface is identified solely by its InterfaceID (not by IP and type).
- On a given InterfaceID, mDNSCore may send both v4 and v6 multicasts.
- In cases where the requested outbound protocol (v4 or v6) is not supported on
- that InterfaceID, the platform support layer should simply discard that packet.
-
- Revision 1.75  2003/01/29 01:47:40  cheshire
- Rename 'Active' to 'CRActive' or 'InterfaceActive' for improved clarity
-
- Revision 1.74  2003/01/28 05:26:25  cheshire
- Bug #: 3147097 mDNSResponder sometimes fails to find the correct results
- Add 'Active' flag for interfaces
-
- Revision 1.73  2003/01/28 03:45:12  cheshire
- Fixed missing "not" in "!mDNSAddrIsDNSMulticast(dstaddr)"
-
- Revision 1.72  2003/01/28 01:49:48  cheshire
- Bug #: 3147097 mDNSResponder sometimes fails to find the correct results
- FindDuplicateQuestion() was incorrectly finding the question itself in the list,
- and incorrectly marking it as a duplicate (of itself), so that it became inactive.
-
- Revision 1.71  2003/01/28 01:41:44  cheshire
- Bug #: 3153091 Race condition when network change causes bad stuff
- When an interface goes away, interface-specific questions on that interface become orphaned.
- Orphan questions cause HaveQueries to return true, but there's no interface to send them on.
- Fix: mDNS_DeregisterInterface() now calls DeActivateInterfaceQuestions()
-
- Revision 1.70  2003/01/23 19:00:20  cheshire
- Protect against infinite loops in mDNS_Execute
-
- Revision 1.69  2003/01/21 22:56:32  jgraessl
- Bug #: 3124348  service name changes are not properly handled
- Submitted by: Stuart Cheshire
- Reviewed by: Joshua Graessley
- Applying changes for 3124348 to main branch. 3124348 changes went in to a
- branch for SU.
-
- Revision 1.68  2003/01/17 04:09:27  cheshire
- Bug #: 3141038 mDNSResponder Resolves are unreliable on multi-homed hosts
-
- Revision 1.67  2003/01/17 03:56:45  cheshire
- Default 24-hour TTL is far too long. Changing to two hours.
-
- Revision 1.66  2003/01/13 23:49:41  jgraessl
- Merged changes for the following fixes in to top of tree:
- 3086540  computer name changes not handled properly
- 3124348  service name changes are not properly handled
- 3124352  announcements sent in pairs, failing chattiness test
-
- Revision 1.65  2002/12/23 22:13:28  jgraessl
- Reviewed by: Stuart Cheshire
- Initial IPv6 support for mDNSResponder.
-
- Revision 1.64  2002/11/26 20:49:06  cheshire
- Bug #: 3104543 RFC 1123 allows the first character of a name label to be either a letter or a digit
-
- Revision 1.63  2002/09/21 20:44:49  zarzycki
- Added APSL info
-
- Revision 1.62  2002/09/20 03:25:37  cheshire
- Fix some compiler warnings
-
- Revision 1.61  2002/09/20 01:05:24  cheshire
- Don't kill the Extras list in mDNS_DeregisterService()
-
- Revision 1.60  2002/09/19 23:47:35  cheshire
- Added mDNS_RegisterNoSuchService() function for assertion of non-existance
- of a particular named service
-
- Revision 1.59  2002/09/19 21:25:34  cheshire
- mDNS_snprintf() doesn't need to be in a separate file
-
- Revision 1.58  2002/09/19 04:20:43  cheshire
- Remove high-ascii characters that confuse some systems
-
- Revision 1.57  2002/09/17 01:07:08  cheshire
- Change mDNS_AdvertiseLocalAddresses to be a parameter to mDNS_Init()
-
- Revision 1.56  2002/09/16 19:44:17  cheshire
- Merge in license terms from Quinn's copy, in preparation for Darwin release
-*/
-
-#define TEST_LOCALONLY_FOR_EVERYTHING 0
-#include "wm_mem.h"
-#include "mDNSClientAPI.h"				// Defines the interface provided to the client layer above
-#include "mDNSPlatformFunctions.h"		// Defines the interface required of the supporting layer below
-
-// Disable certain benign warnings with Microsoft compilers
-#if(defined(_MSC_VER))
-// Disable "conditional expression is constant" warning for debug macros.
-// Otherwise, this generates warnings for the perfectly natural construct "while(1)"
-// If someone knows a variant way of writing "while(1)" that doesn't generate warning messages, please let us know
-#pragma warning(disable:4127)
-	
-// Disable "const object should be initialized"
-// We know that static/globals are defined to be zeroed in ANSI C, and to avoid this warning would require some
-// *really* ugly chunk of zeroes and curly braces to initialize zeroRR and mDNSprintf_format_default to all zeroes
-#pragma warning(disable:4132)
-	
-// Disable "assignment within conditional expression".
-// Other compilers understand the convention that if you place the assignment expression within an extra pair
-// of parentheses, this signals to the compiler that you really intended an assignment and no warning is necessary.
-// The Microsoft compiler doesn't understand this convention, so in the absense of any other way to signal
-// to the compiler that the assignment is intentional, we have to just turn this warning off completely.
-#pragma warning(disable:4706)
-#endif
-
-// ***************************************************************************
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark - DNS Protocol Constants
-#endif
-
-typedef enum
-{
-	kDNSFlag0_QR_Mask     = 0x80,		// Query or response?
-	kDNSFlag0_QR_Query    = 0x00,
-	kDNSFlag0_QR_Response = 0x80,
-	
-	kDNSFlag0_OP_Mask     = 0x78,		// Operation type
-	kDNSFlag0_OP_StdQuery = 0x00,
-	kDNSFlag0_OP_Iquery   = 0x08,
-	kDNSFlag0_OP_Status   = 0x10,
-	kDNSFlag0_OP_Unused3  = 0x18,
-	kDNSFlag0_OP_Notify   = 0x20,
-	kDNSFlag0_OP_Update   = 0x28,
-	
-	kDNSFlag0_QROP_Mask   = kDNSFlag0_QR_Mask | kDNSFlag0_OP_Mask,
-	
-	kDNSFlag0_AA          = 0x04,		// Authoritative Answer?
-	kDNSFlag0_TC          = 0x02,		// Truncated?
-	kDNSFlag0_RD          = 0x01,		// Recursion Desired?
-	kDNSFlag1_RA          = 0x80,		// Recursion Available?
-	
-	kDNSFlag1_Zero        = 0x40,		// Reserved; must be zero
-	kDNSFlag1_AD          = 0x20,		// Authentic Data [RFC 2535]
-	kDNSFlag1_CD          = 0x10,		// Checking Disabled [RFC 2535]
-
-	kDNSFlag1_RC          = 0x0F,		// Response code
-	kDNSFlag1_RC_NoErr    = 0x00,
-	kDNSFlag1_RC_FmtErr   = 0x01,
-	kDNSFlag1_RC_SrvErr   = 0x02,
-	kDNSFlag1_RC_NXDomain = 0x03,
-	kDNSFlag1_RC_NotImpl  = 0x04,
-	kDNSFlag1_RC_Refused  = 0x05,
-	kDNSFlag1_RC_YXDomain = 0x06,
-	kDNSFlag1_RC_YXRRSet  = 0x07,
-	kDNSFlag1_RC_NXRRSet  = 0x08,
-	kDNSFlag1_RC_NotAuth  = 0x09,
-	kDNSFlag1_RC_NotZone  = 0x0A
-} DNS_Flags;
-
-// ***************************************************************************
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - Program Constants
-#endif
-
-mDNSexport const ResourceRecord  zeroRR;
-mDNSexport const mDNSIPPort      zeroIPPort        = { { 0 } };
-mDNSexport const mDNSv4Addr      zeroIPAddr        = { { 0 } };
-mDNSexport const mDNSv6Addr      zerov6Addr        = { { 0 } };
-mDNSexport const mDNSv4Addr      onesIPv4Addr      = { { 255, 255, 255, 255 } };
-mDNSexport const mDNSv6Addr      onesIPv6Addr      = { { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } };
-//mDNSlocal  const mDNSAddr        zeroAddr          = { mDNSAddrType_None, {{{ 0 }}} };
-
-mDNSexport const mDNSInterfaceID mDNSInterface_Any = { 0 };
-mDNSlocal  const mDNSInterfaceID mDNSInterfaceMark = { (mDNSInterfaceID)~0 };
-
-#define UnicastDNSPortAsNumber 53
-#define MulticastDNSPortAsNumber 5353
-mDNSexport const mDNSIPPort UnicastDNSPort     = { { UnicastDNSPortAsNumber   >> 8, UnicastDNSPortAsNumber   & 0xFF } };
-mDNSexport const mDNSIPPort MulticastDNSPort   = { { MulticastDNSPortAsNumber >> 8, MulticastDNSPortAsNumber & 0xFF } };
-mDNSexport const mDNSv4Addr AllDNSAdminGroup   = { { 239, 255, 255, 251 } };
-mDNSexport const mDNSv4Addr AllDNSLinkGroup    = { { 224,   0,   0, 251 } };
-mDNSexport const mDNSv6Addr AllDNSLinkGroupv6  = { { 0xFF,0x02,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xFB } };
-mDNSexport const mDNSAddr   AllDNSLinkGroup_v4 = { mDNSAddrType_IPv4, { { { 224,   0,   0, 251 } } } };
-mDNSexport const mDNSAddr   AllDNSLinkGroup_v6 = { mDNSAddrType_IPv6, { { { 0xFF,0x02,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xFB } } } };
-
-static const mDNSOpaque16 zeroID = { { 0, 0 } };
-static const mDNSOpaque16 QueryFlags    = { { kDNSFlag0_QR_Query    | kDNSFlag0_OP_StdQuery,                0 } };
-static const mDNSOpaque16 ResponseFlags = { { kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery | kDNSFlag0_AA, 0 } };
-#define zeroDomainNamePtr ((domainname*)"")
-
-// Any records bigger than this are considered 'large' records
-#define SmallRecordLimit 1024
-
-#define kDefaultTTLforUnique 240
-#define kDefaultTTLforShared (2*3600)
-
-#define kMaxUpdateCredits 10
-
-#define kNextScheduledTime   0x14000
-/*
-static const char *const mDNS_DomainTypeNames[] =
-{
-	"_browse._dns-sd._udp.local.",
-	"_default._browse._dns-sd._udp.local.",
-	"_register._dns-sd._udp.local.",
-	"_default._register._dns-sd._udp.local."
-};
-*/
-#define AssignDomainName(DST, SRC) mDNSPlatformMemCopy((SRC).c, (DST).c, DomainNameLength(&(SRC)))
-
-// ***************************************************************************
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - Specialized mDNS version of vsnprintf
-#endif
-
-#include <stdio.h>
-#include <string.h>
-//#include <asm/types.h>
-
-static const struct mDNSprintf_format
-{
-	unsigned      leftJustify : 1;
-	unsigned      forceSign : 1;
-	unsigned      zeroPad : 1;
-	unsigned      havePrecision : 1;
-	unsigned      hSize : 1;
-	unsigned      lSize : 1;
-	char          altForm;
-	char          sign;		// +, - or space
-	unsigned int  fieldWidth;
-	unsigned int  precision;
-} mDNSprintf_format_default;
-
-mDNSexport mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, va_list arg)
-{
-	mDNSu32 nwritten = 0;
-	int c;
-	buflen--;		// Pre-reserve one space in the buffer for the terminating nul
-	#define mDNS_VACB_Size 300
-	char *mDNS_VACB = tls_mem_alloc(mDNS_VACB_Size);
-	if(!mDNS_VACB) goto exit;
-	memset(mDNS_VACB, 0, mDNS_VACB_Size);
-	for (c = *fmt; c != 0; c = *++fmt)
-	{
-		if (c != '%')
-		{
-			*sbuffer++ = (char)c;
-			if (++nwritten >= buflen) goto exit;
-		}
-		else
-		{
-			unsigned int i=0, j;
-			// The mDNS Vsprintf Argument Conversion Buffer is used as a temporary holding area for
-			// generating decimal numbers, hexdecimal numbers, IP addresses, domain name strings, etc.
-			// The size needs to be enough for a 256-byte domain name plus some error text.
-
-#define mDNS_VACB_Lim (&mDNS_VACB[mDNS_VACB_Size])
-#define mDNS_VACB_Remain(s) ((mDNSu32)(mDNS_VACB_Lim - s))
-			char *s = mDNS_VACB_Lim, *digits;
-			struct mDNSprintf_format F = mDNSprintf_format_default;
-	
-			while (1)	//  decode flags
-			{
-				c = *++fmt;
-				if      (c == '-') F.leftJustify = 1;
-				else if (c == '+') F.forceSign = 1;
-				else if (c == ' ') F.sign = ' ';
-				else if (c == '#') F.altForm++;
-				else if (c == '0') F.zeroPad = 1;
-				else break;
-			}
-	
-			if (c == '*')	//  decode field width
-			{
-				int f = va_arg(arg, int);
-				if (f < 0) { f = -f; F.leftJustify = 1; }
-				F.fieldWidth = (unsigned int)f;
-				c = *++fmt;
-			}
-			else
-			{
-				for (; c >= '0' && c <= '9'; c = *++fmt)
-					F.fieldWidth = (10 * F.fieldWidth) + (c - '0');
-			}
-	
-			if (c == '.')	//  decode precision
-			{
-				if ((c = *++fmt) == '*')
-				{ F.precision = va_arg(arg, unsigned int); c = *++fmt; }
-				else for (; c >= '0' && c <= '9'; c = *++fmt)
-					F.precision = (10 * F.precision) + (c - '0');
-				F.havePrecision = 1;
-			}
-	
-			if (F.leftJustify) F.zeroPad = 0;
-	
-		conv:
-			switch (c)	//  perform appropriate conversion
-			{
-				unsigned long n;
-			case 'h' :	F.hSize = 1; c = *++fmt; goto conv;
-			case 'l' :	// fall through
-			case 'L' :	F.lSize = 1; c = *++fmt; goto conv;
-			case 'd' :
-			case 'i' :	if (F.lSize) n = (unsigned long)va_arg(arg, long);
-			else n = (unsigned long)va_arg(arg, int);
-				if (F.hSize) n = (short) n;
-				if ((long) n < 0) { n = (unsigned long)-(long)n; F.sign = '-'; }
-				else if (F.forceSign) F.sign = '+';
-				goto decimal;
-			case 'u' :	if (F.lSize) n = va_arg(arg, unsigned long);
-			else n = va_arg(arg, unsigned int);
-				if (F.hSize) n = (unsigned short) n;
-				F.sign = 0;
-				goto decimal;
-			decimal:	if (!F.havePrecision)
-			{
-				if (F.zeroPad)
-				{
-					F.precision = F.fieldWidth;
-					if (F.sign) --F.precision;
-				}
-				if (F.precision < 1) F.precision = 1;
-			}
-				if (F.precision > mDNS_VACB_Size - 1)
-					F.precision = mDNS_VACB_Size - 1;
-				for (i = 0; n; n /= 10, i++) *--s = (char)(n % 10 + '0');
-				for (; i < F.precision; i++) *--s = '0';
-				if (F.sign) { *--s = F.sign; i++; }
-				break;
-	
-			case 'o' :	if (F.lSize) n = va_arg(arg, unsigned long);
-			else n = va_arg(arg, unsigned int);
-				if (F.hSize) n = (unsigned short) n;
-				if (!F.havePrecision)
-				{
-					if (F.zeroPad) F.precision = F.fieldWidth;
-					if (F.precision < 1) F.precision = 1;
-				}
-				if (F.precision > mDNS_VACB_Size - 1)
-					F.precision = mDNS_VACB_Size - 1;
-				for (i = 0; n; n /= 8, i++) *--s = (char)(n % 8 + '0');
-				if (F.altForm && i && *s != '0') { *--s = '0'; i++; }
-				for (; i < F.precision; i++) *--s = '0';
-				break;
-	
-			case 'a' :	{
-				unsigned char *a = va_arg(arg, unsigned char *);
-				if (!a) { static char emsg[] = "<<NULL>>"; s = emsg; i = sizeof(emsg)-1; }
-				else
-				{
-					unsigned short *w = (unsigned short *)a;
-					s = mDNS_VACB;	// Adjust s to point to the start of the buffer, not the end
-					if (F.altForm)
-					{
-						mDNSAddr *ip = (mDNSAddr*)a;
-						a = (unsigned char  *)&ip->ip.v4;
-						w = (unsigned short *)&ip->ip.v6;
-						switch (ip->type)
-						{
-						case mDNSAddrType_IPv4: F.precision =  4; break;
-						case mDNSAddrType_IPv6: F.precision = 16; break;
-						default:                F.precision =  0; break;
-						}
-					}
-					switch (F.precision)
-					{
-					case  4: i = mDNS_snprintf(mDNS_VACB, mDNS_VACB_Size, "%d.%d.%d.%d",
-								   a[0], a[1], a[2], a[3]); break;
-					case  6: i = mDNS_snprintf(mDNS_VACB, mDNS_VACB_Size, "%02X:%02X:%02X:%02X:%02X:%02X",
-								   a[0], a[1], a[2], a[3], a[4], a[5]); break;
-					case 16: i = mDNS_snprintf(mDNS_VACB, mDNS_VACB_Size, "%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X",
-								   w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7]); break;
-					default: i = mDNS_snprintf(mDNS_VACB, mDNS_VACB_Size, "%s", "<< ERROR: Must specify address size "
-								   "(i.e. %.4a=IPv4, %.6a=Ethernet, %.16a=IPv6) >>"); break;
-					}
-				}
-			}
-				break;
-	
-			case 'p' :	F.havePrecision = F.lSize = 1;
-				F.precision = 8;
-			case 'X' :	digits = "0123456789ABCDEF";
-				goto hexadecimal;
-			case 'x' :	digits = "0123456789abcdef";
-			hexadecimal:if (F.lSize) n = va_arg(arg, unsigned long);
-			else n = va_arg(arg, unsigned int);
-			if (F.hSize) n = (unsigned short) n;
-			if (!F.havePrecision)
-			{
-				if (F.zeroPad)
-				{
-					F.precision = F.fieldWidth;
-					if (F.altForm) F.precision -= 2;
-				}
-				if (F.precision < 1) F.precision = 1;
-			}
-			if (F.precision > mDNS_VACB_Size - 1)
-				F.precision = mDNS_VACB_Size - 1;
-			for (i = 0; n; n /= 16, i++) *--s = digits[n % 16];
-			for (; i < F.precision; i++) *--s = '0';
-			if (F.altForm) { *--s = (char)c; *--s = '0'; i += 2; }
-			break;
-	
-			case 'c' :	*--s = (char)va_arg(arg, int); i = 1; break;
-	
-			case 's' :	s = va_arg(arg, char *);
-				if (!s) { static char emsg[] = "<<NULL>>"; s = emsg; i = sizeof(emsg)-1; }
-				else switch (F.altForm)
-				{
-				case 0: { char *a=s; i=0; while(*a++) i++; break; }	// C string
-				case 1: i = (unsigned char) *s++; break;	// Pascal string
-				case 2: {									// DNS label-sequence name
-					unsigned char *a = (unsigned char *)s;
-					s = mDNS_VACB;	// Adjust s to point to the start of the buffer, not the end
-					if (*a == 0) *s++ = '.';	// Special case for root DNS name
-					while (*a)
-					{
-						if (*a > 63) { s += mDNS_snprintf(s, mDNS_VACB_Remain(s), "<<INVALID LABEL LENGTH %u>>", *a); break; }
-						if (s + *a >= &mDNS_VACB[254]) { s += mDNS_snprintf(s, mDNS_VACB_Remain(s), "<<NAME TOO LONG>>"); break; }
-						s += mDNS_snprintf(s, mDNS_VACB_Remain(s), "%#s.", a);
-						a += 1 + *a;
-					}
-					i = (mDNSu32)(s - mDNS_VACB);
-					s = mDNS_VACB;	// Reset s back to the start of the buffer
-					break;
-				}
-				}
-				if (F.havePrecision && i > F.precision)		// Make sure we don't truncate in the middle of a UTF-8 character
-				{ i = F.precision; while (i>0 && (s[i] & 0xC0) == 0x80) i--; }
-				break;
-	
-			case 'n' :	s = va_arg(arg, char *);
-				if      (F.hSize) * (short *) s = (short)nwritten;
-				else if (F.lSize) * (long  *) s = (long)nwritten;
-				else              * (int   *) s = (int)nwritten;
-				continue;
-	
-			default:	s = mDNS_VACB;
-				i = mDNS_snprintf(mDNS_VACB, mDNS_VACB_Size, "<<UNKNOWN FORMAT CONVERSION CODE %%%c>>", c);
-
-			case '%' :	*sbuffer++ = (char)c;
-				if (++nwritten >= buflen) goto exit;
-				break;
-			}
-	
-			if (i < F.fieldWidth && !F.leftJustify)			// Pad on the left
-				do	{
-					*sbuffer++ = ' ';
-					if (++nwritten >= buflen) goto exit;
-				} while (i < --F.fieldWidth);
-	
-			if (i > buflen - nwritten)	// Make sure we don't truncate in the middle of a UTF-8 character
-			{ i = buflen - nwritten; while (i>0 && (s[i] & 0xC0) == 0x80) i--; }
-			for (j=0; j<i; j++) *sbuffer++ = *s++;			// Write the converted result
-			nwritten += i;
-			if (nwritten >= buflen) goto exit;
-	
-			for (; i < F.fieldWidth; i++)					// Pad on the right
-			{
-				*sbuffer++ = ' ';
-				if (++nwritten >= buflen) goto exit;
-			}
-		}
-	}
- exit:
- 	if(mDNS_VACB)
-		tls_mem_free(mDNS_VACB);
-	*sbuffer++ = 0;
-	return(nwritten);
-}
-
-mDNSexport mDNSu32 mDNS_snprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, ...)
-{
-	mDNSu32 length;
-	
-	va_list ptr;
-	va_start(ptr,fmt);
-	length = mDNS_vsnprintf(sbuffer, buflen, fmt, ptr);
-	va_end(ptr);
-	
-	return(length);
-}
-
-// ***************************************************************************
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - General Utility Functions
-#endif
-
-mDNSexport char *DNSTypeName(mDNSu16 rrtype)
-{
-	switch (rrtype)
-	{
-	case kDNSType_A:    return("Addr");
-	case kDNSType_CNAME:return("CNAME");
-	case kDNSType_NULL: return("NULL");
-	case kDNSType_PTR:  return("PTR");
-	case kDNSType_HINFO:return("HINFO");
-	case kDNSType_TXT:  return("TXT");
-	case kDNSType_AAAA: return("AAAA");
-	case kDNSType_SRV:  return("SRV");
-	case kDNSQType_ANY: return("ANY");
-	default:			{
-		static char buffer[16];
-		mDNS_snprintf(buffer, sizeof(buffer), "(%d)", rrtype);
-		return(buffer);
-	}
-	}
-}
-
-mDNSexport char *GetRRDisplayString_rdb(mDNS *const m, const ResourceRecord *rr, RDataBody *rd)
-{
-	char *ptr = m->MsgBuffer;
-	mDNSu32 length = mDNS_snprintf(m->MsgBuffer, 79, "%4d %##s %s ", rr->rdlength, rr->name.c, DNSTypeName(rr->rrtype));
-	switch (rr->rrtype)
-	{
-	case kDNSType_A:	mDNS_snprintf(m->MsgBuffer+length, 79-length, "%.4a", &rd->ip);         break;
-	case kDNSType_CNAME:// Same as PTR
-	case kDNSType_PTR:	mDNS_snprintf(m->MsgBuffer+length, 79-length, "%##s", &rd->name);       break;
-	case kDNSType_HINFO:// Display this the same as TXT (just show first string)
-	case kDNSType_TXT:	mDNS_snprintf(m->MsgBuffer+length, 79-length, "%#s", rd->txt.c);	break;
-	case kDNSType_AAAA:	mDNS_snprintf(m->MsgBuffer+length, 79-length, "%.16a", &rd->ipv6);      break;
-	case kDNSType_SRV:	mDNS_snprintf(m->MsgBuffer+length, 79-length, "%##s", &rd->srv.target); break;
-	default:			mDNS_snprintf(m->MsgBuffer+length, 79-length, "RDLen %d: %s",
-						      rr->rdlength, rd->data);  break;
-	}
-	for (ptr = m->MsgBuffer; *ptr; ptr++) if (*ptr < ' ') *ptr='.';
-	return(m->MsgBuffer);
-}
-
-mDNSlocal mDNSu32 mDNSRandom(mDNSu32 max)
-{
-	static mDNSu32 seed = 0;
-	mDNSu32 mask = 1;
-	
-	if (!seed) seed = (mDNSu32)mDNSPlatformTimeNow();
-	while (mask < max) mask = (mask << 1) | 1;
-	do seed = seed * 21 + 1; while ((seed & mask) > max);
-	return (seed & mask);
-}
-
-#define mDNSSameIPv4Address(A,B) ((A).NotAnInteger == (B).NotAnInteger)
-#define mDNSSameIPv6Address(A,B) ((A).l[0] == (B).l[0] && (A).l[1] == (B).l[1] && (A).l[2] == (B).l[2] && (A).l[3] == (B).l[3])
-
-#define mDNSIPv4AddressIsZero(A) mDNSSameIPv4Address((A), zeroIPAddr)
-#define mDNSIPv6AddressIsZero(A) mDNSSameIPv6Address((A), zerov6Addr)
-
-#define mDNSIPv4AddressIsOnes(A) mDNSSameIPv4Address((A), onesIPv4Addr)
-#define mDNSIPv6AddressIsOnes(A) mDNSSameIPv6Address((A), onesIPv6Addr)
-
-#define mDNSAddressIsZero(X) (                                              \
-	((X)->type == mDNSAddrType_IPv4 && mDNSIPv4AddressIsZero((X)->ip.v4)) || \
-	((X)->type == mDNSAddrType_IPv6 && mDNSIPv6AddressIsZero((X)->ip.v6))    )
-
-#define mDNSAddressIsOnes(X) (                                              \
-	((X)->type == mDNSAddrType_IPv4 && mDNSIPv4AddressIsOnes((X)->ip.v4)) || \
-	((X)->type == mDNSAddrType_IPv6 && mDNSIPv6AddressIsOnes((X)->ip.v6))    )
-
-#define mDNSAddressIsValid(X) (                                                                                             \
-	((X)->type == mDNSAddrType_IPv4) ? !(mDNSIPv4AddressIsZero((X)->ip.v4) || mDNSIPv4AddressIsOnes((X)->ip.v4)) :          \
-	((X)->type == mDNSAddrType_IPv6) ? !(mDNSIPv6AddressIsZero((X)->ip.v6) || mDNSIPv6AddressIsOnes((X)->ip.v6)) : mDNSfalse)
-
-mDNSexport mDNSBool mDNSSameAddress(const mDNSAddr *ip1, const mDNSAddr *ip2)
-{
-	if (ip1->type == ip2->type)
-	{
-		switch (ip1->type)
-		{
-		case mDNSAddrType_IPv4 : return(mDNSBool)(mDNSSameIPv4Address(ip1->ip.v4, ip2->ip.v4));
-		case mDNSAddrType_IPv6 : return(mDNSBool)(mDNSSameIPv6Address(ip1->ip.v6, ip2->ip.v6));
-		}
-	}
-	return(mDNSfalse);
-}
-
-mDNSexport mDNSBool mDNSAddrIsDNSMulticast(const mDNSAddr *ip)
-{
-	switch(ip->type)
-	{
-	case mDNSAddrType_IPv4: return(mDNSBool)(ip->ip.v4.NotAnInteger == AllDNSLinkGroup.NotAnInteger);
-	case mDNSAddrType_IPv6: return(mDNSBool)(ip->ip.v6.l[0] == AllDNSLinkGroupv6.l[0] &&
-						 ip->ip.v6.l[1] == AllDNSLinkGroupv6.l[1] &&
-						 ip->ip.v6.l[2] == AllDNSLinkGroupv6.l[2] &&
-						 ip->ip.v6.l[3] == AllDNSLinkGroupv6.l[3] );
-	default: return(mDNSfalse);
-	}
-}
-
-mDNSlocal const NetworkInterfaceInfo *GetFirstActiveInterface(const NetworkInterfaceInfo *intf)
-{
-	while (intf && !intf->InterfaceActive) intf = intf->next;
-	return(intf);
-}
-
-mDNSlocal mDNSInterfaceID GetNextActiveInterfaceID(const NetworkInterfaceInfo *intf)
-{
-	const NetworkInterfaceInfo *next = GetFirstActiveInterface(intf->next);
-	if (next) return(next->InterfaceID); else return(mDNSNULL);
-}
-
-#define InitialQuestionInterval (mDNSPlatformOneSecond/2)
-#define ActiveQuestion(Q) ((Q)->ThisQInterval > 0 && !(Q)->DuplicateOf)
-#define TimeToSendThisQuestion(Q,time) (ActiveQuestion(Q) && (time) - ((Q)->LastQTime + (Q)->ThisQInterval) >= 0)
-
-mDNSlocal void SetNextQueryTime(mDNS *const m, const DNSQuestion *const q)
-{
-	if (ActiveQuestion(q))
-		if (m->NextScheduledQuery - (q->LastQTime + q->ThisQInterval) > 0)
-			m->NextScheduledQuery = (q->LastQTime + q->ThisQInterval);
-}
-
-// ***************************************************************************
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - Domain Name Utility Functions
-#endif
-
-#define mdnsIsDigit(X)     ((X) >= '0' && (X) <= '9')
-#define mDNSIsUpperCase(X) ((X) >= 'A' && (X) <= 'Z')
-#define mDNSIsLowerCase(X) ((X) >= 'a' && (X) <= 'z')
-#define mdnsIsLetter(X)    (mDNSIsUpperCase(X) || mDNSIsLowerCase(X))
-
-mDNSexport mDNSBool SameDomainLabel(const mDNSu8 *a, const mDNSu8 *b)
-{
-	int i;
-	const int len = *a++;
-
-	if (len > MAX_DOMAIN_LABEL)
-	{ debugf("Malformed label (too long)"); return(mDNSfalse); }
-
-	if (len != *b++) return(mDNSfalse);
-	for (i=0; i<len; i++)
-	{
-		mDNSu8 ac = *a++;
-		mDNSu8 bc = *b++;
-		if (mDNSIsUpperCase(ac)) ac += 'a' - 'A';
-		if (mDNSIsUpperCase(bc)) bc += 'a' - 'A';
-		if (ac != bc) return(mDNSfalse);
-	}
-	return(mDNStrue);
-}
-
-mDNSexport mDNSBool SameDomainName(const domainname *const d1, const domainname *const d2)
-{
-	const mDNSu8 *      a   = d1->c;
-	const mDNSu8 *      b   = d2->c;
-	const mDNSu8 *const max = d1->c + MAX_DOMAIN_NAME;			// Maximum that's valid
-
-	while (*a || *b)
-	{
-		if (a + 1 + *a >= max)
-		{ debugf("Malformed domain name (more than 255 characters)"); return(mDNSfalse); }
-		if (!SameDomainLabel(a, b)) return(mDNSfalse);
-		a += 1 + *a;
-		b += 1 + *b;
-	}
-	
-	return(mDNStrue);
-}
-
-// Returns length of a domain name INCLUDING the byte for the final null label
-// i.e. for the root label "." it returns one
-// For the FQDN "com." it returns 5 (length byte, three data bytes, final zero)
-// Legal results are 1 (just root label) to 255 (MAX_DOMAIN_NAME)
-// If the given domainname is invalid, result is 256
-mDNSexport mDNSu16 DomainNameLength(const domainname *const name)
-{
-	const mDNSu8 *src = name->c;
-	while (*src)
-	{
-		if (*src > MAX_DOMAIN_LABEL) return(MAX_DOMAIN_NAME+1);
-		src += 1 + *src;
-		if (src - name->c >= MAX_DOMAIN_NAME) return(MAX_DOMAIN_NAME+1);
-	}
-	return((mDNSu16)(src - name->c + 1));
-}
-
-// CompressedDomainNameLength returns the length of a domain name INCLUDING the byte
-// for the final null label i.e. for the root label "." it returns one.
-// E.g. for the FQDN "foo.com." it returns 9
-// (length, three data bytes, length, three more data bytes, final zero).
-// In the case where a parent domain name is provided, and the given name is a child
-// of that parent, CompressedDomainNameLength returns the length of the prefix portion
-// of the child name, plus TWO bytes for the compression pointer.
-// E.g. for the name "foo.com." with parent "com.", it returns 6
-// (length, three data bytes, two-byte compression pointer).
-mDNSlocal mDNSu16 CompressedDomainNameLength(const domainname *const name, const domainname *parent)
-{
-	const mDNSu8 *src = name->c;
-	if (parent && parent->c[0] == 0) parent = mDNSNULL;
-	while (*src)
-	{
-		if (*src > MAX_DOMAIN_LABEL) return(MAX_DOMAIN_NAME+1);
-		if (parent && SameDomainName((domainname *)src, parent)) return((mDNSu16)(src - name->c + 2));
-		//printf("%.*s\n", *src, src+1);
-		src += 1 + *src;
-		if (src - name->c >= MAX_DOMAIN_NAME) return(MAX_DOMAIN_NAME+1);
-	}
-	return((mDNSu16)(src - name->c + 1));
-}
-
-// AppendLiteralLabelString appends a single label to an existing (possibly empty) domainname.
-// The C string contains the label as-is, with no escaping, etc.
-// Any dots in the name are literal dots, not label separators
-// If successful, AppendLiteralLabelString returns a pointer to the next unused byte
-// in the domainname bufer (i.e., the next byte after the terminating zero).
-// If unable to construct a legal domain name (i.e. label more than 63 bytes, or total more than 255 bytes)
-// AppendLiteralLabelString returns mDNSNULL.
-mDNSexport mDNSu8 *AppendLiteralLabelString(domainname *const name, const char *cstr)
-{
-	mDNSu8       *      ptr  = name->c + DomainNameLength(name) - 1;	// Find end of current name
-	const mDNSu8 *const lim1 = name->c + MAX_DOMAIN_NAME - 1;			// Limit of how much we can add (not counting final zero)
-	const mDNSu8 *const lim2 = ptr + 1 + MAX_DOMAIN_LABEL;
-	const mDNSu8 *const lim  = (lim1 < lim2) ? lim1 : lim2;
-	mDNSu8       *lengthbyte = ptr++;									// Record where the length is going to go
-	
-	while (*cstr && ptr < lim) *ptr++ = (mDNSu8)*cstr++;	// Copy the data
-	*lengthbyte = (mDNSu8)(ptr - lengthbyte - 1);			// Fill in the length byte
-	*ptr++ = 0;												// Put the null root label on the end
-	if (*cstr) return(mDNSNULL);							// Failure: We didn't successfully consume all input
-	else return(ptr);										// Success: return new value of ptr
-}
-
-// AppendDNSNameString appends zero or more labels to an existing (possibly empty) domainname.
-// The C string is in conventional DNS syntax:
-// Textual labels, escaped as necessary using the usual DNS '\' notation, separated by dots.
-// If successful, AppendDNSNameString returns a pointer to the next unused byte
-// in the domainname bufer (i.e., the next byte after the terminating zero).
-// If unable to construct a legal domain name (i.e. label more than 63 bytes, or total more than 255 bytes)
-// AppendDNSNameString returns mDNSNULL.
-mDNSexport mDNSu8 *AppendDNSNameString(domainname *const name, const char *cstr)
-{
-	mDNSu8       *      ptr = name->c + DomainNameLength(name) - 1;	// Find end of current name
-	const mDNSu8 *const lim = name->c + MAX_DOMAIN_NAME - 1;		// Limit of how much we can add (not counting final zero)
-	while (*cstr && ptr < lim)										// While more characters, and space to put them...
-	{
-		mDNSu8 *lengthbyte = ptr++;									// Record where the length is going to go
-		while (*cstr && *cstr != '.' && ptr < lim)					// While we have characters in the label...
-		{
-			mDNSu8 c = (mDNSu8)*cstr++;								// Read the character
-			if (c == '\\')											// If escape character, check next character
-			{
-				if (*cstr == '\\' || *cstr == '.')					// If a second escape, or a dot,
-					c = (mDNSu8)*cstr++;							// just use the second character
-				else if (mdnsIsDigit(cstr[0]) && mdnsIsDigit(cstr[1]) && mdnsIsDigit(cstr[2]))
-				{												// else, if three decimal digits,
-					int v0 = cstr[0] - '0';							// then interpret as three-digit decimal
-					int v1 = cstr[1] - '0';
-					int v2 = cstr[2] - '0';
-					int val = v0 * 100 + v1 * 10 + v2;
-					if (val <= 255) { c = (mDNSu8)val; cstr += 3; }	// If valid value, use it
-				}
-			}
-			*ptr++ = c;												// Write the character
-		}
-		if (*cstr) cstr++;											// Skip over the trailing dot (if present)
-		if (ptr - lengthbyte - 1 > MAX_DOMAIN_LABEL)				// If illegal label, abort
-			return(mDNSNULL);
-		*lengthbyte = (mDNSu8)(ptr - lengthbyte - 1);				// Fill in the length byte
-	}
-
-	*ptr++ = 0;														// Put the null root label on the end
-	if (*cstr) return(mDNSNULL);									// Failure: We didn't successfully consume all input
-	else return(ptr);												// Success: return new value of ptr
-}
-
-// AppendDomainLabel appends a single label to a name.
-// If successful, AppendDomainLabel returns a pointer to the next unused byte
-// in the domainname bufer (i.e., the next byte after the terminating zero).
-// If unable to construct a legal domain name (i.e. label more than 63 bytes, or total more than 255 bytes)
-// AppendDomainLabel returns mDNSNULL.
-mDNSexport mDNSu8 *AppendDomainLabel(domainname *const name, const domainlabel *const label)
-{
-	int i;
-	mDNSu8 *ptr = name->c + DomainNameLength(name) - 1;
-
-	// Check label is legal
-	if (label->c[0] > MAX_DOMAIN_LABEL) return(mDNSNULL);
-
-	// Check that ptr + length byte + data bytes + final zero does not exceed our limit
-	if (ptr + 1 + label->c[0] + 1 > name->c + MAX_DOMAIN_NAME) return(mDNSNULL);
-
-	for (i=0; i<=label->c[0]; i++) *ptr++ = label->c[i];	// Copy the label data
-	*ptr++ = 0;								// Put the null root label on the end
-	return(ptr);
-}
-
-mDNSexport mDNSu8 *AppendDomainName(domainname *const name, const domainname *const append)
-{
-	mDNSu8       *      ptr = name->c + DomainNameLength(name) - 1;	// Find end of current name
-	const mDNSu8 *const lim = name->c + MAX_DOMAIN_NAME - 1;		// Limit of how much we can add (not counting final zero)
-	const mDNSu8 *      src = append->c;
-	while(src[0])
-	{
-		int i;
-		if (ptr + 1 + src[0] > lim) return(mDNSNULL);
-		for (i=0; i<=src[0]; i++) *ptr++ = src[i];
-		*ptr = 0;	// Put the null root label on the end
-		src += i;
-	}
-	return(ptr);
-}
-
-// MakeDomainLabelFromLiteralString makes a single domain label from a single literal C string (with no escaping).
-// If successful, MakeDomainLabelFromLiteralString returns mDNStrue.
-// If unable to convert the whole string to a legal domain label (i.e. because length is more than 63 bytes) then
-// MakeDomainLabelFromLiteralString makes a legal domain label from the first 63 bytes of the string and returns mDNSfalse.
-// In some cases silently truncated oversized names to 63 bytes is acceptable, so the return result may be ignored.
-// In other cases silent truncation may not be acceptable, so in those cases the calling function needs to check the return result.
-mDNSexport mDNSBool MakeDomainLabelFromLiteralString(domainlabel *const label, const char *cstr)
-{
-	mDNSu8       *      ptr   = label->c + 1;						// Where we're putting it
-	const mDNSu8 *const limit = label->c + 1 + MAX_DOMAIN_LABEL;	// The maximum we can put
-	while (*cstr && ptr < limit) *ptr++ = (mDNSu8)*cstr++;			// Copy the label
-	label->c[0] = (mDNSu8)(ptr - label->c - 1);						// Set the length byte
-	return(*cstr == 0);												// Return mDNStrue if we successfully consumed all input
-}
-
-// MakeDomainNameFromDNSNameString makes a native DNS-format domainname from a C string.
-// The C string is in conventional DNS syntax:
-// Textual labels, escaped as necessary using the usual DNS '\' notation, separated by dots.
-// If successful, MakeDomainNameFromDNSNameString returns a pointer to the next unused byte
-// in the domainname bufer (i.e., the next byte after the terminating zero).
-// If unable to construct a legal domain name (i.e. label more than 63 bytes, or total more than 255 bytes)
-// MakeDomainNameFromDNSNameString returns mDNSNULL.
-mDNSexport mDNSu8 *MakeDomainNameFromDNSNameString(domainname *const name, const char *cstr)
-{
-	name->c[0] = 0;									// Make an empty domain name
-	return(AppendDNSNameString(name, cstr));		// And then add this string to it
-}
-#if 0
-mDNSexport char *ConvertDomainLabelToCString_withescape(const domainlabel *const label, char *ptr, char esc)
-{
-	const mDNSu8 *      src = label->c;							// Domain label we're reading
-	const mDNSu8        len = *src++;							// Read length of this (non-null) label
-	const mDNSu8 *const end = src + len;						// Work out where the label ends
-	if (len > MAX_DOMAIN_LABEL) return(mDNSNULL);				// If illegal label, abort
-	while (src < end)											// While we have characters in the label
-	{
-		mDNSu8 c = *src++;
-		if (esc)
-		{
-			if (c == '.' || c == esc)							// If character is a dot or the escape character
-				*ptr++ = esc;									// Output escape character
-			else if (c <= ' ')									// If non-printing ascii,
-			{												// Output decimal escape sequence
-				*ptr++ = esc;
-				*ptr++ = (char)  ('0' + (c / 100)     );
-				*ptr++ = (char)  ('0' + (c /  10) % 10);
-				c      = (mDNSu8)('0' + (c      ) % 10);
-			}
-		}
-		*ptr++ = (char)c;										// Copy the character
-	}
-	*ptr = 0;													// Null-terminate the string
-	return(ptr);												// and return
-}
-
-// Note, to guarantee that there will be no possible overrun, cstr must be at least 1005 bytes
-// The longest legal domain name is 255 bytes, in the form of three 64-byte labels, one 62-byte label,
-// and the null root label.
-// If every label character has to be escaped as a four-byte escape sequence, the maximum textual
-// ascii display of this is 63*4 + 63*4 + 63*4 + 61*4 = 1000 label characters,
-// plus four dots and the null at the end of the C string = 1005
-mDNSexport char *ConvertDomainNameToCString_withescape(const domainname *const name, char *ptr, char esc)
-{
-	const mDNSu8 *src         = name->c;								// Domain name we're reading
-	const mDNSu8 *const max   = name->c + MAX_DOMAIN_NAME;			// Maximum that's valid
-	
-	if (*src == 0) *ptr++ = '.';									// Special case: For root, just write a dot
-
-	while (*src)													// While more characters in the domain name
-	{
-		if (src + 1 + *src >= max) return(mDNSNULL);
-		ptr = ConvertDomainLabelToCString_withescape((const domainlabel *)src, ptr, esc);
-		if (!ptr) return(mDNSNULL);
-		src += 1 + *src;
-		*ptr++ = '.';												// Write the dot after the label
-	}
-
-	*ptr++ = 0;														// Null-terminate the string
-	return(ptr);													// and return
-}
-
-// RFC 1034 rules:
-// Host names must start with a letter, end with a letter or digit,
-// and have as interior characters only letters, digits, and hyphen.
-// This was subsequently modified in RFC 1123 to allow the first character to be either a letter or a digit
-#define mdnsValidHostChar(X, notfirst, notlast) (mdnsIsLetter(X) || mdnsIsDigit(X) || ((notfirst) && (notlast) && (X) == '-') )
-
-mDNSexport void ConvertUTF8PstringToRFC1034HostLabel(const mDNSu8 UTF8Name[], domainlabel *const hostlabel)
-{
-	const mDNSu8 *      src  = &UTF8Name[1];
-	const mDNSu8 *const end  = &UTF8Name[1] + UTF8Name[0];
-	mDNSu8 *      ptr  = &hostlabel->c[1];
-	const mDNSu8 *const lim  = &hostlabel->c[1] + MAX_DOMAIN_LABEL;
-	while (src < end)
-	{
-		// Delete apostrophes from source name
-		if (src[0] == '\'') { src++; continue; }		// Standard straight single quote
-		if (src + 2 < end && src[0] == 0xE2 && src[1] == 0x80 && src[2] == 0x99)
-		{ src += 3; continue; }	// Unicode curly apostrophe
-		if (ptr < lim)
-		{
-			if (mdnsValidHostChar(*src, (ptr > &hostlabel->c[1]), (src < end-1))) *ptr++ = *src;
-			else if (ptr > &hostlabel->c[1] && ptr[-1] != '-') *ptr++ = '-';
-		}
-		src++;
-	}
-	while (ptr > &hostlabel->c[1] && ptr[-1] == '-') ptr--;	// Truncate trailing '-' marks
-	hostlabel->c[0] = (mDNSu8)(ptr - &hostlabel->c[1]);
-}
-#endif
-mDNSexport mDNSu8 *ConstructServiceName(domainname *const fqdn,
-					const domainlabel *name, const domainname *type, const domainname *const domain)
-{
-	int i, len;
-	mDNSu8 *dst = fqdn->c;
-	const mDNSu8 *src;
-#if MDNS_DEBUGMSGS > 2
-	const char *errormsg;
-#endif
-	// In the case where there is no name (and ONLY in that case),
-	// a single-label subtype is allowed as the first label of a three-part "type"
-	if (!name)
-	{
-		const mDNSu8 *s2 = type->c + 1 + type->c[0];
-		if (type->c[0]  > 0 && type->c[0]  < 0x40 &&
-		    s2[0]       > 0 && s2[0]       < 0x40 &&
-		    s2[1+s2[0]] > 0 && s2[1+s2[0]] < 0x40)
-		{
-			name = (domainlabel *)type;
-			type = (domainname  *)s2;
-		}
-	}
-
-	if (name && name->c[0])
-	{
-		src = name->c;									// Put the service name into the domain name
-		len = *src;
-		if (len >= 0x40) 
-		{ 
-#if MDNS_DEBUGMSGS > 2
-			errormsg="Service instance name too long"; 
-#endif
-			goto fail;
-		}
-		for (i=0; i<=len; i++) *dst++ = *src++;
-	}
-	else
-		name = (domainlabel*)"";	// Set this up to be non-null, to avoid errors if we have to call LogMsg() below
-	
-	src = type->c;										// Put the service type into the domain name
-	len = *src;
-	if (len < 2 || len >= 0x40)  
-	{
-#if MDNS_DEBUGMSGS > 2
-		errormsg="Invalid service application protocol name";
-#endif
-		goto fail; 
-	}
-	if (src[1] != '_') 
-	{ 
-#if MDNS_DEBUGMSGS > 2
-		errormsg="Service application protocol name must begin with underscore";
-#endif
-		goto fail; 
-	}
-	for (i=2; i<=len; i++)
-		if (!mdnsIsLetter(src[i]) && !mdnsIsDigit(src[i]) && src[i] != '-' && src[i] != '_')
-		{ 
-#if MDNS_DEBUGMSGS > 2
-			errormsg="Service application protocol name must contain only letters, digits, and hyphens"; 
-#endif
-			goto fail; 
-		}
-	for (i=0; i<=len; i++) *dst++ = *src++;
-
-	len = *src;
-	//if (len == 0 || len >= 0x40)  { errormsg="Invalid service transport protocol name"; goto fail; }
-	if (!(len == 4 && src[1] == '_' &&
-	      (((src[2] | 0x20) == 'u' && (src[3] | 0x20) == 'd') || ((src[2] | 0x20) == 't' && (src[3] | 0x20) == 'c')) &&
-	      (src[4] | 0x20) == 'p'))
-	{ 
-#if MDNS_DEBUGMSGS > 2
-		errormsg="Service transport protocol name must be _udp or _tcp"; 
-#endif
-		goto fail; 
-	}
-	for (i=0; i<=len; i++) *dst++ = *src++;
-	
-	if (*src) 
-	{
-#if MDNS_DEBUGMSGS > 2 
-		errormsg="Service type must have only two labels"; 
-#endif
-		goto fail; 
-	}
-	
-	*dst = 0;
-	dst = AppendDomainName(fqdn, domain);
-	if (!dst) 
-	{
-#if MDNS_DEBUGMSGS > 2
-		errormsg="Service domain too long"; 
-#endif
-		goto fail; 
-	}
-	return(dst);
-
- fail:
-	LogMsg("ConstructServiceName: %s: %#s.%##s%##s", errormsg, name->c, type->c, domain->c);
-	return(mDNSNULL);
-}
-
-mDNSexport mDNSBool DeconstructServiceName(const domainname *const fqdn,
-					   domainlabel *const name, domainname *const type, domainname *const domain)
-{
-	int i, len;
-	const mDNSu8 *src = fqdn->c;
-	const mDNSu8 *max = fqdn->c + MAX_DOMAIN_NAME;
-	mDNSu8 *dst;
-	
-	dst = name->c;										// Extract the service name from the domain name
-	len = *src;
-	if (len >= 0x40) { debugf("DeconstructServiceName: service name too long"); return(mDNSfalse); }
-	for (i=0; i<=len; i++) *dst++ = *src++;
-	
-	dst = type->c;										// Extract the service type from the domain name
-	len = *src;
-	if (len >= 0x40) { debugf("DeconstructServiceName: service type too long"); return(mDNSfalse); }
-	for (i=0; i<=len; i++) *dst++ = *src++;
-
-	len = *src;
-	if (len >= 0x40) { debugf("DeconstructServiceName: service type too long"); return(mDNSfalse); }
-	for (i=0; i<=len; i++) *dst++ = *src++;
-	*dst++ = 0;		// Put the null root label on the end of the service type
-
-	dst = domain->c;									// Extract the service domain from the domain name
-	while (*src)
-	{
-		len = *src;
-		if (len >= 0x40)
-		{ debugf("DeconstructServiceName: service domain label too long"); return(mDNSfalse); }
-		if (src + 1 + len + 1 >= max)
-		{ debugf("DeconstructServiceName: service domain too long"); return(mDNSfalse); }
-		for (i=0; i<=len; i++) *dst++ = *src++;
-	}
-	*dst++ = 0;		// Put the null root label on the end
-	
-	return(mDNStrue);
-}
-
-// Returns true if a rich text label ends in " (nnn)", or if an RFC 1034
-// name ends in "-nnn", where n is some decimal number.
-mDNSlocal mDNSBool LabelContainsSuffix(const domainlabel *const name, const mDNSBool RichText)
-{
-	mDNSu16 l = name->c[0];
-	
-	if (RichText)
-	{
-		if (l < 4) return mDNSfalse;							// Need at least " (2)"
-		if (name->c[l--] != ')') return mDNSfalse;				// Last char must be ')'
-		if (!mdnsIsDigit(name->c[l])) return mDNSfalse;			// Preceeded by a digit
-		l--;
-		while (l > 2 && mdnsIsDigit(name->c[l])) l--;			// Strip off digits
-		return (name->c[l] == '(' && name->c[l - 1] == ' ');
-	}
-	else
-	{
-		if (l < 2) return mDNSfalse;							// Need at least "-2"
-		if (!mdnsIsDigit(name->c[l])) return mDNSfalse;			// Last char must be a digit
-		l--;
-		while (l > 2 && mdnsIsDigit(name->c[l])) l--;			// Strip off digits
-		return (name->c[l] == '-');
-	}
-}
-
-// removes an auto-generated suffix (appended on a name collision) from a label.  caller is
-// responsible for ensuring that the label does indeed contain a suffix.  returns the number
-// from the suffix that was removed.
-mDNSlocal mDNSu32 RemoveLabelSuffix(domainlabel *name, mDNSBool RichText)
-{
-	mDNSu32 val = 0, multiplier = 1;
-
-	// Chop closing parentheses from RichText suffix
-	if (RichText && name->c[0] >= 1 && name->c[name->c[0]] == ')') name->c[0]--;
-
-	// Get any existing numerical suffix off the name
-	while (mdnsIsDigit(name->c[name->c[0]]))
-	{ val += (name->c[name->c[0]] - '0') * multiplier; multiplier *= 10; name->c[0]--; }
-
-	// Chop opening parentheses or dash from suffix
-	if (RichText)
-	{
-		if (name->c[0] >= 2 && name->c[name->c[0]] == '(' && name->c[name->c[0]-1] == ' ') name->c[0] -= 2;
-	}
-	else
-	{
-		if (name->c[0] >= 1 && name->c[name->c[0]] == '-') name->c[0] -= 1;
-	}
-
-	return(val);
-}
-
-// appends a numerical suffix to a label, with the number following a whitespace and enclosed
-// in parentheses (rich text) or following two consecutive hyphens (RFC 1034 domain label).
-mDNSlocal void AppendLabelSuffix(domainlabel *name, mDNSu32 val, mDNSBool RichText)
-{
-	mDNSu32 divisor = 1, chars = 2;	// Shortest possible RFC1034 name suffix is 3 characters ("-2")
-	if (RichText) chars = 4;		// Shortest possible RichText suffix is 4 characters (" (2)")
-	
-	// Truncate trailing spaces from RichText names
-	if (RichText) while (name->c[name->c[0]] == ' ') name->c[0]--;
-
-	while (val >= divisor * 10) { divisor *= 10; chars++; }
-
-	if (name->c[0] > (mDNSu8)(MAX_DOMAIN_LABEL - chars))
-	{
-		name->c[0] = (mDNSu8)(MAX_DOMAIN_LABEL - chars);
-		// If the following character is a UTF-8 continuation character,
-		// we just chopped a multi-byte UTF-8 character in the middle, so strip back to a safe truncation point
-		while (name->c[0] > 0 && (name->c[name->c[0]+1] & 0xC0) == 0x80) name->c[0]--;
-	}
-
-	if (RichText) { name->c[++name->c[0]] = ' '; name->c[++name->c[0]] = '('; }
-	else          { name->c[++name->c[0]] = '-'; }
-	
-	while (divisor)
-	{
-		name->c[++name->c[0]] = (mDNSu8)('0' + val / divisor);
-		val     %= divisor;
-		divisor /= 10;
-	}
-
-	if (RichText) name->c[++name->c[0]] = ')';
-}
-
-mDNSexport void IncrementLabelSuffix(domainlabel *name, mDNSBool RichText)
-{
-	mDNSu32 val = 0;
-
-	if (LabelContainsSuffix(name, RichText))
-		val = RemoveLabelSuffix(name, RichText);
-		
-	// If no existing suffix, start by renaming "Foo" as "Foo (2)" or "Foo-2" as appropriate.
-	// If existing suffix in the range 2-9, increment it.
-	// If we've had ten conflicts already, there are probably too many hosts trying to use the same name,
-	// so add a random increment to improve the chances of finding an available name next time.
-	if      (val == 0) val = 2;
-	else if (val < 10) val++;
-	else               val += 1 + mDNSRandom(99);
-	
-	AppendLabelSuffix(name, val, RichText);
-}
-
-// ***************************************************************************
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - Resource Record Utility Functions
-#endif
-
-#define RRIsAddressType(RR) ((RR)->resrec.rrtype == kDNSType_A || (RR)->resrec.rrtype == kDNSType_AAAA)
-#define RRTypeIsAddressType(T) ((T) == kDNSType_A || (T) == kDNSType_AAAA)
-
-#define ResourceRecordIsValidAnswer(RR) ( ((RR)->             resrec.RecordType & kDNSRecordTypeActiveMask)  && \
-		((RR)->Additional1 == mDNSNULL || ((RR)->Additional1->resrec.RecordType & kDNSRecordTypeActiveMask)) && \
-		((RR)->Additional2 == mDNSNULL || ((RR)->Additional2->resrec.RecordType & kDNSRecordTypeActiveMask)) && \
-		((RR)->DependentOn == mDNSNULL || ((RR)->DependentOn->resrec.RecordType & kDNSRecordTypeActiveMask))  )
-
-#define ResourceRecordIsValidInterfaceAnswer(RR, INTID) \
-	(ResourceRecordIsValidAnswer(RR) && \
-	((RR)->resrec.InterfaceID == mDNSInterface_Any || (RR)->resrec.InterfaceID == (INTID)))
-
-#define RRUniqueOrKnownUnique(RR) ((RR)->RecordType & (kDNSRecordTypeUnique | kDNSRecordTypeKnownUnique))
-
-#define DefaultProbeCountForTypeUnique ((mDNSu8)3)
-#define DefaultProbeCountForRecordType(X)      ((X) == kDNSRecordTypeUnique ? DefaultProbeCountForTypeUnique : (mDNSu8)0)
-
-// For records that have *never* been announced on the wire, their AnnounceCount will be set to InitialAnnounceCount (10).
-// When de-registering these records we do not need to send any goodbye packet because we never announced them in the first
-// place. If AnnounceCount is less than InitialAnnounceCount that means we have announced them at least once, so a goodbye
-// packet is needed. For this reason, if we ever reset AnnounceCount (e.g. after an interface change) we set it to
-// ReannounceCount (9), not InitialAnnounceCount. If we were to reset AnnounceCount back to InitialAnnounceCount that would
-// imply that the record had never been announced on the wire (which is false) and if the client were then to immediately
-// deregister that record before it had a chance to announce, we'd fail to send its goodbye packet (which would be a bug).
-#define InitialAnnounceCount ((mDNSu8)10)
-#define ReannounceCount      ((mDNSu8)9)
-
-// Note that the announce intervals use exponential backoff, doubling each time. The probe intervals do not.
-// This means that because the announce interval is doubled after sending the first packet, the first
-// observed on-the-wire inter-packet interval between announcements is actually one second.
-// The half-second value here may be thought of as a conceptual (non-existent) half-second delay *before* the first packet is sent.
-#define DefaultProbeIntervalForTypeUnique (mDNSPlatformOneSecond/4)
-#define DefaultAnnounceIntervalForTypeShared (mDNSPlatformOneSecond/2)
-#define DefaultAnnounceIntervalForTypeUnique (mDNSPlatformOneSecond/2)
-
-#define DefaultAPIntervalForRecordType(X)  ((X) & (kDNSRecordTypeAdvisory | kDNSRecordTypeShared     ) ? DefaultAnnounceIntervalForTypeShared : \
-											(X) & (kDNSRecordTypeUnique                              ) ? DefaultProbeIntervalForTypeUnique    : \
-											(X) & (kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique) ? DefaultAnnounceIntervalForTypeUnique : 0)
-
-#define TimeToAnnounceThisRecord(RR,time) ((RR)->AnnounceCount && (time) - ((RR)->LastAPTime + (RR)->ThisAPInterval) >= 0)
-#define TimeToSendThisRecord(RR,time) ((TimeToAnnounceThisRecord(RR,time) || (RR)->ImmedAnswer) && ResourceRecordIsValidAnswer(RR))
-#define TicksTTL(RR) ((mDNSs32)(RR)->resrec.rroriginalttl * mDNSPlatformOneSecond)
-#define RRExpireTime(RR) ((RR)->TimeRcvd + TicksTTL(RR))
-
-#define MaxUnansweredQueries 4
-
-mDNSlocal mDNSBool SameRData(const ResourceRecord *const r1, const ResourceRecord *const r2)
-{
-	if (r1->rrtype     != r2->rrtype)   return(mDNSfalse);
-	if (r1->rdlength   != r2->rdlength) return(mDNSfalse);
-	if (r1->rdatahash  != r2->rdatahash) return(mDNSfalse);
-	if (r1->rdnamehash != r2->rdnamehash) return(mDNSfalse);
-	switch(r1->rrtype)
-	{
-	case kDNSType_CNAME:// Same as PTR
-	case kDNSType_PTR:	return(SameDomainName(&r1->rdata->u.name, &r2->rdata->u.name));
-
-	case kDNSType_SRV:	return(mDNSBool)(  	r1->rdata->u.srv.priority          == r2->rdata->u.srv.priority          &&
-							r1->rdata->u.srv.weight            == r2->rdata->u.srv.weight            &&
-							r1->rdata->u.srv.port.NotAnInteger == r2->rdata->u.srv.port.NotAnInteger &&
-							SameDomainName(&r1->rdata->u.srv.target, &r2->rdata->u.srv.target)       );
-
-	default:			return(mDNSPlatformMemSame(r1->rdata->u.data, r2->rdata->u.data, r1->rdlength));
-	}
-}
-
-mDNSlocal mDNSBool ResourceRecordAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q)
-{
-	if (rr->InterfaceID &&
-	    q ->InterfaceID &&
-	    rr->InterfaceID != q->InterfaceID) return(mDNSfalse);
-
-	// RR type CNAME matches any query type. QTYPE ANY matches any RR type. QCLASS ANY matches any RR class.
-	if (rr->rrtype != kDNSType_CNAME && rr->rrtype  != q->qtype  && q->qtype  != kDNSQType_ANY ) return(mDNSfalse);
-	if (                                rr->rrclass != q->qclass && q->qclass != kDNSQClass_ANY) return(mDNSfalse);
-	return(rr->namehash == q->qnamehash && SameDomainName(&rr->name, &q->qname));
-}
-
-mDNSlocal mDNSu32 DomainNameHashValue(const domainname *const name)
-{
-	mDNSu32 sum = 0;
-	const mDNSu8 *c;
-
-	for (c = name->c; c[0] != 0 && c[1] != 0; c += 2)
-	{
-		sum += ((mDNSIsUpperCase(c[0]) ? c[0] + 'a' - 'A' : c[0]) << 8) |
-			(mDNSIsUpperCase(c[1]) ? c[1] + 'a' - 'A' : c[1]);
-		sum = (sum<<3) | (sum>>29);
-	}
-	if (c[0]) sum += ((mDNSIsUpperCase(c[0]) ? c[0] + 'a' - 'A' : c[0]) << 8);
-	return(sum);
-}
-
-#define HashSlot(X) (DomainNameHashValue(X) % CACHE_HASH_SLOTS)
-
-mDNSlocal mDNSu32 RDataHashValue(mDNSu16 const rdlength, const RDataBody *const rdb)
-{
-	mDNSu32 sum = 0;
-	int i;
-	for (i=0; i+1 < rdlength; i+=2)
-	{
-		sum += (((mDNSu32)(rdb->data[i])) << 8) | rdb->data[i+1];
-		sum = (sum<<3) | (sum>>29);
-	}
-	if (i < rdlength)
-	{
-		sum += ((mDNSu32)(rdb->data[i])) << 8;
-	}
-	return(sum);
-}
-
-// SameResourceRecordSignature returns true if two resources records have the same name, type, and class, and may be sent
-// (or were received) on the same interface (i.e. if *both* records specify an interface, then it has to match).
-// TTL and rdata may differ.
-// This is used for cache flush management:
-// When sending a unique record, all other records matching "SameResourceRecordSignature" must also be sent
-// When receiving a unique record, all old cache records matching "SameResourceRecordSignature" are flushed
-mDNSlocal mDNSBool SameResourceRecordSignature(const ResourceRecord *const r1, const ResourceRecord *const r2)
-{
-	if (!r1) { LogMsg("SameResourceRecordSignature ERROR: r1 is NULL"); return(mDNSfalse); }
-	if (!r2) { LogMsg("SameResourceRecordSignature ERROR: r2 is NULL"); return(mDNSfalse); }
-	if (r1->InterfaceID &&
-	    r2->InterfaceID &&
-	    r1->InterfaceID != r2->InterfaceID) return(mDNSfalse);
-	return(mDNSBool)(r1->rrtype == r2->rrtype && r1->rrclass == r2->rrclass && r1->namehash == r2->namehash && SameDomainName(&r1->name, &r2->name));
-}
-
-// PacketRRMatchesSignature behaves as SameResourceRecordSignature, except that types may differ if the
-// authoratative record is in the probing state.  Probes are sent with the wildcard type, so a response of
-// any type should match, even if it is not the type the client plans to use.
-mDNSlocal mDNSBool PacketRRMatchesSignature(const CacheRecord *const pktrr, const AuthRecord *const authrr)
-{
-	if (!pktrr)  { LogMsg("PacketRRMatchesSignature ERROR: pktrr is NULL"); return(mDNSfalse); }
-	if (!authrr) { LogMsg("PacketRRMatchesSignature ERROR: authrr is NULL"); return(mDNSfalse); }
-	if (pktrr->resrec.InterfaceID &&
-	    authrr->resrec.InterfaceID &&
-	    pktrr->resrec.InterfaceID != authrr->resrec.InterfaceID) return(mDNSfalse);
-	if (authrr->resrec.RecordType != kDNSRecordTypeUnique && pktrr->resrec.rrtype != authrr->resrec.rrtype) return(mDNSfalse);
-	return(mDNSBool)(pktrr->resrec.rrclass == authrr->resrec.rrclass && pktrr->resrec.namehash == authrr->resrec.namehash && SameDomainName(&pktrr->resrec.name, &authrr->resrec.name));
-}
-
-// IdenticalResourceRecord returns true if two resources records have
-// the same name, type, class, and identical rdata (InterfaceID and TTL may differ)
-mDNSlocal mDNSBool IdenticalResourceRecord(const ResourceRecord *const r1, const ResourceRecord *const r2)
-{
-	if (!r1) { LogMsg("IdenticalResourceRecord ERROR: r1 is NULL"); return(mDNSfalse); }
-	if (!r2) { LogMsg("IdenticalResourceRecord ERROR: r2 is NULL"); return(mDNSfalse); }
-	if (r1->rrtype != r2->rrtype || r1->rrclass != r2->rrclass || r1->namehash != r2->namehash || !SameDomainName(&r1->name, &r2->name)) return(mDNSfalse);
-	return(SameRData(r1, r2));
-}
-
-// CacheRecord *ks is the CacheRecord from the known answer list in the query.
-// This is the information that the requester believes to be correct.
-// AuthRecord *rr is the answer we are proposing to give, if not suppressed.
-// This is the information that we believe to be correct.
-// We've already determined that we plan to give this answer on this interface
-// (either the record is non-specific, or it is specific to this interface)
-// so now we just need to check the name, type, class, rdata and TTL.
-mDNSlocal mDNSBool ShouldSuppressKnownAnswer(const CacheRecord *const ka, const AuthRecord *const rr)
-{
-	// If RR signature is different, or data is different, then don't suppress our answer
-	if (!IdenticalResourceRecord(&ka->resrec,&rr->resrec)) return(mDNSfalse);
-	
-	// If the requester's indicated TTL is less than half the real TTL,
-	// we need to give our answer before the requester's copy expires.
-	// If the requester's indicated TTL is at least half the real TTL,
-	// then we can suppress our answer this time.
-	// If the requester's indicated TTL is greater than the TTL we believe,
-	// then that's okay, and we don't need to do anything about it.
-	// (If two responders on the network are offering the same information,
-	// that's okay, and if they are offering the information with different TTLs,
-	// the one offering the lower TTL should defer to the one offering the higher TTL.)
-	return(mDNSBool)(ka->resrec.rroriginalttl >= rr->resrec.rroriginalttl / 2);
-}
-
-mDNSlocal mDNSu16 GetRDLength(const ResourceRecord *const rr, mDNSBool estimate)
-{
-	RDataBody *rd = &rr->rdata->u;
-	const domainname *const name = estimate ? &rr->name : mDNSNULL;
-	switch (rr->rrtype)
-	{
-	case kDNSType_A:	return(sizeof(rd->ip));
-	case kDNSType_CNAME:// Same as PTR
-	case kDNSType_PTR:	return(CompressedDomainNameLength(&rd->name, name));
-	case kDNSType_HINFO:return(mDNSu16)(2 + (int)rd->data[0] + (int)rd->data[1 + (int)rd->data[0]]);
-	case kDNSType_NULL:	// Same as TXT -- not self-describing, so have to just trust rdlength
-	case kDNSType_TXT:  return(rr->rdlength); // TXT is not self-describing, so have to just trust rdlength
-	case kDNSType_AAAA:	return(sizeof(rd->ipv6));
-	case kDNSType_SRV:	return(mDNSu16)(6 + CompressedDomainNameLength(&rd->srv.target, name));
-	default:			debugf("Warning! Don't know how to get length of resource type %d", rr->rrtype);
-		return(rr->rdlength);
-	}
-}
-
-mDNSlocal void SetNextAnnounceProbeTime(mDNS *const m, const AuthRecord *const rr)
-{
-	if (rr->resrec.RecordType == kDNSRecordTypeUnique)
-	{
-		if (m->NextScheduledProbe - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
-			m->NextScheduledProbe = (rr->LastAPTime + rr->ThisAPInterval);
-	}
-	else if (rr->AnnounceCount && ResourceRecordIsValidAnswer(rr))
-	{
-		if (m->NextScheduledResponse - (rr->LastAPTime + rr->ThisAPInterval) >= 0)
-			m->NextScheduledResponse = (rr->LastAPTime + rr->ThisAPInterval);
-	}
-}
-
-#define GetRRDomainNameTarget(RR) (                                                                          \
-	((RR)->rrtype == kDNSType_CNAME || (RR)->rrtype == kDNSType_PTR) ? &(RR)->rdata->u.name       :          \
-	((RR)->rrtype == kDNSType_SRV                                  ) ? &(RR)->rdata->u.srv.target : mDNSNULL )
-
-mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr)
-{
-	// To allow us to aggregate probes when a group of services are registered together,
-	// the first probe is delayed 1/4 second. This means the common-case behaviour is:
-	// 1/4 second wait; probe
-	// 1/4 second wait; probe
-	// 1/4 second wait; probe
-	// 1/4 second wait; announce (i.e. service is normally announced exactly one second after being registered)
-
-	// If we have no probe suppression time set, or it is in the past, set it now
-	if (m->SuppressProbes == 0 || m->SuppressProbes - m->timenow < 0)
-	{
-		m->SuppressProbes = (m->timenow + DefaultProbeIntervalForTypeUnique) | 1;
-		// If we already have a probe scheduled to go out sooner, then use that time to get better aggregation
-		if (m->SuppressProbes - m->NextScheduledProbe >= 0)
-			m->SuppressProbes = m->NextScheduledProbe;
-		// If we already have a query scheduled to go out sooner, then use that time to get better aggregation
-		if (m->SuppressProbes - m->NextScheduledQuery >= 0)
-			m->SuppressProbes = m->NextScheduledQuery;
-	}
-	
-	// We announce to flush stale data from other caches. It is a reasonable assumption that any
-	// old stale copies will probably have the same TTL we're using, so announcing longer than
-	// this serves no purpose -- any stale copies of that record will have expired by then anyway.
-	rr->AnnounceUntil   = m->timenow + TicksTTL(rr);
-	rr->LastAPTime      = m->SuppressProbes - rr->ThisAPInterval;
-	// Set LastMCTime to now, to inhibit multicast responses
-	// (no need to send additional multicast responses when we're announcing anyway)
-	rr->LastMCTime      = m->timenow;
-	rr->LastMCInterface = mDNSInterfaceMark;
-	
-	// If this is a record type that's not going to probe, then delay its first announcement so that
-	// it will go out synchronized with the first announcement for the other records that *are* probing.
-	// This is a minor performance tweak that helps keep groups of related records synchronized together.
-	// The addition of "rr->ThisAPInterval / 2" is to make sure that, in the event that any of the probes are
-	// delayed by a few milliseconds, this announcement does not inadvertently go out *before* the probing is complete.
-	// When the probing is complete and those records begin to announce, these records will also be picked up and accelerated,
-	// because they will meet the criterion of being at least half-way to their scheduled announcement time.
-	if (rr->resrec.RecordType != kDNSRecordTypeUnique)
-		rr->LastAPTime += DefaultProbeIntervalForTypeUnique * DefaultProbeCountForTypeUnique + rr->ThisAPInterval / 2;
-	
-	SetNextAnnounceProbeTime(m, rr);
-}
-
-mDNSlocal void SetNewRData(ResourceRecord *const rr, RData *NewRData, mDNSu16 rdlength)
-{
-	domainname *target;
-	if (NewRData)
-	{
-		rr->rdata    = NewRData;
-		rr->rdlength = rdlength;
-	}
-	// Must not try to get target pointer until after updating rr->rdata
-	target = GetRRDomainNameTarget(rr);
-	rr->rdlength   = GetRDLength(rr, mDNSfalse);
-	rr->rdestimate = GetRDLength(rr, mDNStrue);
-	rr->rdatahash  = RDataHashValue(rr->rdlength, &rr->rdata->u);
-	rr->rdnamehash = target ? DomainNameHashValue(target) : 0;
-}
-
-mDNSlocal void SetTargetToHostName(mDNS *const m, AuthRecord *const rr)
-{
-	domainname *target = GetRRDomainNameTarget(&rr->resrec);
-
-	if (!target) debugf("SetTargetToHostName: Don't know how to set the target of rrtype %d", rr->resrec.rrtype);
-
-	if (target && SameDomainName(target, &m->hostname))
-		debugf("SetTargetToHostName: Target of %##s is already %##s", rr->resrec.name.c, target->c);
-	
-	if (target && !SameDomainName(target, &m->hostname))
-	{
-		AssignDomainName(*target, m->hostname);
-		SetNewRData(&rr->resrec, mDNSNULL, 0);
-		
-		// If we're in the middle of probing this record, we need to start again,
-		// because changing its rdata may change the outcome of the tie-breaker.
-		// (If the record type is kDNSRecordTypeUnique (unconfirmed unique) then DefaultProbeCountForRecordType is non-zero.)
-		rr->ProbeCount     = DefaultProbeCountForRecordType(rr->resrec.RecordType);
-
-		// If we've announced this record, we really should send a goodbye packet for the old rdata before
-		// changing to the new rdata. However, in practice, we only do SetTargetToHostName for unique records,
-		// so when we announce them we'll set the kDNSClass_UniqueRRSet and clear any stale data that way.
-		if (rr->AnnounceCount < InitialAnnounceCount && rr->resrec.RecordType == kDNSRecordTypeShared)
-			debugf("Have announced shared record %##s (%s) at least once: should have sent a goodbye packet before updating", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-
-		if (rr->AnnounceCount < ReannounceCount)
-			rr->AnnounceCount = ReannounceCount;
-		rr->ThisAPInterval = DefaultAPIntervalForRecordType(rr->resrec.RecordType);
-		InitializeLastAPTime(m,rr);
-	}
-}
-
-mDNSlocal void CompleteProbing(mDNS *const m, AuthRecord *const rr)
-{
-	verbosedebugf("Probing for %##s (%s) complete", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-	if (!rr->Acknowledged && rr->RecordCallback)
-	{
-		// CAUTION: MUST NOT do anything more with rr after calling rr->Callback(), because the client's callback function
-		// is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc.
-		rr->Acknowledged = mDNStrue;
-		m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback
-		rr->RecordCallback(m, rr, mStatus_NoError);
-		m->mDNS_reentrancy--; // Decrement to block mDNS API calls again
-	}
-}
-
-#define ValidateDomainName(N) (DomainNameLength(N) <= MAX_DOMAIN_NAME)
-
-mDNSlocal mDNSBool ValidateRData(const mDNSu16 rrtype, const mDNSu16 rdlength, const RData *const rd)
-{
-	mDNSu16 len;
-	switch(rrtype)
-	{
-	case kDNSType_A:	return(rdlength == sizeof(mDNSv4Addr));
-
-	case kDNSType_NS:	// Same as PTR
-	case kDNSType_MD:	// Same as PTR
-	case kDNSType_MF:	// Same as PTR
-	case kDNSType_CNAME:// Same as PTR
-		//case kDNSType_SOA not checked
-	case kDNSType_MB:	// Same as PTR
-	case kDNSType_MG:	// Same as PTR
-	case kDNSType_MR:	// Same as PTR
-		//case kDNSType_NULL not checked (no specified format, so always valid)
-		//case kDNSType_WKS not checked
-	case kDNSType_PTR:	len = DomainNameLength(&rd->u.name);
-		return(len <= MAX_DOMAIN_NAME && rdlength == len);
-
-	case kDNSType_HINFO:// Same as TXT (roughly)
-	case kDNSType_MINFO:// Same as TXT (roughly)
-	case kDNSType_TXT:  {
-		const mDNSu8 *ptr = rd->u.txt.c;
-		const mDNSu8 *end = rd->u.txt.c + rdlength;
-		while (ptr < end) ptr += 1 + ptr[0];
-		return (ptr == end);
-	}
-
-	case kDNSType_AAAA:	return(rdlength == sizeof(mDNSv6Addr));
-
-	case kDNSType_MX:   len = DomainNameLength(&rd->u.mx.exchange);
-		return(len <= MAX_DOMAIN_NAME && rdlength == 2+len);
-
-	case kDNSType_SRV:	len = DomainNameLength(&rd->u.srv.target);
-		return(len <= MAX_DOMAIN_NAME && rdlength == 6+len);
-
-	default:			return(mDNStrue);	// Allow all other types without checking
-	}
-}
-
-// Two records qualify to be local duplicates if the RecordTypes are the same, or if one is Unique and the other Verified
-#define RecordLDT(A,B) ((A)->resrec.RecordType == (B)->resrec.RecordType || ((A)->resrec.RecordType | (B)->resrec.RecordType) == (kDNSRecordTypeUnique | kDNSRecordTypeVerified))
-#define RecordIsLocalDuplicate(A,B) ((A)->resrec.InterfaceID == (B)->resrec.InterfaceID && RecordLDT((A),(B)) && IdenticalResourceRecord(&(A)->resrec, &(B)->resrec))
-
-mDNSlocal mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
-{
-	domainname *target = GetRRDomainNameTarget(&rr->resrec);
-	AuthRecord *r;
-	AuthRecord **p = &m->ResourceRecords;
-	AuthRecord **d = &m->DuplicateRecords;
-	AuthRecord **l = &m->LocalOnlyRecords;
-	
-#if TEST_LOCALONLY_FOR_EVERYTHING
-	rr->resrec.InterfaceID = (mDNSInterfaceID)~0;
-#endif
-
-	while (*p && *p != rr) p=&(*p)->next;
-	while (*d && *d != rr) d=&(*d)->next;
-	while (*l && *l != rr) l=&(*l)->next;
-	if (*d || *p || *l)
-	{
-		LogMsg("Error! Tried to register a AuthRecord %p %##s (%s) that's already in the list", rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-		return(mStatus_AlreadyRegistered);
-	}
-
-	if (rr->DependentOn)
-	{
-		if (rr->resrec.RecordType == kDNSRecordTypeUnique)
-			rr->resrec.RecordType =  kDNSRecordTypeVerified;
-		else
-		{
-			LogMsg("mDNS_Register_internal: ERROR! %##s (%s): rr->DependentOn && RecordType != kDNSRecordTypeUnique",
-			       rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-			return(mStatus_Invalid);
-		}
-		if (!(rr->DependentOn->resrec.RecordType & (kDNSRecordTypeUnique | kDNSRecordTypeVerified)))
-		{
-			LogMsg("mDNS_Register_internal: ERROR! %##s (%s): rr->DependentOn->RecordType bad type %X",
-			       rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype), rr->DependentOn->resrec.RecordType);
-			return(mStatus_Invalid);
-		}
-	}
-
-	// If this resource record is referencing a specific interface, make sure it exists
-	if (rr->resrec.InterfaceID && rr->resrec.InterfaceID != ((mDNSInterfaceID)~0))
-	{
-		NetworkInterfaceInfo *intf;
-		for (intf = m->HostInterfaces; intf; intf = intf->next)
-			if (intf->InterfaceID == rr->resrec.InterfaceID) break;
-		if (!intf)
-		{
-			debugf("mDNS_Register_internal: Bogus InterfaceID %p in resource record", rr->resrec.InterfaceID);
-			return(mStatus_BadReferenceErr);
-		}
-	}
-
-	rr->next = mDNSNULL;
-
-	// Field Group 1: Persistent metadata for Authoritative Records
-//	rr->Additional1       = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client
-//	rr->Additional2       = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client
-//	rr->DependentOn       = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client
-//	rr->RRSet             = set to mDNSNULL in mDNS_SetupResourceRecord; may be overridden by client
-//	rr->Callback          = already set in mDNS_SetupResourceRecord
-//	rr->Context           = already set in mDNS_SetupResourceRecord
-//	rr->RecordType        = already set in mDNS_SetupResourceRecord
-//	rr->HostTarget        = set to mDNSfalse in mDNS_SetupResourceRecord; may be overridden by client
-
-	// Field Group 2: Transient state for Authoritative Records
-	rr->Acknowledged      = mDNSfalse;
-	rr->ProbeCount        = DefaultProbeCountForRecordType(rr->resrec.RecordType);
-	rr->AnnounceCount     = InitialAnnounceCount;
-	rr->IncludeInProbe    = mDNSfalse;
-	rr->ImmedAnswer       = mDNSNULL;
-	rr->ImmedAdditional   = mDNSNULL;
-	rr->SendRNow          = mDNSNULL;
-	rr->v4Requester       = zeroIPAddr;
-	rr->v6Requester       = zerov6Addr;
-	rr->NextResponse      = mDNSNULL;
-	rr->NR_AnswerTo       = mDNSNULL;
-	rr->NR_AdditionalTo   = mDNSNULL;
-	rr->ThisAPInterval    = DefaultAPIntervalForRecordType(rr->resrec.RecordType);
-	InitializeLastAPTime(m, rr);
-//	rr->AnnounceUntil     = Set for us in InitializeLastAPTime()
-//	rr->LastAPTime        = Set for us in InitializeLastAPTime()
-//	rr->LastMCTime        = Set for us in InitializeLastAPTime()
-//	rr->LastMCInterface   = Set for us in InitializeLastAPTime()
-	rr->NewRData          = mDNSNULL;
-	rr->newrdlength       = 0;
-	rr->UpdateCallback    = mDNSNULL;
-	rr->UpdateCredits     = kMaxUpdateCredits;
-	rr->NextUpdateCredit  = 0;
-	rr->UpdateBlocked     = 0;
-
-//	rr->resrec.interface         = already set in mDNS_SetupResourceRecord
-//	rr->resrec.name.c            = MUST be set by client
-//	rr->resrec.rrtype            = already set in mDNS_SetupResourceRecord
-//	rr->resrec.rrclass           = already set in mDNS_SetupResourceRecord
-//	rr->resrec.rroriginalttl     = already set in mDNS_SetupResourceRecord
-//	rr->resrec.rdata             = MUST be set by client, unless record type is CNAME or PTR and rr->HostTarget is set
-
-	if (rr->HostTarget)
-	{
-		if (target) target->c[0] = 0;
-		SetTargetToHostName(m, rr);	// This also sets rdlength and rdestimate for us
-	}
-	else
-	{
-		rr->resrec.rdlength   = GetRDLength(&rr->resrec, mDNSfalse);
-		rr->resrec.rdestimate = GetRDLength(&rr->resrec, mDNStrue);
-	}
-
-	if (!ValidateDomainName(&rr->resrec.name))
-	{ LogMsg("Attempt to register record with invalid name: %s", GetRRDisplayString(m, rr)); return(mStatus_Invalid); }
-
-	// Don't do this until *after* we've set rr->resrec.rdlength
-	if (!ValidateRData(rr->resrec.rrtype, rr->resrec.rdlength, rr->resrec.rdata))
-	{ LogMsg("Attempt to register record with invalid rdata: %s", GetRRDisplayString(m, rr)); return(mStatus_Invalid); }
-
-	rr->resrec.namehash   = DomainNameHashValue(&rr->resrec.name);
-	rr->resrec.rdatahash  = RDataHashValue(rr->resrec.rdlength, &rr->resrec.rdata->u);
-	rr->resrec.rdnamehash = target ? DomainNameHashValue(target) : 0;
-	
-	if (rr->resrec.InterfaceID == ((mDNSInterfaceID)~0))
-	{
-		debugf("Adding %p %##s (%s) to LocalOnly list", rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-		*l = rr;
-		if (!m->NewLocalOnlyRecords) m->NewLocalOnlyRecords = rr;
-		// If this is supposed to be unique, make sure we don't have any name conflicts
-		if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
-		{
-			const AuthRecord *s1 = rr->RRSet ? rr->RRSet : rr;
-			for (r = m->LocalOnlyRecords; r; r=r->next)
-			{
-				const AuthRecord *s2 = r->RRSet ? r->RRSet : r;
-				if (s1 != s2 && SameResourceRecordSignature(&r->resrec, &rr->resrec) && !SameRData(&r->resrec, &rr->resrec))
-					break;
-			}
-			if (r)	// If we found a conflict, set DiscardLocalOnlyRecords so we'll deliver the callback
-			{
-				debugf("Name conflict %p %##s (%s)", rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-				m->DiscardLocalOnlyRecords = mDNStrue;
-			}
-			else	// else no conflict, so set ProbeCount to zero and update RecordType as appropriate
-			{
-				rr->ProbeCount = 0;
-				if (rr->resrec.RecordType == kDNSRecordTypeUnique) rr->resrec.RecordType = kDNSRecordTypeVerified;
-			}
-		}
-	}
-	else
-	{
-		// Now that's we've finished building our new record, make sure it's not identical to one we already have
-		for (r = m->ResourceRecords; r; r=r->next) if (RecordIsLocalDuplicate(r, rr)) break;
-		
-		if (r)
-		{
-			debugf("Adding %p %##s (%s) to duplicate list", rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-			*d = rr;
-			// If the previous copy of this record is already verified unique,
-			// then indicate that we should move this record promptly to kDNSRecordTypeUnique state.
-			// Setting ProbeCount to zero will cause SendQueries() to advance this record to
-			// kDNSRecordTypeVerified state and call the client callback at the next appropriate time.
-			if (rr->resrec.RecordType == kDNSRecordTypeUnique && r->resrec.RecordType == kDNSRecordTypeVerified)
-				rr->ProbeCount = 0;
-		}
-		else
-		{
-			debugf("Adding %p %##s (%s) to active record list", rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-			*p = rr;
-		}
-	}
-	return(mStatus_NoError);
-}
-
-mDNSlocal void RecordProbeFailure(mDNS *const m, const AuthRecord *const rr)
-{
-	m->ProbeFailTime = m->timenow;
-	m->NumFailedProbes++;
-	// If we've had ten or more probe failures, rate-limit to one every five seconds
-	// The result is ORed with 1 to make sure SuppressProbes is not accidentally set to zero
-	if (m->NumFailedProbes >= 10) m->SuppressProbes = (m->timenow + mDNSPlatformOneSecond * 5) | 1;
-	if (m->NumFailedProbes >= 16)
-		LogMsg("Name in use: %##s (%s); need to choose another (%d)",
-		       rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype), m->NumFailedProbes);
-}
-
-// mDNS_Dereg_normal is used for most calls to mDNS_Deregister_internal
-// mDNS_Dereg_conflict is used to indicate that this record is being forcibly deregistered because of a conflict
-// mDNS_Dereg_repeat is used when cleaning up, for records that may have already been forcibly deregistered
-typedef enum { mDNS_Dereg_normal, mDNS_Dereg_conflict, mDNS_Dereg_repeat } mDNS_Dereg_type;
-
-// NOTE: mDNS_Deregister_internal can call a user callback, which may change the record list and/or question list.
-// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
-mDNSlocal mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr, mDNS_Dereg_type drt)
-{
-	mDNSu8 RecordType = rr->resrec.RecordType;
-	AuthRecord **p = &m->ResourceRecords;	// Find this record in our list of active records
-	if (rr->resrec.InterfaceID == ((mDNSInterfaceID)~0)) p = &m->LocalOnlyRecords;
-	while (*p && *p != rr) p=&(*p)->next;
-
-	if (*p)
-	{
-		// We found our record on the main list. See if there are any duplicates that need special handling.
-		if (drt == mDNS_Dereg_conflict)		// If this was a conflict, see that all duplicates get the same treatment
-		{
-			AuthRecord *r2 = m->DuplicateRecords;
-			while (r2)
-			{
-				if (RecordIsLocalDuplicate(r2, rr)) { mDNS_Deregister_internal(m, r2, drt); r2 = m->DuplicateRecords; }
-				else r2=r2->next;
-			}
-		}
-		else
-		{
-			// Before we delete the record (and potentially send a goodbye packet)
-			// first see if we have a record on the duplicate list ready to take over from it.
-			AuthRecord **d = &m->DuplicateRecords;
-			while (*d && !RecordIsLocalDuplicate(*d, rr)) d=&(*d)->next;
-			if (*d)
-			{
-				AuthRecord *dup = *d;
-				debugf("Duplicate record %p taking over from %p %##s (%s)", dup, rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-				*d        = dup->next;		// Cut replacement record from DuplicateRecords list
-				dup->next = rr->next;		// And then...
-				rr->next  = dup;			// ... splice it in right after the record we're about to delete
-				dup->resrec.RecordType        = rr->resrec.RecordType;
-				dup->ProbeCount        = rr->ProbeCount;
-				dup->AnnounceCount     = rr->AnnounceCount;
-				dup->ImmedAnswer       = rr->ImmedAnswer;
-				dup->ImmedAdditional   = rr->ImmedAdditional;
-				dup->v4Requester       = rr->v4Requester;
-				dup->v6Requester       = rr->v6Requester;
-				dup->ThisAPInterval    = rr->ThisAPInterval;
-				dup->AnnounceUntil     = rr->AnnounceUntil;
-				dup->LastAPTime        = rr->LastAPTime;
-				dup->LastMCTime        = rr->LastMCTime;
-				dup->LastMCInterface   = rr->LastMCInterface;
-				if (RecordType == kDNSRecordTypeShared) rr->AnnounceCount = InitialAnnounceCount;
-			}
-		}
-	}
-	else
-	{
-		// We didn't find our record on the main list; try the DuplicateRecords list instead.
-		p = &m->DuplicateRecords;
-		while (*p && *p != rr) p=&(*p)->next;
-		// If we found our record on the duplicate list, then make sure we don't send a goodbye for it
-		if (*p && RecordType == kDNSRecordTypeShared) rr->AnnounceCount = InitialAnnounceCount;
-		if (*p) debugf("DNS_Deregister_internal: Deleting DuplicateRecord %p %##s (%s)", rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-	}
-
-	if (!*p)
-	{
-		// No need to log an error message if we already know this is a potentially repeated deregistration
-		if (drt != mDNS_Dereg_repeat)
-			debugf("mDNS_Deregister_internal: Record %p %##s (%s) not found in list", rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-		return(mStatus_BadReferenceErr);
-	}
-
-	// If this is a shared record and we've announced it at least once,
-	// we need to retract that announcement before we delete the record
-	if (RecordType == kDNSRecordTypeShared && rr->AnnounceCount < InitialAnnounceCount)
-	{
-		verbosedebugf("mDNS_Deregister_internal: Sending deregister for %##s (%s)", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-		rr->resrec.RecordType    = kDNSRecordTypeDeregistering;
-		rr->resrec.rroriginalttl = 0;
-		rr->ImmedAnswer          = mDNSInterfaceMark;
-		if (rr->resrec.InterfaceID == ((mDNSInterfaceID)~0))
-			m->DiscardLocalOnlyRecords = mDNStrue;
-		else
-		{
-			if (m->NextScheduledResponse - (m->timenow + mDNSPlatformOneSecond/10) >= 0)
-				m->NextScheduledResponse = (m->timenow + mDNSPlatformOneSecond/10);
-		}
-	}
-	else
-	{
-		*p = rr->next;					// Cut this record from the list
-		// If someone is about to look at this, bump the pointer forward
-		if (m->CurrentRecord       == rr) m->CurrentRecord       = rr->next;
-		if (m->NewLocalOnlyRecords == rr) m->NewLocalOnlyRecords = rr->next;
-		rr->next = mDNSNULL;
-
-		if      (RecordType == kDNSRecordTypeUnregistered)
-			debugf("mDNS_Deregister_internal: Record %##s (%s) already marked kDNSRecordTypeUnregistered",
-			       rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-		else if (RecordType == kDNSRecordTypeDeregistering)
-			debugf("mDNS_Deregister_internal: Record %##s (%s) already marked kDNSRecordTypeDeregistering",
-			       rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-		else
-		{
-			verbosedebugf("mDNS_Deregister_internal: Deleting record for %##s (%s)", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-			rr->resrec.RecordType = kDNSRecordTypeUnregistered;
-		}
-
-		if ((drt == mDNS_Dereg_conflict || drt == mDNS_Dereg_repeat) && RecordType == kDNSRecordTypeShared)
-			debugf("mDNS_Deregister_internal: Cannot have a conflict on a shared record! %##s (%s)",
-			       rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-
-		// If we have an update queued up which never executed, give the client a chance to free that memory
-		if (rr->NewRData)
-		{
-			RData *OldRData = rr->resrec.rdata;
-			SetNewRData(&rr->resrec, rr->NewRData, rr->newrdlength);	// Update our rdata
-			rr->NewRData = mDNSNULL;									// Clear the NewRData pointer ...
-			if (rr->UpdateCallback)
-				rr->UpdateCallback(m, rr, OldRData);					// ... and let the client know
-		}
-		
-		// CAUTION: MUST NOT do anything more with rr after calling rr->Callback(), because the client's callback function
-		// is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc.
-		// In this case the likely client action to the mStatus_MemFree message is to free the memory,
-		// so any attempt to touch rr after this is likely to lead to a crash.
-		m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback
-		if (RecordType == kDNSRecordTypeShared)
-		{
-			if (rr->RecordCallback)
-				rr->RecordCallback(m, rr, mStatus_MemFree);
-		}
-		else if (drt == mDNS_Dereg_conflict)
-		{
-			RecordProbeFailure(m, rr);
-			if (rr->RecordCallback)
-				rr->RecordCallback(m, rr, mStatus_NameConflict);
-		}
-		m->mDNS_reentrancy--; // Decrement to block mDNS API calls again
-	}
-	return(mStatus_NoError);
-}
-
-// ***************************************************************************
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark -
-#pragma mark - DNS Message Creation Functions
-#endif
-
-mDNSlocal void InitializeDNSMessage(DNSMessageHeader *h, mDNSOpaque16 id, mDNSOpaque16 flags)
-{
-	h->id             = id;
-	h->flags          = flags;
-	h->numQuestions   = 0;
-	h->numAnswers     = 0;
-	h->numAuthorities = 0;
-	h->numAdditionals = 0;
-}
-
-mDNSlocal const mDNSu8 *FindCompressionPointer(const mDNSu8 *const base, const mDNSu8 *const end, const mDNSu8 *const domname)
-{
-	const mDNSu8 *result = end - *domname - 1;
-
-	if (*domname == 0) return(mDNSNULL);	// There's no point trying to match just the root label
-	
-	// This loop examines each possible starting position in packet, starting end of the packet and working backwards
-	while (result >= base)
-	{
-		// If the length byte and first character of the label match, then check further to see
-		// if this location in the packet will yield a useful name compression pointer.
-		if (result[0] == domname[0] && result[1] == domname[1])
-		{
-			const mDNSu8 *name = domname;
-			const mDNSu8 *targ = result;
-			while (targ + *name < end)
-			{
-				// First see if this label matches
-				int i;
-				const mDNSu8 *pointertarget;
-				for (i=0; i <= *name; i++) if (targ[i] != name[i]) break;
-				if (i <= *name) break;							// If label did not match, bail out
-				targ += 1 + *name;								// Else, did match, so advance target pointer
-				name += 1 + *name;								// and proceed to check next label
-				if (*name == 0 && *targ == 0) return(result);	// If no more labels, we found a match!
-				if (*name == 0) break;							// If no more labels to match, we failed, so bail out
-
-				// The label matched, so now follow the pointer (if appropriate) and then see if the next label matches
-				if (targ[0] < 0x40) continue;					// If length value, continue to check next label
-				if (targ[0] < 0xC0) break;						// If 40-BF, not valid
-				if (targ+1 >= end) break;						// Second byte not present!
-				pointertarget = base + (((mDNSu16)(targ[0] & 0x3F)) << 8) + targ[1];
-				if (targ < pointertarget) break;				// Pointertarget must point *backwards* in the packet
-				if (pointertarget[0] >= 0x40) break;			// Pointertarget must point to a valid length byte
-				targ = pointertarget;
-			}
-		}
-		result--;	// We failed to match at this search position, so back up the tentative result pointer and try again
-	}
-	return(mDNSNULL);
-}
-
-// Put a string of dot-separated labels as length-prefixed labels
-// domainname is a fully-qualified name (i.e. assumed to be ending in a dot, even if it doesn't)
-// msg points to the message we're building (pass mDNSNULL if we don't want to use compression pointers)
-// end points to the end of the message so far
-// ptr points to where we want to put the name
-// limit points to one byte past the end of the buffer that we must not overrun
-// domainname is the name to put
-mDNSlocal mDNSu8 *putDomainNameAsLabels(const DNSMessage *const msg,
-					mDNSu8 *ptr, const mDNSu8 *const limit, const domainname *const name)
-{
-	const mDNSu8 *const base        = (const mDNSu8 *)msg;
-	const mDNSu8 *      np          = name->c;
-	const mDNSu8 *const max         = name->c + MAX_DOMAIN_NAME;	// Maximum that's valid
-	const mDNSu8 *      pointer     = mDNSNULL;
-	const mDNSu8 *const searchlimit = ptr;
-
-	while (*np && ptr < limit-1)		// While we've got characters in the name, and space to write them in the message...
-	{
-		if (*np > MAX_DOMAIN_LABEL)
-		{ LogMsg("Malformed domain name %##s (label more than 63 bytes)", name->c); return(mDNSNULL); }
-		
-		// This check correctly allows for the final trailing root label:
-		// e.g.
-		// Suppose our domain name is exactly 255 bytes long, including the final trailing root label.
-		// Suppose np is now at name->c[248], and we're about to write our last non-null label ("local").
-		// We know that max will be at name->c[255]
-		// That means that np + 1 + 5 == max - 1, so we (just) pass the "if" test below, write our
-		// six bytes, then exit the loop, write the final terminating root label, and the domain
-		// name we've written is exactly 255 bytes long, exactly at the correct legal limit.
-		// If the name is one byte longer, then we fail the "if" test below, and correctly bail out.
-		if (np + 1 + *np >= max)
-		{ LogMsg("Malformed domain name %##s (more than 255 bytes)", name->c); return(mDNSNULL); }
-
-		if (base) pointer = FindCompressionPointer(base, searchlimit, np);
-		if (pointer)					// Use a compression pointer if we can
-		{
-			mDNSu16 offset = (mDNSu16)(pointer - base);
-			*ptr++ = (mDNSu8)(0xC0 | (offset >> 8));
-			*ptr++ = (mDNSu8)(        offset      );
-			return(ptr);
-		}
-		else							// Else copy one label and try again
-		{
-			int i;
-			mDNSu8 len = *np++;
-			if (ptr + 1 + len >= limit) return(mDNSNULL);
-			*ptr++ = len;
-			for (i=0; i<len; i++) *ptr++ = *np++;
-		}
-	}
-
-	if (ptr < limit)												// If we didn't run out of space
-	{
-		*ptr++ = 0;													// Put the final root label
-		return(ptr);												// and return
-	}
-
-	return(mDNSNULL);
-}
-
-mDNSlocal mDNSu8 *putRData(const DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit, ResourceRecord *rr)
-{
-	switch (rr->rrtype)
-	{
-	case kDNSType_A:	if (rr->rdlength != 4)
-	{
-		debugf("putRData: Illegal length %d for kDNSType_A", rr->rdlength);
-		return(mDNSNULL);
-	}
-		if (ptr + 4 > limit) return(mDNSNULL);
-		*ptr++ = rr->rdata->u.ip.b[0];
-		*ptr++ = rr->rdata->u.ip.b[1];
-		*ptr++ = rr->rdata->u.ip.b[2];
-		*ptr++ = rr->rdata->u.ip.b[3];
-		return(ptr);
-
-	case kDNSType_CNAME:// Same as PTR
-	case kDNSType_PTR:	return(putDomainNameAsLabels(msg, ptr, limit, &rr->rdata->u.name));
-
-	case kDNSType_HINFO:// Same as TXT
-	case kDNSType_TXT:  if (ptr + rr->rdlength > limit) return(mDNSNULL);
-		mDNSPlatformMemCopy(rr->rdata->u.data, ptr, rr->rdlength);
-		return(ptr + rr->rdlength);
-
-	case kDNSType_AAAA:	if (rr->rdlength != sizeof(rr->rdata->u.ipv6))
-	{
-		debugf("putRData: Illegal length %d for kDNSType_AAAA", rr->rdlength);
-		return(mDNSNULL);
-	}
-		if (ptr + sizeof(rr->rdata->u.ipv6) > limit) return(mDNSNULL);
-		mDNSPlatformMemCopy(&rr->rdata->u.ipv6, ptr, sizeof(rr->rdata->u.ipv6));
-		return(ptr + sizeof(rr->rdata->u.ipv6));
-
-	case kDNSType_SRV:	if (ptr + 6 > limit) return(mDNSNULL);
-		*ptr++ = (mDNSu8)(rr->rdata->u.srv.priority >> 8);
-		*ptr++ = (mDNSu8)(rr->rdata->u.srv.priority     );
-		*ptr++ = (mDNSu8)(rr->rdata->u.srv.weight   >> 8);
-		*ptr++ = (mDNSu8)(rr->rdata->u.srv.weight       );
-		*ptr++ = rr->rdata->u.srv.port.b[0];
-		*ptr++ = rr->rdata->u.srv.port.b[1];
-		return(putDomainNameAsLabels(msg, ptr, limit, &rr->rdata->u.srv.target));
-
-	default:			if (ptr + rr->rdlength > limit) return(mDNSNULL);
-		debugf("putRData: Warning! Writing resource type %d as raw data", rr->rrtype);
-		mDNSPlatformMemCopy(rr->rdata->u.data, ptr, rr->rdlength);
-		return(ptr + rr->rdlength);
-	}
-}
-
-mDNSlocal mDNSu8 *PutResourceRecordTTL(DNSMessage *const msg, mDNSu8 *ptr, mDNSu16 *count, ResourceRecord *rr, mDNSu32 ttl)
-{
-	mDNSu8 *endofrdata;
-	mDNSu16 actualLength;
-	const mDNSu8 *limit = msg->data + AbsoluteMaxDNSMessageData;
-	
-	// If we have a single large record to put in the packet, then we allow the packet to be up to 9K bytes,
-	// but in the normal case we try to keep the packets below 1500 to avoid IP fragmentation on standard Ethernet
-	if (msg->h.numAnswers || msg->h.numAuthorities || msg->h.numAdditionals)
-		limit = msg->data + NormalMaxDNSMessageData;
-
-	if (rr->RecordType == kDNSRecordTypeUnregistered)
-	{
-		LogMsg("PutResourceRecord ERROR! Attempt to put kDNSRecordTypeUnregistered %##s (%s)", rr->name.c, DNSTypeName(rr->rrtype));
-		return(ptr);
-	}
-
-	ptr = putDomainNameAsLabels(msg, ptr, limit, &rr->name);
-	if (!ptr || ptr + 10 >= limit) return(mDNSNULL);	// If we're out-of-space, return mDNSNULL
-	ptr[0] = (mDNSu8)(rr->rrtype  >> 8);
-	ptr[1] = (mDNSu8)(rr->rrtype      );
-	ptr[2] = (mDNSu8)(rr->rrclass >> 8);
-	ptr[3] = (mDNSu8)(rr->rrclass     );
-	ptr[4] = (mDNSu8)(ttl >> 24);
-	ptr[5] = (mDNSu8)(ttl >> 16);
-	ptr[6] = (mDNSu8)(ttl >>  8);
-	ptr[7] = (mDNSu8)(ttl      );
-	endofrdata = putRData(msg, ptr+10, limit, rr);
-	if (!endofrdata) { verbosedebugf("Ran out of space in PutResourceRecord for %##s (%s)", rr->name.c, DNSTypeName(rr->rrtype)); return(mDNSNULL); }
-
-	// Go back and fill in the actual number of data bytes we wrote
-	// (actualLength can be less than rdlength when domain name compression is used)
-	actualLength = (mDNSu16)(endofrdata - ptr - 10);
-	ptr[8] = (mDNSu8)(actualLength >> 8);
-	ptr[9] = (mDNSu8)(actualLength     );
-
-	(*count)++;
-	return(endofrdata);
-}
-
-#define PutResourceRecord(MSG, P, C, RR) PutResourceRecordTTL((MSG), (P), (C), (RR), (RR)->rroriginalttl)
-
-mDNSlocal mDNSu8 *PutResourceRecordCappedTTL(DNSMessage *const msg, mDNSu8 *ptr, mDNSu16 *count, ResourceRecord *rr, mDNSu32 maxttl)
-{
-	if (maxttl > rr->rroriginalttl) maxttl = rr->rroriginalttl;
-	return(PutResourceRecordTTL(msg, ptr, count, rr, maxttl));
-}
-
-#if 0
-mDNSlocal mDNSu8 *putEmptyResourceRecord(DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit,
-					 mDNSu16 *count, const AuthRecord *rr)
-{
-	ptr = putDomainNameAsLabels(msg, ptr, limit, &rr->name);
-	if (!ptr || ptr + 10 > limit) return(mDNSNULL);		// If we're out-of-space, return mDNSNULL
-	ptr[0] = (mDNSu8)(rr->resrec.rrtype  >> 8);				// Put type
-	ptr[1] = (mDNSu8)(rr->resrec.rrtype      );
-	ptr[2] = (mDNSu8)(rr->resrec.rrclass >> 8);				// Put class
-	ptr[3] = (mDNSu8)(rr->resrec.rrclass     );
-	ptr[4] = ptr[5] = ptr[6] = ptr[7] = 0;				// TTL is zero
-	ptr[8] = ptr[9] = 0;								// RDATA length is zero
-	(*count)++;
-	return(ptr + 10);
-}
-#endif
-
-mDNSlocal mDNSu8 *putQuestion(DNSMessage *const msg, mDNSu8 *ptr, const mDNSu8 *const limit,
-			      const domainname *const name, mDNSu16 rrtype, mDNSu16 rrclass)
-{
-	ptr = putDomainNameAsLabels(msg, ptr, limit, name);
-	if (!ptr || ptr+4 >= limit) return(mDNSNULL);			// If we're out-of-space, return mDNSNULL
-	ptr[0] = (mDNSu8)(rrtype  >> 8);
-	ptr[1] = (mDNSu8)(rrtype      );
-	ptr[2] = (mDNSu8)(rrclass >> 8);
-	ptr[3] = (mDNSu8)(rrclass     );
-	msg->h.numQuestions++;
-	return(ptr+4);
-}
-
-// ***************************************************************************
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - DNS Message Parsing Functions
-#endif
-
-mDNSlocal const mDNSu8 *skipDomainName(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end)
-{
-	mDNSu16 total = 0;
-
-	if (ptr < (mDNSu8*)msg || ptr >= end)
-	{ debugf("skipDomainName: Illegal ptr not within packet boundaries"); return(mDNSNULL); }
-
-	while (1)						// Read sequence of labels
-	{
-		const mDNSu8 len = *ptr++;	// Read length of this label
-		if (len == 0) return(ptr);	// If length is zero, that means this name is complete
-		switch (len & 0xC0)
-		{
-		case 0x00:	if (ptr + len >= end)					// Remember: expect at least one more byte for the root label
-		{ debugf("skipDomainName: Malformed domain name (overruns packet end)"); return(mDNSNULL); }
-			if (total + 1 + len >= MAX_DOMAIN_NAME)	// Remember: expect at least one more byte for the root label
-			{ debugf("skipDomainName: Malformed domain name (more than 255 characters)"); return(mDNSNULL); }
-			ptr += len;
-			total += 1 + len;
-			break;
-
-		case 0x40:	debugf("skipDomainName: Extended EDNS0 label types 0x%X not supported", len); return(mDNSNULL);
-		case 0x80:	debugf("skipDomainName: Illegal label length 0x%X", len); return(mDNSNULL);
-		case 0xC0:	return(ptr+1);
-		}
-	}
-}
-
-// Routine to fetch an FQDN from the DNS message, following compression pointers if necessary.
-mDNSlocal const mDNSu8 *getDomainName(const DNSMessage *const msg, const mDNSu8 *ptr, const mDNSu8 *const end,
-				      domainname *const name)
-{
-	const mDNSu8 *nextbyte = mDNSNULL;					// Record where we got to before we started following pointers
-	mDNSu8       *np = name->c;							// Name pointer
-	const mDNSu8 *const limit = np + MAX_DOMAIN_NAME;	// Limit so we don't overrun buffer
-
-	if (ptr < (mDNSu8*)msg || ptr >= end)
-	{ debugf("getDomainName: Illegal ptr not within packet boundaries"); return(mDNSNULL); }
-
-	*np = 0;						// Tentatively place the root label here (may be overwritten if we have more labels)
-
-	while (1)						// Read sequence of labels
-	{
-		const mDNSu8 len = *ptr++;	// Read length of this label
-		if (len == 0) break;		// If length is zero, that means this name is complete
-		switch (len & 0xC0)
-		{
-			int i;
-			mDNSu16 offset;
-
-		case 0x00:	if (ptr + len >= end)		// Remember: expect at least one more byte for the root label
-		{ debugf("getDomainName: Malformed domain name (overruns packet end)"); return(mDNSNULL); }
-		if (np + 1 + len >= limit)	// Remember: expect at least one more byte for the root label
-		{ debugf("getDomainName: Malformed domain name (more than 255 characters)"); return(mDNSNULL); }
-		*np++ = len;
-		for (i=0; i<len; i++) *np++ = *ptr++;
-		*np = 0;	// Tentatively place the root label here (may be overwritten if we have more labels)
-		break;
-
-		case 0x40:	debugf("getDomainName: Extended EDNS0 label types 0x%X not supported in name %##s", len, name->c);
-		return(mDNSNULL);
-
-		case 0x80:	debugf("getDomainName: Illegal label length 0x%X in domain name %##s", len, name->c); return(mDNSNULL);
-
-		case 0xC0:	offset = (mDNSu16)((((mDNSu16)(len & 0x3F)) << 8) | *ptr++);
-			if (!nextbyte) nextbyte = ptr;	// Record where we got to before we started following pointers
-			ptr = (mDNSu8 *)msg + offset;
-			if (ptr < (mDNSu8*)msg || ptr >= end)
-			{ debugf("getDomainName: Illegal compression pointer not within packet boundaries"); return(mDNSNULL); }
-			if (*ptr & 0xC0)
-			{ debugf("getDomainName: Compression pointer must point to real label"); return(mDNSNULL); }
-			break;
-		}
-	}
-	
-	if (nextbyte) return(nextbyte);
-	else return(ptr);
-}
-
-mDNSlocal const mDNSu8 *skipResourceRecord(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end)
-{
-	mDNSu16 pktrdlength;
-
-	ptr = skipDomainName(msg, ptr, end);
-	if (!ptr) { debugf("skipResourceRecord: Malformed RR name"); return(mDNSNULL); }
-	
-	if (ptr + 10 > end) { debugf("skipResourceRecord: Malformed RR -- no type/class/ttl/len!"); return(mDNSNULL); }
-	pktrdlength = (mDNSu16)((mDNSu16)ptr[8] <<  8 | ptr[9]);
-	ptr += 10;
-	if (ptr + pktrdlength > end) { debugf("skipResourceRecord: RDATA exceeds end of packet"); return(mDNSNULL); }
-
-	return(ptr + pktrdlength);
-}
-
-#define GetLargeResourceRecord(m, msg, p, e, i, t, L) \
-	(((L)->r.rdatastorage.MaxRDLength = MaximumRDSize), GetResourceRecord((m), (msg), (p), (e), (i), (t), &(L)->r, (RData*)&(L)->r.rdatastorage))
-
-mDNSlocal const mDNSu8 *GetResourceRecord(mDNS *const m, const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end,
-					  const mDNSInterfaceID InterfaceID, mDNSu8 RecordType, CacheRecord *rr, RData *RDataStorage)
-{
-	mDNSu16 pktrdlength;
-
-	rr->next              = mDNSNULL;
-	rr->resrec.RecordType        = RecordType;
-
-	rr->NextInKAList      = mDNSNULL;
-	rr->TimeRcvd          = m->timenow;
-	rr->NextRequiredQuery = m->timenow;		// Will be updated to the real value when we call SetNextCacheCheckTime()
-	rr->LastUsed          = m->timenow;
-	rr->UseCount          = 0;
-	rr->CRActiveQuestion  = mDNSNULL;
-	rr->UnansweredQueries = 0;
-	rr->LastUnansweredTime= 0;
-	rr->MPUnansweredQ     = 0;
-	rr->MPLastUnansweredQT= 0;
-	rr->MPUnansweredKA    = 0;
-	rr->MPExpectingKA     = mDNSfalse;
-	rr->NextInCFList      = mDNSNULL;
-
-	rr->resrec.InterfaceID       = InterfaceID;
-	ptr = getDomainName(msg, ptr, end, &rr->resrec.name);
-	if (!ptr) { debugf("GetResourceRecord: Malformed RR name"); return(mDNSNULL); }
-
-	if (ptr + 10 > end) { debugf("GetResourceRecord: Malformed RR -- no type/class/ttl/len!"); return(mDNSNULL); }
-	
-	rr->resrec.rrtype            = (mDNSu16) ((mDNSu16)ptr[0] <<  8 | ptr[1]);
-	rr->resrec.rrclass           = (mDNSu16)(((mDNSu16)ptr[2] <<  8 | ptr[3]) & kDNSClass_Mask);
-	rr->resrec.rroriginalttl     = (mDNSu32) ((mDNSu32)ptr[4] << 24 | (mDNSu32)ptr[5] << 16 | (mDNSu32)ptr[6] << 8 | ptr[7]);
-	if (rr->resrec.rroriginalttl > 0x70000000UL / mDNSPlatformOneSecond)
-		rr->resrec.rroriginalttl = 0x70000000UL / mDNSPlatformOneSecond;
-	// Note: We don't have to adjust m->NextCacheCheck here -- this is just getting a record into memory for
-	// us to look at. If we decide to copy it into the cache, then we'll update m->NextCacheCheck accordingly.
-	pktrdlength           = (mDNSu16)((mDNSu16)ptr[8] <<  8 | ptr[9]);
-	if (ptr[2] & (kDNSClass_UniqueRRSet >> 8))
-		rr->resrec.RecordType |= kDNSRecordTypePacketUniqueMask;
-	ptr += 10;
-	if (ptr + pktrdlength > end) { debugf("GetResourceRecord: RDATA exceeds end of packet"); return(mDNSNULL); }
-
-	if (RDataStorage)
-		rr->resrec.rdata = RDataStorage;
-	else
-	{
-		rr->resrec.rdata = (RData*)&rr->rdatastorage;
-		rr->resrec.rdata->MaxRDLength = sizeof(RDataBody);
-	}
-
-	switch (rr->resrec.rrtype)
-	{
-	case kDNSType_A:	rr->resrec.rdata->u.ip.b[0] = ptr[0];
-		rr->resrec.rdata->u.ip.b[1] = ptr[1];
-		rr->resrec.rdata->u.ip.b[2] = ptr[2];
-		rr->resrec.rdata->u.ip.b[3] = ptr[3];
-		break;
-
-	case kDNSType_CNAME:// Same as PTR
-	case kDNSType_PTR:	if (!getDomainName(msg, ptr, end, &rr->resrec.rdata->u.name))
-	{ debugf("GetResourceRecord: Malformed CNAME/PTR RDATA name"); return(mDNSNULL); }
-		//debugf("%##s PTR %##s rdlen %d", rr->resrec.name.c, rr->resrec.rdata->u.name.c, pktrdlength);
-		break;
-
-	case kDNSType_NULL:	//Same as TXT
-	case kDNSType_HINFO://Same as TXT
-	case kDNSType_TXT:  if (pktrdlength > rr->resrec.rdata->MaxRDLength)
-	{
-		debugf("GetResourceRecord: %s rdata size (%d) exceeds storage (%d)",
-		       DNSTypeName(rr->resrec.rrtype), pktrdlength, rr->resrec.rdata->MaxRDLength);
-		return(mDNSNULL);
-	}
-		rr->resrec.rdlength = pktrdlength;
-		mDNSPlatformMemCopy(ptr, rr->resrec.rdata->u.data, pktrdlength);
-		break;
-
-	case kDNSType_AAAA:	mDNSPlatformMemCopy(ptr, &rr->resrec.rdata->u.ipv6, sizeof(rr->resrec.rdata->u.ipv6));
-		break;
-
-	case kDNSType_SRV:	rr->resrec.rdata->u.srv.priority = (mDNSu16)((mDNSu16)ptr[0] <<  8 | ptr[1]);
-		rr->resrec.rdata->u.srv.weight   = (mDNSu16)((mDNSu16)ptr[2] <<  8 | ptr[3]);
-		rr->resrec.rdata->u.srv.port.b[0] = ptr[4];
-		rr->resrec.rdata->u.srv.port.b[1] = ptr[5];
-		if (!getDomainName(msg, ptr+6, end, &rr->resrec.rdata->u.srv.target))
-		{ debugf("GetResourceRecord: Malformed SRV RDATA name"); return(mDNSNULL); }
-		//debugf("%##s SRV %##s rdlen %d", rr->resrec.name.c, rr->resrec.rdata->u.srv.target.c, pktrdlength);
-		break;
-
-	default:			if (pktrdlength > rr->resrec.rdata->MaxRDLength)
-	{
-		debugf("GetResourceRecord: rdata %d (%s) size (%d) exceeds storage (%d)",
-		       rr->resrec.rrtype, DNSTypeName(rr->resrec.rrtype), pktrdlength, rr->resrec.rdata->MaxRDLength);
-		return(mDNSNULL);
-	}
-		debugf("GetResourceRecord: Warning! Reading resource type %d (%s) as opaque data",
-		       rr->resrec.rrtype, DNSTypeName(rr->resrec.rrtype));
-		// Note: Just because we don't understand the record type, that doesn't
-		// mean we fail. The DNS protocol specifies rdlength, so we can
-		// safely skip over unknown records and ignore them.
-		// We also grab a binary copy of the rdata anyway, since the caller
-		// might know how to interpret it even if we don't.
-		rr->resrec.rdlength = pktrdlength;
-		mDNSPlatformMemCopy(ptr, rr->resrec.rdata->u.data, pktrdlength);
-		break;
-	}
-
-	rr->resrec.namehash = DomainNameHashValue(&rr->resrec.name);
-	SetNewRData(&rr->resrec, mDNSNULL, 0);
-
-	return(ptr + pktrdlength);
-}
-
-mDNSlocal const mDNSu8 *skipQuestion(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end)
-{
-	ptr = skipDomainName(msg, ptr, end);
-	if (!ptr) { debugf("skipQuestion: Malformed domain name in DNS question section"); return(mDNSNULL); }
-	if (ptr+4 > end) { debugf("skipQuestion: Malformed DNS question section -- no query type and class!"); return(mDNSNULL); }
-	return(ptr+4);
-}
-
-mDNSlocal const mDNSu8 *getQuestion(const DNSMessage *msg, const mDNSu8 *ptr, const mDNSu8 *end, const mDNSInterfaceID InterfaceID,
-				    DNSQuestion *question)
-{
-	question->InterfaceID = InterfaceID;
-	ptr = getDomainName(msg, ptr, end, &question->qname);
-	if (!ptr) { debugf("Malformed domain name in DNS question section"); return(mDNSNULL); }
-	if (ptr+4 > end) { debugf("Malformed DNS question section -- no query type and class!"); return(mDNSNULL); }
-
-	question->qnamehash = DomainNameHashValue(&question->qname);
-	question->qtype  = (mDNSu16)((mDNSu16)ptr[0] << 8 | ptr[1]);			// Get type
-	question->qclass = (mDNSu16)((mDNSu16)ptr[2] << 8 | ptr[3]);			// and class
-	return(ptr+4);
-}
-
-mDNSlocal const mDNSu8 *LocateAnswers(const DNSMessage *const msg, const mDNSu8 *const end)
-{
-	int i;
-	const mDNSu8 *ptr = msg->data;
-	for (i = 0; i < msg->h.numQuestions && ptr; i++) ptr = skipQuestion(msg, ptr, end);
-	return(ptr);
-}
-
-mDNSlocal const mDNSu8 *LocateAuthorities(const DNSMessage *const msg, const mDNSu8 *const end)
-{
-	int i;
-	const mDNSu8 *ptr = LocateAnswers(msg, end);
-	for (i = 0; i < msg->h.numAnswers && ptr; i++) ptr = skipResourceRecord(msg, ptr, end);
-	return(ptr);
-}
-
-// ***************************************************************************
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark -
-#pragma mark - Packet Sending Functions
-#endif
-
-mDNSlocal mStatus mDNSSendDNSMessage(const mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end,
-				     mDNSInterfaceID InterfaceID, mDNSIPPort srcport, const mDNSAddr *dst, mDNSIPPort dstport)
-{
-	mStatus status;
-	mDNSu16 numQuestions   = msg->h.numQuestions;
-	mDNSu16 numAnswers     = msg->h.numAnswers;
-	mDNSu16 numAuthorities = msg->h.numAuthorities;
-	mDNSu16 numAdditionals = msg->h.numAdditionals;
-	
-	// Put all the integer values in IETF byte-order (MSB first, LSB second)
-	mDNSu8 *ptr = (mDNSu8 *)&msg->h.numQuestions;
-	*ptr++ = (mDNSu8)(numQuestions   >> 8);
-	*ptr++ = (mDNSu8)(numQuestions       );
-	*ptr++ = (mDNSu8)(numAnswers     >> 8);
-	*ptr++ = (mDNSu8)(numAnswers         );
-	*ptr++ = (mDNSu8)(numAuthorities >> 8);
-	*ptr++ = (mDNSu8)(numAuthorities     );
-	*ptr++ = (mDNSu8)(numAdditionals >> 8);
-	*ptr++ = (mDNSu8)(numAdditionals     );
-	
-	// Send the packet on the wire
-	status = mDNSPlatformSendUDP(m, msg, end, InterfaceID, srcport, dst, dstport);
-	
-	// Put all the integer values back the way they were before we return
-	msg->h.numQuestions   = numQuestions;
-	msg->h.numAnswers     = numAnswers;
-	msg->h.numAuthorities = numAuthorities;
-	msg->h.numAdditionals = numAdditionals;
-
-	return(status);
-}
-
-mDNSlocal void CompleteDeregistration(mDNS *const m, AuthRecord *rr)
-{
-	// Setting AnnounceCount to InitialAnnounceCount signals mDNS_Deregister_internal()
-	// that it should go ahead and immediately dispose of this registration
-	rr->resrec.RecordType    = kDNSRecordTypeShared;
-	rr->AnnounceCount = InitialAnnounceCount;
-	mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
-}
-
-// NOTE: DiscardDeregistrations calls mDNS_Deregister_internal which can call a user callback, which may change
-// the record list and/or question list.
-// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
-mDNSlocal void DiscardDeregistrations(mDNS *const m)
-{
-	if (m->CurrentRecord) LogMsg("DiscardDeregistrations ERROR m->CurrentRecord already set");
-	m->CurrentRecord = m->ResourceRecords;
-	
-	while (m->CurrentRecord)
-	{
-		AuthRecord *rr = m->CurrentRecord;
-		m->CurrentRecord = rr->next;
-		if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
-			CompleteDeregistration(m, rr);
-	}
-}
-
-mDNSlocal mDNSBool HaveSentEntireRRSet(const mDNS *const m, const AuthRecord *const rr, mDNSInterfaceID InterfaceID)
-{
-	// Try to find another member of this set that we're still planning to send on this interface
-	const AuthRecord *a;
-	for (a = m->ResourceRecords; a; a=a->next)
-		if (a->SendRNow == InterfaceID && a != rr && SameResourceRecordSignature(&a->resrec, &rr->resrec)) break;
-	return (a == mDNSNULL);		// If no more members of this set found, then we should set the cache flush bit
-}
-
-// Note about acceleration of announcements to facilitate automatic coalescing of
-// multiple independent threads of announcements into a single synchronized thread:
-// The announcements in the packet may be at different stages of maturity;
-// One-second interval, two-second interval, four-second interval, and so on.
-// After we've put in all the announcements that are due, we then consider
-// whether there are other nearly-due announcements that are worth accelerating.
-// To be eligible for acceleration, a record MUST NOT be older (further along
-// its timeline) than the most mature record we've already put in the packet.
-// In other words, younger records can have their timelines accelerated to catch up
-// with their elder bretheren; this narrows the age gap and helps them eventually get in sync.
-// Older records cannot have their timelines accelerated; this would just widen
-// the gap between them and their younger bretheren and get them even more out of sync.
-
-// NOTE: SendResponses calls mDNS_Deregister_internal which can call a user callback, which may change
-// the record list and/or question list.
-// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
-mDNSlocal void SendResponses(mDNS *const m)
-{
-	int pktcount = 0;
-	AuthRecord *rr, *r2;
-	mDNSs32 maxExistingAnnounceInterval = 0;
-	const NetworkInterfaceInfo *intf = GetFirstActiveInterface(m->HostInterfaces);
-
-	m->NextScheduledResponse = m->timenow + kNextScheduledTime;
-
-	// ***
-	// *** 1. Setup: Set the SendRNow and ImmedAnswer fields to indicate which interface(s) the records need to be sent on
-	// ***
-
-	// Run through our list of records, and decide which ones we're going to announce on all interfaces
-	for (rr = m->ResourceRecords; rr; rr=rr->next)
-	{
-		if (rr->NextUpdateCredit && m->timenow - rr->NextUpdateCredit >= 0)
-		{
-			if (++rr->UpdateCredits >= kMaxUpdateCredits) rr->NextUpdateCredit = 0; 
-			else rr->NextUpdateCredit = (m->timenow + mDNSPlatformOneSecond * 60) | 1;
-		}
-		if (TimeToAnnounceThisRecord(rr, m->timenow) && ResourceRecordIsValidAnswer(rr))
-		{
-			rr->ImmedAnswer = mDNSInterfaceMark;		// Send on all interfaces
-			if (maxExistingAnnounceInterval < rr->ThisAPInterval)
-				maxExistingAnnounceInterval = rr->ThisAPInterval;
-			if (rr->UpdateBlocked) rr->UpdateBlocked = 0;
-		}
-	}
-
-	// Any interface-specific records we're going to send are marked as being sent on all appropriate interfaces (which is just one)
-	// Eligible records that are more than half-way to their announcement time are accelerated
-	for (rr = m->ResourceRecords; rr; rr=rr->next)
-		if ((rr->resrec.InterfaceID && rr->ImmedAnswer) ||
-		    (rr->ThisAPInterval <= maxExistingAnnounceInterval &&
-		     TimeToAnnounceThisRecord(rr, m->timenow + rr->ThisAPInterval/2) &&
-		     ResourceRecordIsValidAnswer(rr)))
-			rr->ImmedAnswer = mDNSInterfaceMark;		// Send on all interfaces
-
-	// When sending SRV records (particularly when announcing a new service) automatically add the related Address record(s)
-	for (rr = m->ResourceRecords; rr; rr=rr->next)
-		if (rr->ImmedAnswer && rr->resrec.rrtype == kDNSType_SRV)
-			for (r2=m->ResourceRecords; r2; r2=r2->next)				// Scan list of resource records
-				if (RRIsAddressType(r2) &&								// For all address records (A/AAAA) ...
-				    ResourceRecordIsValidAnswer(r2) &&					// ... which are valid for answer ...
-				    rr->LastMCTime - r2->LastMCTime >= 0 &&				// ... which we have not sent recently ...
-				    rr->resrec.rdnamehash == r2->resrec.namehash &&		// ... whose name is the name of the SRV target
-				    SameDomainName(&rr->resrec.rdata->u.srv.target, &r2->resrec.name) &&
-				    (rr->ImmedAnswer == mDNSInterfaceMark || rr->ImmedAnswer == r2->resrec.InterfaceID))
-					r2->ImmedAnswer = mDNSInterfaceMark;				// ... then mark this address record for sending too
-
-	// If there's a record which is supposed to be unique that we're going to send, then make sure that we give
-	// the whole RRSet as an atomic unit. That means that if we have any other records with the same name/type/class
-	// then we need to mark them for sending too. Otherwise, if we set the kDNSClass_UniqueRRSet bit on a
-	// record, then other RRSet members that have not been sent recently will get flushed out of client caches.
-	// -- If a record is marked to be sent on a certain interface, make sure the whole set is marked to be sent on that interface
-	// -- If any record is marked to be sent on all interfaces, make sure the whole set is marked to be sent on all interfaces
-	for (rr = m->ResourceRecords; rr; rr=rr->next)
-		if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
-		{
-			if (rr->ImmedAnswer)			// If we're sending this as answer, see that its whole RRSet is similarly marked
-			{
-				for (r2 = m->ResourceRecords; r2; r2=r2->next)
-					if (ResourceRecordIsValidAnswer(r2))
-						if (r2->ImmedAnswer != mDNSInterfaceMark && r2->ImmedAnswer != rr->ImmedAnswer && SameResourceRecordSignature(&r2->resrec, &rr->resrec))
-							r2->ImmedAnswer = rr->ImmedAnswer;
-			}
-			else if (rr->ImmedAdditional)	// If we're sending this as additional, see that its whole RRSet is similarly marked
-			{
-				for (r2 = m->ResourceRecords; r2; r2=r2->next)
-					if (ResourceRecordIsValidAnswer(r2))
-						if (r2->ImmedAdditional != rr->ImmedAdditional && SameResourceRecordSignature(&r2->resrec, &rr->resrec))
-							r2->ImmedAdditional = rr->ImmedAdditional;
-			}
-		}
-
-	// Now set SendRNow state appropriately
-	for (rr = m->ResourceRecords; rr; rr=rr->next)
-	{
-		if (rr->ImmedAnswer == mDNSInterfaceMark)		// Sending this record on all appropriate interfaces
-		{
-			rr->SendRNow = !intf ? mDNSNULL : (rr->resrec.InterfaceID) ? rr->resrec.InterfaceID : intf->InterfaceID;
-			rr->ImmedAdditional = mDNSNULL;				// No need to send as additional if sending as answer
-			rr->LastMCTime      = m->timenow;
-			rr->LastMCInterface = rr->ImmedAnswer;
-			// If we're announcing this record, and it's at least half-way to its ordained time, then consider this announcement done
-			if (TimeToAnnounceThisRecord(rr, m->timenow + rr->ThisAPInterval/2))
-			{
-				rr->AnnounceCount--;
-				rr->ThisAPInterval *= 2;
-				rr->LastAPTime = m->timenow;
-				if (rr->LastAPTime + rr->ThisAPInterval - rr->AnnounceUntil >= 0) rr->AnnounceCount = 0;
-				debugf("Announcing %##s (%s) %d", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype), rr->AnnounceCount);
-			}
-		}
-		else if (rr->ImmedAnswer)						// Else, just respond to a single query on single interface:
-		{
-			rr->SendRNow = rr->ImmedAnswer;				// Just respond on that interface
-			rr->ImmedAdditional = mDNSNULL;				// No need to send as additional too
-			rr->LastMCTime      = m->timenow;
-			rr->LastMCInterface = rr->ImmedAnswer;
-		}
-		SetNextAnnounceProbeTime(m, rr);
-	}
-
-	// ***
-	// *** 2. Loop through interface list, sending records as appropriate
-	// ***
-
-	while (intf)
-	{
-		int numDereg    = 0;
-		int numAnnounce = 0;
-		int numAnswer   = 0;
-		DNSMessage response;
-		mDNSu8 *responseptr = response.data;
-		mDNSu8 *newptr;
-		InitializeDNSMessage(&response.h, zeroID, ResponseFlags);
-	
-		// First Pass. Look for:
-		// 1. Deregistering records that need to send their goodbye packet
-		// 2. Updated records that need to retract their old data
-		// 3. Answers and announcements we need to send
-		// In all cases, if we fail, and we've put at least one answer, we break out of the for loop so we can
-		// send this packet and then try again.
-		// If we have not put even one answer, then we don't bail out. We pretend we succeeded anyway,
-		// because otherwise we'll end up in an infinite loop trying to send a record that will never fit.
-		for (rr = m->ResourceRecords; rr; rr=rr->next)
-			if (rr->SendRNow == intf->InterfaceID)
-			{
-				if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
-				{
-					newptr = PutResourceRecordTTL(&response, responseptr, &response.h.numAnswers, &rr->resrec, 0);
-					if (!newptr && response.h.numAnswers) break;
-					numDereg++;
-					responseptr = newptr;
-				}
-				else if (rr->NewRData)							// If we have new data for this record
-				{
-					RData *OldRData     = rr->resrec.rdata;
-					mDNSu16 oldrdlength = rr->resrec.rdlength;
-					// See if we should send a courtesy "goodbye" the old data before we replace it.
-					// We compare with "InitialAnnounceCount-1" instead of "InitialAnnounceCount" because by the time
-					// we get to this place in this routine we've we've already decremented rr->AnnounceCount
-					if (ResourceRecordIsValidAnswer(rr) && rr->AnnounceCount < InitialAnnounceCount-1)
-					{
-						newptr = PutResourceRecordTTL(&response, responseptr, &response.h.numAnswers, &rr->resrec, 0);
-						if (!newptr && response.h.numAnswers) break;
-						numDereg++;
-						responseptr = newptr;
-					}
-					// Now try to see if we can fit the update in the same packet (not fatal if we can't)
-					SetNewRData(&rr->resrec, rr->NewRData, rr->newrdlength);
-					if ((rr->resrec.RecordType & kDNSRecordTypeUniqueMask) && HaveSentEntireRRSet(m, rr, intf->InterfaceID))
-						rr->resrec.rrclass |= kDNSClass_UniqueRRSet;		// Temporarily set the cache flush bit so PutResourceRecord will set it
-					newptr = PutResourceRecord(&response, responseptr, &response.h.numAnswers, &rr->resrec);
-					rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;			// Make sure to clear cache flush bit back to normal state
-					if (newptr) responseptr = newptr;
-					SetNewRData(&rr->resrec, OldRData, oldrdlength);
-				}
-				else
-				{
-					if ((rr->resrec.RecordType & kDNSRecordTypeUniqueMask) && HaveSentEntireRRSet(m, rr, intf->InterfaceID))
-						rr->resrec.rrclass |= kDNSClass_UniqueRRSet;		// Temporarily set the cache flush bit so PutResourceRecord will set it
-					newptr = PutResourceRecordTTL(&response, responseptr, &response.h.numAnswers, &rr->resrec, m->SleepState ? 0 : rr->resrec.rroriginalttl);
-					rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;			// Make sure to clear cache flush bit back to normal state
-					if (!newptr && response.h.numAnswers) break;
-					if (rr->LastAPTime == m->timenow) numAnnounce++; else numAnswer++;
-					responseptr = newptr;
-				}
-				// If sending on all interfaces, go to next interface; else we're finished now
-				if (rr->ImmedAnswer == mDNSInterfaceMark && rr->resrec.InterfaceID == mDNSInterface_Any)
-					rr->SendRNow = GetNextActiveInterfaceID(intf);
-				else
-					rr->SendRNow = mDNSNULL;
-			}
-	
-		// Second Pass. Add additional records, if there's space.
-		newptr = responseptr;
-		for (rr = m->ResourceRecords; rr; rr=rr->next)
-			if (rr->ImmedAdditional == intf->InterfaceID)
-			{
-				// Since additionals are optional, we clear ImmedAdditional anyway, even if we subsequently find it doesn't fit in the packet
-				rr->ImmedAdditional = mDNSNULL;
-				if (newptr && ResourceRecordIsValidAnswer(rr))
-				{
-					if (rr->resrec.RecordType & kDNSRecordTypeUniqueMask)
-					{
-						// Try to find another member of this set that we're still planning to send on this interface
-						const AuthRecord *a;
-						for (a = m->ResourceRecords; a; a=a->next)
-							if (a->ImmedAdditional == intf->InterfaceID && SameResourceRecordSignature(&a->resrec, &rr->resrec)) break;
-						if (a == mDNSNULL)							// If no more members of this set found
-							rr->resrec.rrclass |= kDNSClass_UniqueRRSet;	// Temporarily set the cache flush bit so PutResourceRecord will set it
-					}
-					newptr = PutResourceRecord(&response, newptr, &response.h.numAdditionals, &rr->resrec);
-					if (newptr) responseptr = newptr;
-					rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet;			// Make sure to clear cache flush bit back to normal state
-				}
-			}
-	
-		if (response.h.numAnswers > 0)	// We *never* send a packet with only additionals in it
-		{
-			debugf("SendResponses: Sending %d Deregistration%s, %d Announcement%s, %d Answer%s, %d Additional%s on %p",
-			       numDereg,                  numDereg                  == 1 ? "" : "s",
-			       numAnnounce,               numAnnounce               == 1 ? "" : "s",
-			       numAnswer,                 numAnswer                 == 1 ? "" : "s",
-			       response.h.numAdditionals, response.h.numAdditionals == 1 ? "" : "s", intf->InterfaceID);
-			mDNSSendDNSMessage(m, &response, responseptr, intf->InterfaceID, MulticastDNSPort, &AllDNSLinkGroup_v4, MulticastDNSPort);
-			mDNSSendDNSMessage(m, &response, responseptr, intf->InterfaceID, MulticastDNSPort, &AllDNSLinkGroup_v6, MulticastDNSPort);
-			if (!m->SuppressSending) m->SuppressSending = (m->timenow + mDNSPlatformOneSecond/10) | 1;	// OR with one to ensure non-zero
-			if (++pktcount >= 1000)
-			{ LogMsg("SendResponses exceeded loop limit %d: giving up", pktcount); break; }
-			// There might be more things to send on this interface, so go around one more time and try again.
-		}
-		else	// Nothing more to send on this interface; go to next
-		{
-			const NetworkInterfaceInfo *next = GetFirstActiveInterface(intf->next);
-#if MDNS_DEBUGMSGS && 0
-			const char *const msg = next ? "SendResponses: Nothing more on %p; moving to %p" : "SendResponses: Nothing more on %p";
-			debugf(msg, intf, next);
-#endif
-			intf = next;
-		}
-	}
-
-	// ***
-	// *** 3. Cleanup: Now that everything is sent, call client callback functions, and reset state variables
-	// ***
-
-	if (m->CurrentRecord) LogMsg("SendResponses: ERROR m->CurrentRecord already set");
-	m->CurrentRecord = m->ResourceRecords;
-	while (m->CurrentRecord)
-	{
-		rr = m->CurrentRecord;
-		m->CurrentRecord = rr->next;
-
-		if (rr->NewRData)
-		{
-			RData *OldRData = rr->resrec.rdata;
-			SetNewRData(&rr->resrec, rr->NewRData, rr->newrdlength);	// Update our rdata
-			rr->NewRData = mDNSNULL;									// Clear the NewRData pointer ...
-			if (rr->UpdateCallback)
-				rr->UpdateCallback(m, rr, OldRData);					// ... and let the client know
-		}
-
-		if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
-			CompleteDeregistration(m, rr);
-		else
-		{
-			rr->ImmedAnswer = mDNSNULL;
-			rr->v4Requester = zeroIPAddr;
-			rr->v6Requester = zerov6Addr;
-		}
-	}
-	verbosedebugf("SendResponses: Next in %d ticks", m->NextScheduledResponse - m->timenow);
-}
-
-// Calling CheckCacheExpiration() is an expensive operation because it has to look at the entire cache,
-// so we want to be lazy about how frequently we do it.
-// 1. If a cache record is currently referenced by *no* active questions,
-//    then we don't mind expiring it up to a minute late (who will know?)
-// 2. Else, if a cache record is due for some of its final expiration queries,
-//    we'll allow them to be late by up to 2% of the TTL
-// 3. Else, if a cache record has completed all its final expiration queries without success,
-//    and is expiring, and had an original TTL more than ten seconds, we'll allow it to be one second late
-// 4. Else, it is expiring and had an original TTL of ten seconds or less (includes explicit goodbye packets),
-//    so allow at most 1/10 second lateness
-#define CacheCheckGracePeriod(RR) (                                                   \
-	((RR)->CRActiveQuestion == mDNSNULL            ) ? (60 * mDNSPlatformOneSecond) : \
-	((RR)->UnansweredQueries < MaxUnansweredQueries) ? (TicksTTL(rr)/50)            : \
-	((RR)->resrec.rroriginalttl > 10               ) ? (mDNSPlatformOneSecond)      : (mDNSPlatformOneSecond/10))
-
-// Note: MUST call SetNextCacheCheckTime any time we change:
-// rr->TimeRcvd
-// rr->resrec.rroriginalttl
-// rr->UnansweredQueries
-// rr->CRActiveQuestion
-mDNSlocal void SetNextCacheCheckTime(mDNS *const m, CacheRecord *const rr)
-{
-	rr->NextRequiredQuery = RRExpireTime(rr);
-
-	// If we have an active question, then see if we want to schedule a refresher query for this record.
-	// Usually we expect to do four queries, at 80-82%, 85-87%, 90-92% and then 95-97% of the TTL.
-	if (rr->CRActiveQuestion && rr->UnansweredQueries < MaxUnansweredQueries)
-	{
-		rr->NextRequiredQuery -= TicksTTL(rr)/20 * (MaxUnansweredQueries - rr->UnansweredQueries);
-		rr->NextRequiredQuery += mDNSRandom((mDNSu32)TicksTTL(rr)/50);
-		verbosedebugf("SetNextCacheCheckTime: %##s (%s) NextRequiredQuery in %ld sec",
-			      rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype), (rr->NextRequiredQuery - m->timenow) / mDNSPlatformOneSecond);
-	}
-
-	if (m->NextCacheCheck - (rr->NextRequiredQuery + CacheCheckGracePeriod(rr)) > 0)
-		m->NextCacheCheck = (rr->NextRequiredQuery + CacheCheckGracePeriod(rr));
-}
-
-#define kDefaultReconfirmTimeForNoAnswer        ((mDNSu32)mDNSPlatformOneSecond * 45)
-#define kDefaultReconfirmTimeForCableDisconnect ((mDNSu32)mDNSPlatformOneSecond *  5)
-#define kMinimumReconfirmTime                   ((mDNSu32)mDNSPlatformOneSecond *  5)
-
-mDNSlocal mStatus mDNS_Reconfirm_internal(mDNS *const m, CacheRecord *const rr, mDNSu32 interval)
-{
-	if (interval < kMinimumReconfirmTime)
-		interval = kMinimumReconfirmTime;
-	if (interval > 0x10000000)	// Make sure interval doesn't overflow when we multiply by four below
-		interval = 0x10000000;
-
-	// If the expected expiration time for this record is more than interval+33%, then accelerate its expiration
-	if (RRExpireTime(rr) - m->timenow > (mDNSs32)((interval * 4) / 3))
-	{
-		// Add a 33% random amount to the interval, to avoid synchronization between multiple hosts
-		interval += mDNSRandom(interval/3);
-		rr->TimeRcvd          = m->timenow - (mDNSs32)interval * 3;
-		rr->resrec.rroriginalttl     = interval * 4 / mDNSPlatformOneSecond;
-		SetNextCacheCheckTime(m, rr);
-	}
-	debugf("mDNS_Reconfirm_internal:%5ld ticks to go for %s", RRExpireTime(rr) - m->timenow, GetRRDisplayString(m, rr));
-	return(mStatus_NoError);
-}
-
-#define MaxQuestionInterval         (3600 * mDNSPlatformOneSecond)
-
-// BuildQuestion puts a question into a DNS Query packet and if successful, updates the value of queryptr.
-// It also appends to the list of known answer records that need to be included,
-// and updates the forcast for the size of the known answer section.
-mDNSlocal mDNSBool BuildQuestion(mDNS *const m, DNSMessage *query, mDNSu8 **queryptr, DNSQuestion *q,
-				 CacheRecord ***kalistptrptr, mDNSu32 *answerforecast)
-{
-	mDNSBool ucast = q->LargeAnswers || q->ThisQInterval <= InitialQuestionInterval*2;
-	mDNSu16 ucbit = (mDNSu16)(ucast ? kDNSQClass_UnicastResponse : 0);
-	const mDNSu8 *const limit = query->data + NormalMaxDNSMessageData;
-	mDNSu8 *newptr = putQuestion(query, *queryptr, limit, &q->qname, q->qtype, (mDNSu16)(q->qclass | ucbit));
-	if (!newptr)
-	{
-		debugf("BuildQuestion: No more space in this packet for question %##s", q->qname.c);
-		return(mDNSfalse);
-	}
-	else if (newptr + *answerforecast >= limit)
-	{
-		verbosedebugf("BuildQuestion: Retracting question %##s new forecast total %d", q->qname.c, newptr + *answerforecast - query->data);
-		query->h.numQuestions--;
-		return(mDNSfalse);
-	}
-	else
-	{
-		mDNSu32 forecast = *answerforecast;
-		CacheRecord *rr;
-		CacheRecord **ka = *kalistptrptr;	// Make a working copy of the pointer we're going to update
-
-		for (rr=m->rrcache_hash[HashSlot(&q->qname)]; rr; rr=rr->next)		// If we have a resource record in our cache,
-			if (rr->resrec.InterfaceID == q->SendQNow &&					// received on this interface
-			    rr->NextInKAList == mDNSNULL && ka != &rr->NextInKAList &&	// which is not already in the known answer list
-			    rr->resrec.rdlength <= SmallRecordLimit &&					// which is small enough to sensibly fit in the packet
-			    ResourceRecordAnswersQuestion(&rr->resrec, q) &&			// which answers our question
-			    rr->TimeRcvd + TicksTTL(rr)/2 - m->timenow >= 0 &&			// and it is less than half-way to expiry
-			    rr->NextRequiredQuery - (m->timenow + q->ThisQInterval) > 0)// and we'll ask at least once again before NextRequiredQuery
-			{
-				*ka = rr;	// Link this record into our known answer chain
-				ka = &rr->NextInKAList;
-				// We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n)
-				forecast += 12 + rr->resrec.rdestimate;
-				// If we're trying to put more than one question in this packet, and it doesn't fit
-				// then undo that last question and try again next time
-				if (query->h.numQuestions > 1 && newptr + forecast >= limit)
-				{
-					debugf("BuildQuestion: Retracting question %##s (%s) new forecast total %d",
-					       q->qname.c, DNSTypeName(q->qtype), newptr + forecast - query->data);
-					query->h.numQuestions--;
-					ka = *kalistptrptr;		// Go back to where we started and retract these answer records
-					while (*ka) { CacheRecord *rr = *ka; *ka = mDNSNULL; ka = &rr->NextInKAList; }
-					return(mDNSfalse);		// Return false, so we'll try again in the next packet
-				}
-			}
-
-		// Traffic reduction:
-		// If we already have at least one unique answer in the cache,
-		// OR we have so many shared answers that the KA list is too big to fit in one packet
-		// The we suppress queries number 3 and 5:
-		// Query 1 (immediately;      ThisQInterval =  1 sec; request unicast replies)
-		// Query 2 (after  1 second;  ThisQInterval =  2 sec; send normally)
-		// Query 3 (after  2 seconds; ThisQInterval =  4 sec; may suppress)
-		// Query 4 (after  4 seconds; ThisQInterval =  8 sec; send normally)
-		// Query 5 (after  8 seconds; ThisQInterval = 16 sec; may suppress)
-		// Query 6 (after 16 seconds; ThisQInterval = 32 sec; send normally)
-		if (q->UniqueAnswers || newptr + forecast >= limit)
-			if (q->ThisQInterval == InitialQuestionInterval * 8 || q->ThisQInterval == InitialQuestionInterval * 32)
-			{
-				query->h.numQuestions--;
-				ka = *kalistptrptr;		// Go back to where we started and retract these answer records
-				while (*ka) { CacheRecord *rr = *ka; *ka = mDNSNULL; ka = &rr->NextInKAList; }
-				return(mDNStrue);		// Return true: pretend we succeeded, even though we actually suppressed this question
-			}
-
-		// Success! Update our state pointers, increment UnansweredQueries as appropriate, and return
-		*queryptr        = newptr;				// Update the packet pointer
-		*answerforecast  = forecast;			// Update the forecast
-		*kalistptrptr    = ka;					// Update the known answer list pointer
-		if (ucast) m->ExpectUnicastResponse = m->timenow;
-
-		for (rr=m->rrcache_hash[HashSlot(&q->qname)]; rr; rr=rr->next)		// For every resource record in our cache,
-			if (rr->resrec.InterfaceID == q->SendQNow &&					// received on this interface
-			    rr->NextInKAList == mDNSNULL && ka != &rr->NextInKAList &&	// which is not in the known answer list
-			    ResourceRecordAnswersQuestion(&rr->resrec, q))				// which answers our question
-			{
-				rr->UnansweredQueries++;								// indicate that we're expecting a response
-				rr->LastUnansweredTime = m->timenow;
-				SetNextCacheCheckTime(m, rr);
-			}
-
-		return(mDNStrue);
-	}
-}
-
-mDNSlocal void ReconfirmAntecedents(mDNS *const m, DNSQuestion *q)
-{
-	mDNSu32 slot;
-	CacheRecord *rr;
-	domainname *target = NULL;
-	for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
-		for (rr = m->rrcache_hash[slot]; rr; rr=rr->next)
-		{
-			mDNSBool b = SameDomainName(target, &q->qname);
-			target = GetRRDomainNameTarget(&rr->resrec);
-			if ((target) && rr->resrec.rdnamehash == q->qnamehash && b)
-			{
-				mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForNoAnswer);
-			}
-		}
-}
-
-// Only DupSuppressInfos newer than the specified 'time' are allowed to remain active
-mDNSlocal void ExpireDupSuppressInfo(DupSuppressInfo ds[DupSuppressInfoSize], mDNSs32 time)
-{
-	int i;
-	for (i=0; i<DupSuppressInfoSize; i++) if (ds[i].Time - time < 0) ds[i].InterfaceID = mDNSNULL;
-}
-
-mDNSlocal void ExpireDupSuppressInfoOnInterface(DupSuppressInfo ds[DupSuppressInfoSize], mDNSs32 time, mDNSInterfaceID InterfaceID)
-{
-	int i;
-	for (i=0; i<DupSuppressInfoSize; i++) if (ds[i].InterfaceID == InterfaceID && ds[i].Time - time < 0) ds[i].InterfaceID = mDNSNULL;
-}
-
-mDNSlocal mDNSBool SuppressOnThisInterface(const DupSuppressInfo ds[DupSuppressInfoSize], const NetworkInterfaceInfo * const intf)
-{
-	int i;
-	mDNSBool v4 = !intf->IPv4Available;		// If this interface doesn't do v4, we don't need to find a v4 duplicate of this query
-	mDNSBool v6 = !intf->IPv6Available;		// If this interface doesn't do v6, we don't need to find a v6 duplicate of this query
-	for (i=0; i<DupSuppressInfoSize; i++)
-		if (ds[i].InterfaceID == intf->InterfaceID)
-		{
-			if      (ds[i].Type == mDNSAddrType_IPv4) v4 = mDNStrue;
-			else if (ds[i].Type == mDNSAddrType_IPv6) v6 = mDNStrue;
-			if (v4 && v6) return(mDNStrue);
-		}
-	return(mDNSfalse);
-}
-
-mDNSlocal int RecordDupSuppressInfo(DupSuppressInfo ds[DupSuppressInfoSize], mDNSs32 Time, mDNSInterfaceID InterfaceID, mDNSs32 Type)
-{
-	int i, j;
-
-	// See if we have this one in our list somewhere already
-	for (i=0; i<DupSuppressInfoSize; i++) if (ds[i].InterfaceID == InterfaceID && ds[i].Type == Type) break;
-
-	// If not, find a slot we can re-use
-	if (i >= DupSuppressInfoSize)
-	{
-		i = 0;
-		for (j=1; j<DupSuppressInfoSize && ds[i].InterfaceID; j++)
-			if (!ds[j].InterfaceID || ds[j].Time - ds[i].Time < 0)
-				i = j;
-	}
-	
-	// Record the info about this query we saw
-	ds[i].Time        = Time;
-	ds[i].InterfaceID = InterfaceID;
-	ds[i].Type        = Type;
-	
-	return(i);
-}
-
-mDNSlocal mDNSBool AccelerateThisQuery(mDNS *const m, DNSQuestion *q)
-{
-	// If more than 90% of the way to the query time, we should unconditionally accelerate it
-	if (TimeToSendThisQuestion(q, m->timenow + q->ThisQInterval/10))
-		return(mDNStrue);
-
-	// If half-way to next scheduled query time, only accelerate if it will add less than 512 bytes to the packet
-	if (TimeToSendThisQuestion(q, m->timenow + q->ThisQInterval/2))
-	{
-		// We forecast: qname (n) type (2) class (2)
-		mDNSu32 forecast = (mDNSu32)DomainNameLength(&q->qname) + 4;
-		CacheRecord *rr;
-		for (rr=m->rrcache_hash[HashSlot(&q->qname)]; rr; rr=rr->next)		// If we have a resource record in our cache,
-			if (rr->resrec.rdlength <= SmallRecordLimit &&					// which is small enough to sensibly fit in the packet
-			    ResourceRecordAnswersQuestion(&rr->resrec, q) &&			// which answers our question
-			    rr->TimeRcvd + TicksTTL(rr)/2 - m->timenow >= 0 &&			// and it is less than half-way to expiry
-			    rr->NextRequiredQuery - (m->timenow + q->ThisQInterval) > 0)// and we'll ask at least once again before NextRequiredQuery
-			{
-				// We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n)
-				forecast += 12 + rr->resrec.rdestimate;
-				if (forecast >= 512) return(mDNSfalse);	// If this would add 512 bytes or more to the packet, don't accelerate
-			}
-		return(mDNStrue);
-	}
-
-	return(mDNSfalse);
-}
-
-// How Standard Queries are generated:
-// 1. The Question Section contains the question
-// 2. The Additional Section contains answers we already know, to suppress duplicate responses
-
-// How Probe Queries are generated:
-// 1. The Question Section contains queries for the name we intend to use, with QType=ANY because
-// if some other host is already using *any* records with this name, we want to know about it.
-// 2. The Authority Section contains the proposed values we intend to use for one or more
-// of our records with that name (analogous to the Update section of DNS Update packets)
-// because if some other host is probing at the same time, we each want to know what the other is
-// planning, in order to apply the tie-breaking rule to see who gets to use the name and who doesn't.
-
-mDNSlocal void SendQueries(mDNS *const m)
-{
-	int pktcount = 0;
-	DNSQuestion *q;
-	// For explanation of maxExistingQuestionInterval logic, see comments for maxExistingAnnounceInterval
-	mDNSs32 maxExistingQuestionInterval = 0;
-	const NetworkInterfaceInfo *intf = GetFirstActiveInterface(m->HostInterfaces);
-	CacheRecord *KnownAnswerList = mDNSNULL;
-
-	// 1. If time for a query, work out what we need to do
-	if (m->timenow - m->NextScheduledQuery >= 0)
-	{
-		mDNSu32 slot;
-		CacheRecord *rr;
-		m->NextScheduledQuery = m->timenow + kNextScheduledTime;
-
-		// We're expecting to send a query anyway, so see if any expiring cache records are close enough
-		// to their NextRequiredQuery to be worth batching them together with this one
-		for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
-			for (rr = m->rrcache_hash[slot]; rr; rr=rr->next)
-				if (rr->CRActiveQuestion && rr->UnansweredQueries < MaxUnansweredQueries)
-					if (m->timenow + TicksTTL(rr)/50 - rr->NextRequiredQuery >= 0)
-					{
-						q = rr->CRActiveQuestion;
-						ExpireDupSuppressInfoOnInterface(q->DupSuppress, m->timenow - TicksTTL(rr)/20, rr->resrec.InterfaceID);
-						if      (q->SendQNow == mDNSNULL)               q->SendQNow = rr->resrec.InterfaceID;
-						else if (q->SendQNow != rr->resrec.InterfaceID) q->SendQNow = mDNSInterfaceMark;
-					}
-
-		// Scan our list of questions to see which ones we're definitely going to send
-		for (q = m->Questions; q; q=q->next)
-			if (TimeToSendThisQuestion(q, m->timenow))
-			{
-				q->SendQNow = mDNSInterfaceMark;		// Mark this question for sending on all interfaces
-				if (maxExistingQuestionInterval < q->ThisQInterval)
-					maxExistingQuestionInterval = q->ThisQInterval;
-			}
-	
-		// Scan our list of questions
-		// (a) to see if there are any more that are worth accelerating, and
-		// (b) to update the state variables for all the questions we're going to send
-		for (q = m->Questions; q; q=q->next)
-		{
-			if (q->SendQNow || (ActiveQuestion(q) && q->ThisQInterval <= maxExistingQuestionInterval && AccelerateThisQuery(m,q)))
-			{
-				// If at least halfway to next query time, advance to next interval
-				// If less than halfway to next query time, treat this as logically a repeat of the last transmission, without advancing the interval
-				if (m->timenow - (q->LastQTime + q->ThisQInterval/2) >= 0)
-				{
-					q->SendQNow = mDNSInterfaceMark;	// Mark this question for sending on all interfaces
-					q->ThisQInterval *= 2;
-					if (q->ThisQInterval > MaxQuestionInterval)
-						q->ThisQInterval = MaxQuestionInterval;
-					else if (q->CurrentAnswers == 0 && q->ThisQInterval == InitialQuestionInterval * 8)
-					{
-						debugf("SendQueries: Zero current answers for %##s (%s); will reconfirm antecedents", q->qname.c, DNSTypeName(q->qtype));
-						ReconfirmAntecedents(m, q);		// If sending third query, and no answers yet, time to begin doubting the source
-					}
-				}
-
-				// Mark for sending. (If no active interfaces, then don't even try.)
-				q->SendOnAll = (q->SendQNow == mDNSInterfaceMark);
-				if (q->SendOnAll)
-				{
-					q->SendQNow  = !intf ? mDNSNULL : (q->InterfaceID) ? q->InterfaceID : intf->InterfaceID;
-					q->LastQTime = m->timenow;
-				}
-
-				// If we recorded a duplicate suppression for this question less than half an interval ago,
-				// then we consider it recent enough that we don't need to do an identical query ourselves.
-				ExpireDupSuppressInfo(q->DupSuppress, m->timenow - q->ThisQInterval/2);
-
-				q->LastQTxTime   = m->timenow;
-				q->RecentAnswers = 0;
-			}
-			// For all questions (not just the ones we're sending) check what the next scheduled event will be
-			SetNextQueryTime(m,q);
-		}
-	}
-
-	// 2. Scan our authoritative RR list to see what probes we might need to send
-	if (m->timenow - m->NextScheduledProbe >= 0)
-	{
-		m->NextScheduledProbe = m->timenow + kNextScheduledTime;
-
-		if (m->CurrentRecord) LogMsg("SendQueries:   ERROR m->CurrentRecord already set");
-		m->CurrentRecord = m->ResourceRecords;
-		while (m->CurrentRecord)
-		{
-			AuthRecord *rr = m->CurrentRecord;
-			m->CurrentRecord = rr->next;
-			if (rr->resrec.RecordType == kDNSRecordTypeUnique)			// For all records that are still probing...
-			{
-				// 1. If it's not reached its probe time, just make sure we update m->NextScheduledProbe correctly
-				if (m->timenow - (rr->LastAPTime + rr->ThisAPInterval) < 0)
-				{
-					SetNextAnnounceProbeTime(m, rr);
-				}
-				// 2. else, if it has reached its probe time, mark it for sending and then update m->NextScheduledProbe correctly
-				else if (rr->ProbeCount)
-				{
-					// Mark for sending. (If no active interfaces, then don't even try.)
-					rr->SendRNow   = !intf ? mDNSNULL : (rr->resrec.InterfaceID) ? rr->resrec.InterfaceID : intf->InterfaceID;
-					rr->LastAPTime = m->timenow;
-					rr->ProbeCount--;
-					SetNextAnnounceProbeTime(m, rr);
-				}
-				// else, if it has now finished probing, move it to state Verified, and update m->NextScheduledResponse so it will be announced
-				else
-				{
-					AuthRecord *r2;
-					rr->resrec.RecordType     = kDNSRecordTypeVerified;
-					rr->ThisAPInterval = DefaultAnnounceIntervalForTypeUnique;
-					rr->LastAPTime     = m->timenow - DefaultAnnounceIntervalForTypeUnique;
-					SetNextAnnounceProbeTime(m, rr);
-					// If we have any records on our duplicate list that match this one, they have now also completed probing
-					for (r2 = m->DuplicateRecords; r2; r2=r2->next)
-						if (r2->resrec.RecordType == kDNSRecordTypeUnique && RecordIsLocalDuplicate(r2, rr))
-							r2->ProbeCount = 0;
-					CompleteProbing(m, rr);
-				}
-			}
-		}
-		m->CurrentRecord = m->DuplicateRecords;
-		while (m->CurrentRecord)
-		{
-			AuthRecord *rr = m->CurrentRecord;
-			m->CurrentRecord = rr->next;
-			if (rr->resrec.RecordType == kDNSRecordTypeUnique && rr->ProbeCount == 0)
-				CompleteProbing(m, rr);
-		}
-	}
-
-	// 3. Now we know which queries and probes we're sending, go through our interface list sending the appropriate queries on each interface
-	while (intf)
-	{
-		AuthRecord *rr;
-		DNSMessage query;
-		mDNSu8 *queryptr = query.data;
-		InitializeDNSMessage(&query.h, zeroID, QueryFlags);
-		if (KnownAnswerList) verbosedebugf("SendQueries:   KnownAnswerList set... Will continue from previous packet");
-		if (!KnownAnswerList)
-		{
-			// Start a new known-answer list
-			CacheRecord **kalistptr = &KnownAnswerList;
-			mDNSu32 answerforecast = 0;
-			
-			// Put query questions in this packet
-			for (q = m->Questions; q; q=q->next)
-				if (q->SendQNow == intf->InterfaceID)
-				{
-					debugf("SendQueries: %s question for %##s (%s) at %lu forecast total %lu",
-					       SuppressOnThisInterface(q->DupSuppress, intf) ? "Suppressing" : "Putting    ",
-					       q->qname.c, DNSTypeName(q->qtype), queryptr - query.data, queryptr + answerforecast - query.data);
-					// If we're suppressing this question, or we successfully put it, update its SendQNow state
-					if (SuppressOnThisInterface(q->DupSuppress, intf) ||
-					    BuildQuestion(m, &query, &queryptr, q, &kalistptr, &answerforecast))
-						q->SendQNow = (q->InterfaceID || !q->SendOnAll) ? mDNSNULL : GetNextActiveInterfaceID(intf);
-				}
-
-			// Put probe questions in this packet
-			for (rr = m->ResourceRecords; rr; rr=rr->next)
-				if (rr->SendRNow == intf->InterfaceID)
-				{
-					mDNSBool ucast = rr->ProbeCount >= DefaultProbeCountForTypeUnique-1;
-					mDNSu16 ucbit = (mDNSu16)(ucast ? kDNSQClass_UnicastResponse : 0);
-					const mDNSu8 *const limit = query.data + ((query.h.numQuestions) ? NormalMaxDNSMessageData : AbsoluteMaxDNSMessageData);
-					mDNSu8 *newptr = putQuestion(&query, queryptr, limit, &rr->resrec.name, kDNSQType_ANY, (mDNSu16)(rr->resrec.rrclass | ucbit));
-					// We forecast: compressed name (2) type (2) class (2) TTL (4) rdlength (2) rdata (n)
-					mDNSu32 forecast = answerforecast + 12 + rr->resrec.rdestimate;
-					if (newptr && newptr + forecast < limit)
-					{
-						queryptr       = newptr;
-						answerforecast = forecast;
-						rr->SendRNow = (rr->resrec.InterfaceID) ? mDNSNULL : GetNextActiveInterfaceID(intf);
-						rr->IncludeInProbe = mDNStrue;
-						verbosedebugf("SendQueries:   Put Question %##s (%s) probecount %d", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype), rr->ProbeCount);
-					}
-					else
-					{
-						verbosedebugf("SendQueries:   Retracting Question %##s (%s)", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-						query.h.numQuestions--;
-					}
-				}
-		}
-
-		// Put our known answer list (either new one from this question or questions, or remainder of old one from last time)
-		while (KnownAnswerList)
-		{
-			CacheRecord *rr = KnownAnswerList;
-			mDNSu32 SecsSinceRcvd = ((mDNSu32)(m->timenow - rr->TimeRcvd)) / mDNSPlatformOneSecond;
-			mDNSu8 *newptr = PutResourceRecordTTL(&query, queryptr, &query.h.numAnswers, &rr->resrec, rr->resrec.rroriginalttl - SecsSinceRcvd);
-			if (newptr)
-			{
-				verbosedebugf("SendQueries:   Put %##s (%s) at %lu - %lu", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype), queryptr - query.data, newptr - query.data);
-				queryptr = newptr;
-				KnownAnswerList = rr->NextInKAList;
-				rr->NextInKAList = mDNSNULL;
-			}
-			else
-			{
-				// If we ran out of space and we have more than one question in the packet, that's an error --
-				// we shouldn't have put more than one question if there was a risk of us running out of space.
-				if (query.h.numQuestions > 1)
-					LogMsg("SendQueries:   Put %d answers; No more space for known answers", query.h.numAnswers);
-				query.h.flags.b[0] |= kDNSFlag0_TC;
-				break;
-			}
-		}
-
-		for (rr = m->ResourceRecords; rr; rr=rr->next)
-			if (rr->IncludeInProbe)
-			{
-				mDNSu8 *newptr = PutResourceRecord(&query, queryptr, &query.h.numAuthorities, &rr->resrec);
-				rr->IncludeInProbe = mDNSfalse;
-				if (newptr) queryptr = newptr;
-				else LogMsg("SendQueries:   How did we fail to have space for the Update record %##s (%s)?",
-					    rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-			}
-		
-		if (queryptr > query.data)
-		{
-			if ((query.h.flags.b[0] & kDNSFlag0_TC) && query.h.numQuestions > 1)
-				LogMsg("SendQueries: Should not have more than one question (%d) in a truncated packet\n", query.h.numQuestions);
-			debugf("SendQueries:   Sending %d Question%s %d Answer%s %d Update%s on %p",
-			       query.h.numQuestions,   query.h.numQuestions   == 1 ? "" : "s",
-			       query.h.numAnswers,     query.h.numAnswers     == 1 ? "" : "s",
-			       query.h.numAuthorities, query.h.numAuthorities == 1 ? "" : "s", intf->InterfaceID);
-			mDNSSendDNSMessage(m, &query, queryptr, intf->InterfaceID, MulticastDNSPort, &AllDNSLinkGroup_v4, MulticastDNSPort);
-			mDNSSendDNSMessage(m, &query, queryptr, intf->InterfaceID, MulticastDNSPort, &AllDNSLinkGroup_v6, MulticastDNSPort);
-			if (!m->SuppressSending) m->SuppressSending = (m->timenow + mDNSPlatformOneSecond/10) | 1;	// OR with one to ensure non-zero
-			if (++pktcount >= 1000)
-			{ LogMsg("SendQueries exceeded loop limit %d: giving up", pktcount); break; }
-			// There might be more records left in the known answer list, or more questions to send
-			// on this interface, so go around one more time and try again.
-		}
-		else	// Nothing more to send on this interface; go to next
-		{
-			const NetworkInterfaceInfo *next = GetFirstActiveInterface(intf->next);
-#if MDNS_DEBUGMSGS && 0
-			const char *const msg = next ? "SendQueries:   Nothing more on %p; moving to %p" : "SendQueries:   Nothing more on %p";
-			debugf(msg, intf, next);
-#endif
-			intf = next;
-		}
-	}
-}
-
-// ***************************************************************************
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - RR List Management & Task Management
-#endif
-
-// NOTE: AnswerQuestionWithResourceRecord can call a user callback, which may change the record list and/or question list.
-// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
-mDNSlocal void AnswerQuestionWithResourceRecord(mDNS *const m, DNSQuestion *q, CacheRecord *rr, mDNSBool AddRecord)
-{
-	verbosedebugf("AnswerQuestionWithResourceRecord:%4lu %s TTL%6lu %##s (%s)",
-		      q->CurrentAnswers, AddRecord ? "Add" : "Rmv", rr->resrec.rroriginalttl, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-
-	rr->LastUsed = m->timenow;
-	rr->UseCount++;
-	if (ActiveQuestion(q) && rr->CRActiveQuestion != q)
-	{
-		if (!rr->CRActiveQuestion) m->rrcache_active++;	// If not previously active, increment rrcache_active count
-		rr->CRActiveQuestion = q;						// We know q is non-null
-		SetNextCacheCheckTime(m, rr);
-	}
-
-	// CAUTION: MUST NOT do anything more with q after calling q->Callback(), because the client's callback function
-	// is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc.
-	// Right now the only routines that call AnswerQuestionWithResourceRecord() are CacheRecordAdd(), CacheRecordRmv()
-	// and AnswerNewQuestion(), and all of them use the "m->CurrentQuestion" mechanism to protect against questions
-	// being deleted out from under them.
-	m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback
-	if (q->QuestionCallback)
-		q->QuestionCallback(m, q, &rr->resrec, AddRecord);
-	m->mDNS_reentrancy--; // Decrement to block mDNS API calls again
-}
-
-// CacheRecordAdd is only called from mDNSCoreReceiveResponse, *never* directly as a result of a client API call.
-// If new questions are created as a result of invoking client callbacks, they will be added to
-// the end of the question list, and m->NewQuestions will be set to indicate the first new question.
-// rr is a new CacheRecord just received into our cache
-// (kDNSRecordTypePacketAns/PacketAnsUnique/PacketAdd/PacketAddUnique).
-// NOTE: CacheRecordAdd calls AnswerQuestionWithResourceRecord which can call a user callback,
-// which may change the record list and/or question list.
-// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
-mDNSlocal void CacheRecordAdd(mDNS *const m, CacheRecord *rr)
-{
-	if (m->CurrentQuestion) LogMsg("CacheRecordAdd ERROR m->CurrentQuestion already set");
-	m->CurrentQuestion = m->Questions;
-	while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
-	{
-		DNSQuestion *q = m->CurrentQuestion;
-		m->CurrentQuestion = q->next;
-		if (ResourceRecordAnswersQuestion(&rr->resrec, q))
-		{
-			// If this question is one that's actively sending queries, and it's received ten answers within one second of sending the last
-			// query packet, then that indicates some radical network topology change, so reset its exponential backoff back to the start.
-			// We must be at least at the eight-second interval to do this. If we're at the four-second interval, or less,
-			// there's not much benefit accelerating because we will anyway send another query within a few seconds.
-			// The first reset query is sent out randomized over the next four seconds to reduce possible synchronization between machines.
-			if (ActiveQuestion(q) && ++q->RecentAnswers >= 10 &&
-			    q->ThisQInterval > InitialQuestionInterval*16 && m->timenow - q->LastQTxTime < mDNSPlatformOneSecond)
-			{
-				LogMsg("CacheRecordAdd: %##s (%s) got immediate answer burst; restarting exponential backoff sequence",
-				       q->qname.c, DNSTypeName(q->qtype));
-				q->LastQTime     = m->timenow - InitialQuestionInterval + (mDNSs32)mDNSRandom((mDNSu32)mDNSPlatformOneSecond*4);
-				q->ThisQInterval = InitialQuestionInterval;
-				SetNextQueryTime(m,q);
-			}
-			verbosedebugf("CacheRecordAdd %p %##s (%s) %lu", rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype), rr->resrec.rroriginalttl);
-			q->CurrentAnswers++;
-			if (rr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers++;
-			if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers++;
-			AnswerQuestionWithResourceRecord(m, q, rr, mDNStrue);
-			// MUST NOT dereference q again after calling AnswerQuestionWithResourceRecord()
-		}
-	}
-	m->CurrentQuestion = mDNSNULL;
-}
-
-// CacheRecordRmv is only called from CheckCacheExpiration, which is called from mDNS_Execute
-// If new questions are created as a result of invoking client callbacks, they will be added to
-// the end of the question list, and m->NewQuestions will be set to indicate the first new question.
-// rr is an existing cache CacheRecord that just expired and is being deleted
-// (kDNSRecordTypePacketAns/PacketAnsUnique/PacketAdd/PacketAddUnique).
-// NOTE: CacheRecordRmv calls AnswerQuestionWithResourceRecord which can call a user callback,
-// which may change the record list and/or question list.
-// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
-mDNSlocal void CacheRecordRmv(mDNS *const m, CacheRecord *rr)
-{
-	if (m->CurrentQuestion) LogMsg("CacheRecordRmv ERROR m->CurrentQuestion already set");
-	m->CurrentQuestion = m->Questions;
-	while (m->CurrentQuestion && m->CurrentQuestion != m->NewQuestions)
-	{
-		DNSQuestion *q = m->CurrentQuestion;
-		m->CurrentQuestion = q->next;
-		if (ResourceRecordAnswersQuestion(&rr->resrec, q))
-		{
-			verbosedebugf("CacheRecordRmv %p %##s (%s)", rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-			if (q->CurrentAnswers == 0)
-				LogMsg("CacheRecordRmv ERROR: How can CurrentAnswers already be zero for %p %##s (%s)?", q, q->qname.c, DNSTypeName(q->qtype));
-			else
-			{
-				q->CurrentAnswers--;
-				if (rr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers--;
-				if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers--;
-			}
-			if (q->CurrentAnswers == 0)
-			{
-				debugf("CacheRecordRmv: Zero current answers for %##s (%s); will reconfirm antecedents", q->qname.c, DNSTypeName(q->qtype));
-				ReconfirmAntecedents(m, q);
-			}
-			AnswerQuestionWithResourceRecord(m, q, rr, mDNSfalse);
-			// MUST NOT dereference q again after calling AnswerQuestionWithResourceRecord()
-		}
-	}
-	m->CurrentQuestion = mDNSNULL;
-}
-
-mDNSlocal void ReleaseCacheRR(mDNS *const m, CacheRecord *r)
-{
-	if (r->resrec.rdata && r->resrec.rdata != (RData*)&r->rdatastorage)
-		mDNSPlatformMemFree(r->resrec.rdata);
-	r->resrec.rdata = mDNSNULL;
-	r->next = m->rrcache_free;
-	m->rrcache_free = r;
-	m->rrcache_totalused--;
-}
-
-mDNSlocal void CheckCacheExpiration(mDNS *const m, mDNSu32 slot)
-{
-	CacheRecord **rp = &(m->rrcache_hash[slot]);
-
-	if (m->lock_rrcache) { LogMsg("CheckCacheExpiration ERROR! Cache already locked!"); return; }
-	m->lock_rrcache = 1;
-
-	while (*rp)
-	{
-		CacheRecord *const rr = *rp;
-		mDNSs32 event = RRExpireTime(rr);
-		if (m->timenow - event >= 0)	// If expired, delete it
-		{
-			*rp = rr->next;				// Cut it from the list
-			verbosedebugf("CheckCacheExpiration: Deleting %s", GetRRDisplayString(m, rr));
-			if (rr->CRActiveQuestion)	// If this record has one or more active questions, tell them it's going away
-			{
-				CacheRecordRmv(m, rr);
-				m->rrcache_active--;
-			}
-			m->rrcache_used[slot]--;
-			ReleaseCacheRR(m, rr);
-		}
-		else							// else, not expired; see if we need to query
-		{
-			if (rr->CRActiveQuestion && rr->UnansweredQueries < MaxUnansweredQueries)
-			{
-				if (m->timenow - rr->NextRequiredQuery < 0)		// If not yet time for next query
-					event = rr->NextRequiredQuery;				// then just record when we want the next query
-				else											// else trigger our question to go out now
-				{
-					// Set NextScheduledQuery to timenow so that SendQueries() will run.
-					// SendQueries() will see that we have records close to expiration, and send FEQs for them.
-					m->NextScheduledQuery = m->timenow;
-					// After sending the query we'll increment UnansweredQueries and call SetNextCacheCheckTime(),
-					// which will correctly update m->NextCacheCheck for us
-					event = m->timenow + 0x3FFFFFFF;
-				}
-			}
-			if (m->NextCacheCheck - (event + CacheCheckGracePeriod(rr)) > 0)
-				m->NextCacheCheck = (event + CacheCheckGracePeriod(rr));
-			rp = &rr->next;
-		}
-	}
-	if (m->rrcache_tail[slot] != rp) debugf("CheckCacheExpiration: Updating m->rrcache_tail[%d] from %p to %p", slot, m->rrcache_tail[slot], rp);
-	m->rrcache_tail[slot] = rp;
-	m->lock_rrcache = 0;
-}
-
-mDNSlocal void AnswerNewQuestion(mDNS *const m)
-{
-	mDNSBool ShouldQueryImmediately = mDNStrue;
-	CacheRecord *rr;
-	DNSQuestion *q = m->NewQuestions;		// Grab the question we're going to answer
-	mDNSu32 slot = HashSlot(&q->qname);
-
-	verbosedebugf("AnswerNewQuestion: Answering %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-
-	CheckCacheExpiration(m, slot);
-	m->NewQuestions = q->next;				// Advance NewQuestions to the next *after* calling CheckCacheExpiration();
-
-	if (m->lock_rrcache) LogMsg("AnswerNewQuestion ERROR! Cache already locked!");
-	// This should be safe, because calling the client's question callback may cause the
-	// question list to be modified, but should not ever cause the rrcache list to be modified.
-	// If the client's question callback deletes the question, then m->CurrentQuestion will
-	// be advanced, and we'll exit out of the loop
-	m->lock_rrcache = 1;
-	if (m->CurrentQuestion) LogMsg("AnswerNewQuestion ERROR m->CurrentQuestion already set");
-	m->CurrentQuestion = q;		// Indicate which question we're answering, so we'll know if it gets deleted
-	for (rr=m->rrcache_hash[slot]; rr; rr=rr->next)
-		if (ResourceRecordAnswersQuestion(&rr->resrec, q))
-		{
-			// SecsSinceRcvd is whole number of elapsed seconds, rounded down
-			mDNSu32 SecsSinceRcvd = ((mDNSu32)(m->timenow - rr->TimeRcvd)) / mDNSPlatformOneSecond;
-			if (rr->resrec.rroriginalttl <= SecsSinceRcvd)
-			{
-				LogMsg("AnswerNewQuestion: How is rr->resrec.rroriginalttl %lu <= SecsSinceRcvd %lu for %##s (%s)",
-				       rr->resrec.rroriginalttl, SecsSinceRcvd, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-				continue;	// Go to next one in loop
-			}
-
-			// If this record set is marked unique, then that means we can reasonably assume we have the whole set
-			// -- we don't need to rush out on the network and query immediately to see if there are more answers out there
-			if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) ShouldQueryImmediately = mDNSfalse;
-			q->CurrentAnswers++;
-			if (rr->resrec.rdlength > SmallRecordLimit) q->LargeAnswers++;
-			if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask) q->UniqueAnswers++;
-			AnswerQuestionWithResourceRecord(m, q, rr, mDNStrue);
-			// MUST NOT dereference q again after calling AnswerQuestionWithResourceRecord()
-			if (m->CurrentQuestion != q) break;		// If callback deleted q, then we're finished here
-		}
-		else if (RRTypeIsAddressType(rr->resrec.rrtype) && RRTypeIsAddressType(q->qtype))
-			if (rr->resrec.namehash == q->qnamehash && SameDomainName(&rr->resrec.name, &q->qname))
-				ShouldQueryImmediately = mDNSfalse;
-
-	if (ShouldQueryImmediately && m->CurrentQuestion == q)
-	{
-		q->ThisQInterval = InitialQuestionInterval;
-		q->LastQTime = m->timenow - q->ThisQInterval;
-		m->NextScheduledQuery = m->timenow;
-	}
-	m->CurrentQuestion = mDNSNULL;
-	m->lock_rrcache = 0;
-}
-
-mDNSlocal void AnswerLocalOnlyQuestionWithResourceRecord(mDNS *const m, DNSQuestion *q, AuthRecord *rr, mDNSBool AddRecord)
-{
-	// Indicate that we've given at least one positive answer for this record, so we should be prepared to send a goodbye for it
-	if (AddRecord) rr->AnnounceCount = InitialAnnounceCount - 1;
-	m->mDNS_reentrancy++; // Increment to allow client to legally make mDNS API calls from the callback
-	if (q->QuestionCallback)
-		q->QuestionCallback(m, q, &rr->resrec, AddRecord);
-	m->mDNS_reentrancy--; // Decrement to block mDNS API calls again
-}
-
-mDNSlocal void AnswerNewLocalOnlyQuestion(mDNS *const m)
-{
-	DNSQuestion *q = m->NewLocalOnlyQuestions;		// Grab the question we're going to answer
-	m->NewLocalOnlyQuestions = q->next;				// Advance NewQuestions to the next (if any)
-
-	debugf("AnswerNewLocalOnlyQuestion: Answering %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
-
-	if (m->CurrentQuestion) LogMsg("AnswerNewQuestion ERROR m->CurrentQuestion already set");
-	m->CurrentQuestion = q;		// Indicate which question we're answering, so we'll know if it gets deleted
-
-	m->CurrentRecord = m->LocalOnlyRecords;
-	while (m->CurrentRecord && m->CurrentRecord != m->NewLocalOnlyRecords)
-	{
-		AuthRecord *rr = m->CurrentRecord;
-		m->CurrentRecord = rr->next;
-		if (ResourceRecordAnswersQuestion(&rr->resrec, q))
-		{
-			AnswerLocalOnlyQuestionWithResourceRecord(m, q, rr, mDNStrue);
-			// MUST NOT dereference q again after calling AnswerLocalOnlyQuestionWithResourceRecord()
-			if (m->CurrentQuestion != q) break;		// If callback deleted q, then we're finished here
-		}
-	}
-
-	m->CurrentQuestion = mDNSNULL;
-}
-
-mDNSlocal void AnswerLocalOnlyQuestions(mDNS *const m, AuthRecord *rr, mDNSBool AddRecord)
-{
-	if (m->CurrentQuestion) LogMsg("AnswerLocalOnlyQuestions ERROR m->CurrentQuestion already set");
-	m->CurrentQuestion = m->LocalOnlyQuestions;
-	while (m->CurrentQuestion && m->CurrentQuestion != m->NewLocalOnlyQuestions)
-	{
-		DNSQuestion *q = m->CurrentQuestion;
-		m->CurrentQuestion = q->next;
-		if (ResourceRecordAnswersQuestion(&rr->resrec, q))
-		{
-			debugf("AnswerLocalOnlyQuestions %p %##s (%s) %lu", rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype), rr->resrec.rroriginalttl);
-			AnswerLocalOnlyQuestionWithResourceRecord(m, q, rr, AddRecord);
-			// MUST NOT dereference q again after calling AnswerQuestionWithResourceRecord()
-		}
-	}
-	m->CurrentQuestion = mDNSNULL;
-}
-
-mDNSlocal void DiscardLocalOnlyRecords(mDNS *const m)
-{
-	AuthRecord *rr = m->LocalOnlyRecords;
-	while (rr)
-	{
-		if (rr->resrec.RecordType == kDNSRecordTypeDeregistering)
-		{ AnswerLocalOnlyQuestions(m, rr, mDNSfalse); CompleteDeregistration(m, rr); return; }
-		if (rr->ProbeCount) { mDNS_Deregister_internal(m, rr, mDNS_Dereg_conflict); return; }
-		rr=rr->next;
-	}
-	m->DiscardLocalOnlyRecords = mDNSfalse;
-}
-
-mDNSlocal void AnswerForNewLocalOnlyRecords(mDNS *const m)
-{
-	AuthRecord *rr = m->NewLocalOnlyRecords;
-	m->NewLocalOnlyRecords = m->NewLocalOnlyRecords->next;
-	AnswerLocalOnlyQuestions(m, rr, mDNStrue);
-}
-
-mDNSlocal CacheRecord *GetFreeCacheRR(mDNS *const m, mDNSu16 RDLength)
-{
-	CacheRecord *r = mDNSNULL;
-
-	if (m->lock_rrcache) { LogMsg("GetFreeCacheRR ERROR! Cache already locked!"); return(mDNSNULL); }
-	m->lock_rrcache = 1;
-	
-	// If we have no free records, ask the client layer to give us some more memory
-	if (!m->rrcache_free && m->MainCallback)
-	{
-		if (m->rrcache_totalused != m->rrcache_size)
-			LogMsg("GetFreeCacheRR: count mismatch: m->rrcache_totalused %lu != m->rrcache_size %lu",
-			       m->rrcache_totalused, m->rrcache_size);
-		
-		// We don't want to be vulnerable to a malicious attacker flooding us with an infinite
-		// number of bogus records so that we keep growing our cache until the machine runs out of memory.
-		// To guard against this, if we're actively using less than 1/32 of our cache, then we
-		// purge all the unused records and recycle them, instead of allocating more memory.
-		if (m->rrcache_size >= 512 && m->rrcache_size / 32 > m->rrcache_active)
-			debugf("Possible denial-of-service attack in progress: m->rrcache_size %lu; m->rrcache_active %lu",
-			       m->rrcache_size, m->rrcache_active);
-		else
-			m->MainCallback(m, mStatus_GrowCache);
-	}
-	
-	// If we still have no free records, recycle all the records we can.
-	// Enumerating the entire cache is moderately expensive, so when we do it, we reclaim all the records we can in one pass.
-	if (!m->rrcache_free)
-	{
-#if MDNS_DEBUGMSGS
-		mDNSu32 oldtotalused = m->rrcache_totalused;
-#endif
-		mDNSu32 slot;
-		for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
-		{
-			CacheRecord **rp = &(m->rrcache_hash[slot]);
-			while (*rp)
-			{
-				// Records that answer still-active questions are not candidates for deletion
-				if ((*rp)->CRActiveQuestion)
-					rp=&(*rp)->next;
-				else
-				{
-					CacheRecord *rr = *rp;
-					*rp = (*rp)->next;			// Cut record from list
-					m->rrcache_used[slot]--;	// Decrement counts
-					ReleaseCacheRR(m, rr);
-				}
-			}
-			if (m->rrcache_tail[slot] != rp) debugf("GetFreeCacheRR: Updating m->rrcache_tail[%d] from %p to %p", slot, m->rrcache_tail[slot], rp);
-			m->rrcache_tail[slot] = rp;
-		}
-#if MDNS_DEBUGMSGS
-		debugf("Clear unused records; m->rrcache_totalused was %lu; now %lu", oldtotalused, m->rrcache_totalused);
-#endif
-	}
-	
-	if (m->rrcache_free)	// If there are records in the free list, take one
-	{
-		r = m->rrcache_free;
-		m->rrcache_free = r->next;
-	}
-
-	if (r)
-	{
-		if (++m->rrcache_totalused >= m->rrcache_report)
-		{
-			debugf("RR Cache now using %ld records", m->rrcache_totalused);
-			if (m->rrcache_report < 100) m->rrcache_report += 10;
-			else                         m->rrcache_report += 100;
-		}
-		mDNSPlatformMemZero(r, sizeof(*r));
-		r->resrec.rdata = (RData*)&r->rdatastorage;		// By default, assume we're usually going to be using local storage
-	
-		if (RDLength > InlineCacheRDSize)		// If RDLength is too big, allocate extra storage
-		{
-			r->resrec.rdata = (RData*)mDNSPlatformMemAllocate(sizeofRDataHeader + RDLength);
-			if (r->resrec.rdata) r->resrec.rdata->MaxRDLength = r->resrec.rdlength = RDLength;
-			else { ReleaseCacheRR(m, r); r = mDNSNULL; }
-		}
-	}
-
-	m->lock_rrcache = 0;
-
-	return(r);
-}
-
-mDNSlocal void PurgeCacheResourceRecord(mDNS *const m, CacheRecord *rr)
-{
-	// Make sure we mark this record as thoroughly expired -- we don't ever want to give
-	// a positive answer using an expired record (e.g. from an interface that has gone away).
-	// We don't want to clear CRActiveQuestion here, because that would leave the record subject to
-	// summary deletion without giving the proper callback to any questions that are monitoring it.
-	// By setting UnansweredQueries to MaxUnansweredQueries we ensure it won't trigger any further expiration queries.
-	rr->TimeRcvd          = m->timenow - mDNSPlatformOneSecond * 60;
-	rr->UnansweredQueries = MaxUnansweredQueries;
-	rr->resrec.rroriginalttl     = 0;
-	SetNextCacheCheckTime(m, rr);
-}
-
-mDNSexport void mDNS_Lock(mDNS *const m)
-{
-	// MUST grab the platform lock FIRST!
-	mDNSPlatformLock(m);
-
-	// Normally, mDNS_reentrancy is zero and so is mDNS_busy
-	// However, when we call a client callback mDNS_busy is one, and we increment mDNS_reentrancy too
-	// If that client callback does mDNS API calls, mDNS_reentrancy and mDNS_busy will both be one
-	// If mDNS_busy != mDNS_reentrancy that's a bad sign
-	if (m->mDNS_busy != m->mDNS_reentrancy)
-		LogMsg("mDNS_Lock: Locking failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
-
-	// If this is an initial entry into the mDNSCore code, set m->timenow
-	// else, if this is a re-entrant entry into the mDNSCore code, m->timenow should already be set
-	if (m->mDNS_busy == 0)
-	{
-		if (m->timenow)
-			LogMsg("mDNS_Lock: m->timenow already set (%ld/%ld)", m->timenow, mDNSPlatformTimeNow() + m->timenow_adjust);
-		m->timenow = mDNSPlatformTimeNow() + m->timenow_adjust;
-		if (m->timenow == 0) m->timenow = 1;
-	}
-	else if (m->timenow == 0)
-	{
-		LogMsg("mDNS_Lock: m->mDNS_busy is %ld but m->timenow not set", m->mDNS_busy);
-		m->timenow = mDNSPlatformTimeNow() + m->timenow_adjust;
-		if (m->timenow == 0) m->timenow = 1;
-	}
-
-	if (m->timenow_last - m->timenow > 0)
-	{
-		m->timenow_adjust += m->timenow_last - m->timenow;
-		LogMsg("mDNSPlatformTimeNow went backwards by %ld ticks; setting correction factor to %ld", m->timenow_last - m->timenow, m->timenow_adjust);
-		m->timenow = m->timenow_last;
-	}
-	m->timenow_last = m->timenow;
-
-	// Increment mDNS_busy so we'll recognise re-entrant calls
-	m->mDNS_busy++;
-}
-
-mDNSlocal mDNSs32 GetNextScheduledEvent(const mDNS *const m)
-{
-	mDNSs32 e = m->timenow + kNextScheduledTime;
-	LogMsg("GetNextScheduledEvent e=%d, m->timenow= %d\n", e, m->timenow);
-	if (m->mDNSPlatformStatus != mStatus_NoError || m->SleepState) return(e);
-	LogMsg("GetNextScheduledEvent m->NewQuestions=%d, m->NewLocalOnlyQuestions=%d, m->NewLocalOnlyRecords=%d, m->DiscardLocalOnlyRecords=%d\n",
-		m->NewQuestions, m->NewLocalOnlyQuestions, m->NewLocalOnlyRecords, m->DiscardLocalOnlyRecords);
-	if (m->NewQuestions)            return(m->timenow);
-	if (m->NewLocalOnlyQuestions)   return(m->timenow);
-	if (m->NewLocalOnlyRecords)     return(m->timenow);
-	if (m->DiscardLocalOnlyRecords) return(m->timenow);
-	LogMsg("GetNextScheduledEvent SuppressSending=%d\n", m->SuppressSending);
-	if (m->SuppressSending)         return(m->SuppressSending);
-	if (e - m->NextCacheCheck        > 0) e = m->NextCacheCheck;
-	if (e - m->NextScheduledQuery    > 0) e = m->NextScheduledQuery;
-	if (e - m->NextScheduledProbe    > 0) e = m->NextScheduledProbe;
-	if (e - m->NextScheduledResponse > 0) e = m->NextScheduledResponse;
-	LogMsg("GetNextScheduledEvent m->rrcache_size=%d, m->NextCacheCheck=%d, m->NextScheduledQuery=%d, m->NextScheduledProbe=%d, m->NextScheduledResponse=%d\n",
-		m->rrcache_size, m->NextCacheCheck, m->NextScheduledQuery, m->NextScheduledProbe, m->NextScheduledResponse);
-	return(e);
-}
-
-mDNSexport void mDNS_Unlock(mDNS *const m)
-{
-	// Decrement mDNS_busy
-	m->mDNS_busy--;
-	
-	// Check for locking failures
-	if (m->mDNS_busy != m->mDNS_reentrancy)
-		LogMsg("mDNS_Unlock: Locking failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
-
-	// If this is a final exit from the mDNSCore code, set m->NextScheduledEvent and clear m->timenow
-	if (m->mDNS_busy == 0)
-	{
-		m->NextScheduledEvent = GetNextScheduledEvent(m);
-		LogMsg("mDNS_Unlock: NextScheduledEvent %d\n", m->NextScheduledEvent);
-		if (m->timenow == 0) LogMsg("mDNS_Unlock: ERROR! m->timenow aready zero");
-		m->timenow = 0;
-	}
-
-	// MUST release the platform lock LAST!
-	mDNSPlatformUnlock(m);
-}
-
-mDNSexport mDNSs32 mDNS_Execute(mDNS *const m)
-{
-	mDNS_Lock(m);	// Must grab lock before trying to read m->timenow
-
-	LogMsg("mDNS_Execute: m->timenow=%d, m->NextScheduledEvent=%d\n", m->timenow, m->NextScheduledEvent);
-	if (m->timenow - m->NextScheduledEvent >= 0)
-	{
-		int i;
-
-		verbosedebugf("mDNS_Execute");
-		if (m->CurrentQuestion) LogMsg("mDNS_Execute: ERROR! m->CurrentQuestion already set");
-	
-		// 1. If we're past the probe suppression time, we can clear it
-		if (m->SuppressProbes && m->timenow - m->SuppressProbes >= 0) m->SuppressProbes = 0;
-	
-		// 2. If it's been more than ten seconds since the last probe failure, we can clear the counter
-		if (m->NumFailedProbes && m->timenow - m->ProbeFailTime >= mDNSPlatformOneSecond * 10) m->NumFailedProbes = 0;
-		
-		// 3. Purge our cache of stale old records
-		if (m->rrcache_size && m->timenow - m->NextCacheCheck >= 0)
-		{
-			mDNSu32 slot;
-			m->NextCacheCheck = m->timenow + 0x3FFFFFFF;
-			for (slot = 0; slot < CACHE_HASH_SLOTS; slot++) CheckCacheExpiration(m, slot);
-		}
-	
-		// 4. See if we can answer any of our new local questions from the cache
-		for (i=0; m->NewQuestions && i<1000; i++) AnswerNewQuestion(m);
-		if (i >= 1000) debugf("mDNS_Execute: AnswerNewQuestion exceeded loop limit");
-		
-		for (i=0; m->DiscardLocalOnlyRecords && i<1000; i++) DiscardLocalOnlyRecords(m);
-		if (i >= 1000) debugf("mDNS_Execute: DiscardLocalOnlyRecords exceeded loop limit");
-
-		for (i=0; m->NewLocalOnlyQuestions && i<1000; i++) AnswerNewLocalOnlyQuestion(m);
-		if (i >= 1000) debugf("mDNS_Execute: AnswerNewLocalOnlyQuestion exceeded loop limit");
-
-		for (i=0; m->NewLocalOnlyRecords && i<1000; i++) AnswerForNewLocalOnlyRecords(m);
-		if (i >= 1000) debugf("mDNS_Execute: AnswerLocalOnlyQuestions exceeded loop limit");
-
-		// 5. See what packets we need to send
-		if (m->mDNSPlatformStatus != mStatus_NoError || m->SleepState) DiscardDeregistrations(m);
-		else if (m->SuppressSending == 0 || m->timenow - m->SuppressSending >= 0)
-		{
-			// If the platform code is ready, and we're not suppressing packet generation right now
-			// then send our responses, probes, and questions.
-			// We check the cache first, because there might be records close to expiring that trigger questions to refresh them
-			// We send queries next, because there might be final-stage probes that complete their probing here, causing
-			// them to advance to announcing state, and we want those to be included in any announcements we send out.
-			// Finally, we send responses, including the previously mentioned records that just completed probing
-			m->SuppressSending = 0;
-	
-			// 6. Send Query packets. This may cause some probing records to advance to announcing state
-			if (m->timenow - m->NextScheduledQuery >= 0 || m->timenow - m->NextScheduledProbe >= 0) SendQueries(m);
-			if (m->timenow - m->NextScheduledQuery >= 0)
-			{
-				LogMsg("mDNS_Execute: SendQueries didn't send all its queries; will try again in one second");
-				m->NextScheduledQuery = m->timenow + mDNSPlatformOneSecond;
-			}
-			if (m->timenow - m->NextScheduledProbe >= 0)
-			{
-				LogMsg("mDNS_Execute: SendQueries didn't send all its probes; will try again in one second");
-				m->NextScheduledProbe = m->timenow + mDNSPlatformOneSecond;
-			}
-	
-			// 7. Send Response packets, including probing records just advanced to announcing state
-			if (m->timenow - m->NextScheduledResponse >= 0) SendResponses(m);
-			if (m->timenow - m->NextScheduledResponse >= 0)
-			{
-				LogMsg("mDNS_Execute: SendResponses didn't send all its responses; will try again in one second");
-				m->NextScheduledResponse = m->timenow + mDNSPlatformOneSecond;
-			}
-		}
-
-		m->RandomQueryDelay = 0;	// Clear m->RandomQueryDelay, ready to pick a new different value, when necessary
-	}
-
-	// Note about multi-threaded systems:
-	// On a multi-threaded system, some other thread could run right after the mDNS_Unlock(),
-	// performing mDNS API operations that change our next scheduled event time.
-	//
-	// On multi-threaded systems (like the current Windows implementation) that have a single main thread
-	// calling mDNS_Execute() (and other threads allowed to call mDNS API routines) it is the responsibility
-	// of the mDNSPlatformUnlock() routine to signal some kind of stateful condition variable that will
-	// signal whatever blocking primitive the main thread is using, so that it will wake up and execute one
-	// more iteration of its loop, and immediately call mDNS_Execute() again. The signal has to be stateful
-	// in the sense that if the main thread has not yet entered its blocking primitive, then as soon as it
-	// does, the state of the signal will be noticed, causing the blocking primitive to return immediately
-	// without blocking. This avoids the race condition between the signal from the other thread arriving
-	// just *before* or just *after* the main thread enters the blocking primitive.
-	//
-	// On multi-threaded systems (like the current Mac OS 9 implementation) that are entirely timer-driven,
-	// with no main mDNS_Execute() thread, it is the responsibility of the mDNSPlatformUnlock() routine to
-	// set the timer according to the m->NextScheduledEvent value, and then when the timer fires, the timer
-	// callback function should call mDNS_Execute() (and ignore the return value, which may already be stale
-	// by the time it gets to the timer callback function).
-
-	mDNS_Unlock(m);		// Calling mDNS_Unlock is what gives m->NextScheduledEvent its new value
-	return(m->NextScheduledEvent);
-}
-#if 0
-// Call mDNSCoreMachineSleep(m, mDNStrue) when the machine is about to go to sleep.
-// Call mDNSCoreMachineSleep(m, mDNSfalse) when the machine is has just woken up.
-// Normally, the platform support layer below mDNSCore should call this, not the client layer above.
-// Note that sleep/wake calls do not have to be paired one-for-one; it is acceptable to call
-// mDNSCoreMachineSleep(m, mDNSfalse) any time there is reason to believe that the machine may have just
-// found itself in a new network environment. For example, if the Ethernet hardware indicates that the
-// cable has just been connected, the platform support layer should call mDNSCoreMachineSleep(m, mDNSfalse)
-// to make mDNSCore re-issue its outstanding queries, probe for record uniqueness, etc.
-// While it is safe to call mDNSCoreMachineSleep(m, mDNSfalse) at any time, it does cause extra network
-// traffic, so it should only be called when there is legitimate reason to believe the machine
-// may have become attached to a new network.
-mDNSexport void mDNSCoreMachineSleep(mDNS *const m, mDNSBool sleepstate)
-{
-	AuthRecord *rr;
-
-	mDNS_Lock(m);
-
-	m->SleepState = sleepstate;
-	LogMsg("mDNSResponder %s at %ld", sleepstate ? "Sleeping" : "Waking", m->timenow);
-
-	if (sleepstate)
-	{
-		// Mark all the records we need to deregister and send them
-		for (rr = m->ResourceRecords; rr; rr=rr->next)
-			if (rr->resrec.RecordType == kDNSRecordTypeShared && rr->AnnounceCount < InitialAnnounceCount)
-				rr->ImmedAnswer = mDNSInterfaceMark;
-		SendResponses(m);
-	}
-	else
-	{
-		DNSQuestion *q;
-		mDNSu32 slot;
-		CacheRecord *cr;
-
-		// 1. Retrigger all our questions
-		for (q = m->Questions; q; q=q->next)				// Scan our list of questions
-			if (ActiveQuestion(q))
-			{
-				q->ThisQInterval = InitialQuestionInterval;	// MUST be > zero for an active question
-				q->LastQTime     = m->timenow - q->ThisQInterval;
-				q->RecentAnswers = 0;
-				ExpireDupSuppressInfo(q->DupSuppress, m->timenow);
-				m->NextScheduledQuery = m->timenow;
-			}
-
-		// 2. Re-validate our cache records
-		m->NextCacheCheck  = m->timenow;
-		for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
-			for (cr = m->rrcache_hash[slot]; cr; cr=cr->next)
-				mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForCableDisconnect);
-
-		// 3. Retrigger probing and announcing for all our authoritative records
-		for (rr = m->ResourceRecords; rr; rr=rr->next)
-		{
-			if (rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->DependentOn) rr->resrec.RecordType = kDNSRecordTypeUnique;
-			rr->ProbeCount        = DefaultProbeCountForRecordType(rr->resrec.RecordType);
-			if (rr->AnnounceCount < ReannounceCount)
-				rr->AnnounceCount = ReannounceCount;
-			rr->ThisAPInterval    = DefaultAPIntervalForRecordType(rr->resrec.RecordType);
-			InitializeLastAPTime(m, rr);
-		}
-
-	}
-
-	mDNS_Unlock(m);
-}
-#endif
-// ***************************************************************************
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - Packet Reception Functions
-#endif
-
-mDNSlocal void AddRecordToResponseList(AuthRecord ***nrpp, AuthRecord *rr, AuthRecord *add)
-{
-	if (rr->NextResponse == mDNSNULL && *nrpp != &rr->NextResponse)
-	{
-		**nrpp = rr;
-		// NR_AdditionalTo must point to a record with NR_AnswerTo set (and not NR_AdditionalTo)
-		// If 'add' does not meet this requirement, then follow its NR_AdditionalTo pointer to a record that does
-		// The referenced record will definitely be acceptable (by recursive application of this rule)
-		if (add && add->NR_AdditionalTo) add = add->NR_AdditionalTo;
-		rr->NR_AdditionalTo = add;
-		*nrpp = &rr->NextResponse;
-	}
-	debugf("AddRecordToResponseList: %##s (%s) already in list", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-}
-
-#define MustSendRecord(RR) ((RR)->NR_AnswerTo || (RR)->NR_AdditionalTo)
-
-mDNSlocal mDNSu8 *GenerateUnicastResponse(const DNSMessage *const query, const mDNSu8 *const end,
-					  const mDNSInterfaceID InterfaceID, mDNSBool LegacyQuery, DNSMessage *const response, AuthRecord *ResponseRecords)
-{
-	mDNSu8          *responseptr     = response->data;
-	const mDNSu8    *const limit     = response->data + sizeof(response->data);
-	const mDNSu8    *ptr             = query->data;
-	AuthRecord  *rr;
-	mDNSu32          maxttl = 0x70000000;
-	int i;
-
-	// Initialize the response fields so we can answer the questions
-	InitializeDNSMessage(&response->h, query->h.id, ResponseFlags);
-
-	// ***
-	// *** 1. Write out the list of questions we are actually going to answer with this packet
-	// ***
-	if (LegacyQuery)
-	{
-		DNSQuestion *q = tls_mem_alloc(sizeof(DNSQuestion));
-		maxttl = 10;
-		if(q)
-		{
-			memset(q, 0, sizeof(DNSQuestion));
-			for (i=0; i<query->h.numQuestions; i++)						// For each question...
-			{
-				ptr = getQuestion(query, ptr, end, InterfaceID, q);	// get the question...
-				if (!ptr) { tls_mem_free(q); return(mDNSNULL); }
-		
-				for (rr=ResponseRecords; rr; rr=rr->NextResponse)		// and search our list of proposed answers
-				{
-					if (rr->NR_AnswerTo == ptr)							// If we're going to generate a record answering this question
-					{												// then put the question in the question section
-						responseptr = putQuestion(response, responseptr, limit, &q->qname, q->qtype, q->qclass);
-						if (!responseptr) { debugf("GenerateUnicastResponse: Ran out of space for questions!"); tls_mem_free(q); return(mDNSNULL); }
-						break;		// break out of the ResponseRecords loop, and go on to the next question
-					}
-				}
-			}
-			tls_mem_free(q);
-		}
-		if (response->h.numQuestions == 0) { LogMsg("GenerateUnicastResponse: ERROR! Why no questions?"); return(mDNSNULL); }
-	}
-
-	// ***
-	// *** 2. Write Answers
-	// ***
-	for (rr=ResponseRecords; rr; rr=rr->NextResponse)
-		if (rr->NR_AnswerTo)
-		{
-			mDNSu8 *p = PutResourceRecordCappedTTL(response, responseptr, &response->h.numAnswers, &rr->resrec, maxttl);
-			if (p) responseptr = p;
-			else { debugf("GenerateUnicastResponse: Ran out of space for answers!"); response->h.flags.b[0] |= kDNSFlag0_TC; }
-		}
-
-	// ***
-	// *** 3. Write Additionals
-	// ***
-	for (rr=ResponseRecords; rr; rr=rr->NextResponse)
-		if (rr->NR_AdditionalTo && !rr->NR_AnswerTo)
-		{
-			mDNSu8 *p = PutResourceRecordCappedTTL(response, responseptr, &response->h.numAdditionals, &rr->resrec, maxttl);
-			if (p) responseptr = p;
-			else debugf("GenerateUnicastResponse: No more space for additionals");
-		}
-
-	return(responseptr);
-}
-
-// AuthRecord *our is our Resource Record
-// CacheRecord *pkt is the Resource Record from the response packet we've witnessed on the network
-// Returns 0 if there is no conflict
-// Returns +1 if there was a conflict and we won
-// Returns -1 if there was a conflict and we lost and have to rename
-mDNSlocal int CompareRData(AuthRecord *our, CacheRecord *pkt)
-{
-	mDNSu8 *ourdata = NULL, *ourptr = ourdata, *ourend;
-	mDNSu8 *pktdata = NULL, *pktptr = pktdata, *pktend;
-	if (!our) { LogMsg("CompareRData ERROR: our is NULL"); return(+1); }
-	if (!pkt) { LogMsg("CompareRData ERROR: pkt is NULL"); return(+1); }
-
-	ourdata = tls_mem_alloc(512);
-	if(!ourdata) return (0);
-	pktdata = ourdata + 256;
-	memset(ourdata, 0, 512);
-	ourend = putRData(mDNSNULL, ourdata, ourdata + 256, &our->resrec);
-	pktend = putRData(mDNSNULL, pktdata, pktdata + 256, &pkt->resrec);
-	while (ourptr < ourend && pktptr < pktend && *ourptr == *pktptr) { ourptr++; pktptr++; }
-	if (ourptr >= ourend && pktptr >= pktend) { tls_mem_free(ourdata); return(0); }		// If data identical, not a conflict
-
-	if (ourptr >= ourend) { tls_mem_free(ourdata); return(-1); }									// Our data ran out first; We lost
-	if (pktptr >= pktend) { tls_mem_free(ourdata); return(+1); }									// Packet data ran out first; We won
-	if (*pktptr > *ourptr) { tls_mem_free(ourdata); return(-1); }								// Our data is numerically lower; We lost
-	if (*pktptr < *ourptr) { tls_mem_free(ourdata); return(+1); }								// Packet data is numerically lower; We won
-	
-	debugf("CompareRData: How did we get here?");
-	tls_mem_free(ourdata);
-	return(-1);
-}
-
-// See if we have an authoritative record that's identical to this packet record,
-// whose canonical DependentOn record is the specified master record.
-// The DependentOn pointer is typically used for the TXT record of service registrations
-// It indicates that there is no inherent conflict detection for the TXT record
-// -- it depends on the SRV record to resolve name conflicts
-// If we find any identical ResourceRecords in our authoritative list, then follow their DependentOn
-// pointer chain (if any) to make sure we reach the canonical DependentOn record
-// If the record has no DependentOn, then just return that record's pointer
-// Returns NULL if we don't have any local RRs that are identical to the one from the packet
-mDNSlocal mDNSBool MatchDependentOn(const mDNS *const m, const CacheRecord *const pktrr, const AuthRecord *const master)
-{
-	const AuthRecord *r1;
-	for (r1 = m->ResourceRecords; r1; r1=r1->next)
-	{
-		if (IdenticalResourceRecord(&r1->resrec, &pktrr->resrec))
-		{
-			const AuthRecord *r2 = r1;
-			while (r2->DependentOn) r2 = r2->DependentOn;
-			if (r2 == master) return(mDNStrue);
-		}
-	}
-	for (r1 = m->DuplicateRecords; r1; r1=r1->next)
-	{
-		if (IdenticalResourceRecord(&r1->resrec, &pktrr->resrec))
-		{
-			const AuthRecord *r2 = r1;
-			while (r2->DependentOn) r2 = r2->DependentOn;
-			if (r2 == master) return(mDNStrue);
-		}
-	}
-	return(mDNSfalse);
-}
-
-// Find the canonical RRSet pointer for this RR received in a packet.
-// If we find any identical AuthRecord in our authoritative list, then follow its RRSet
-// pointers (if any) to make sure we return the canonical member of this name/type/class
-// Returns NULL if we don't have any local RRs that are identical to the one from the packet
-mDNSlocal const AuthRecord *FindRRSet(const mDNS *const m, const CacheRecord *const pktrr)
-{
-	const AuthRecord *rr;
-	for (rr = m->ResourceRecords; rr; rr=rr->next)
-	{
-		if (IdenticalResourceRecord(&rr->resrec, &pktrr->resrec))
-		{
-			while (rr->RRSet && rr != rr->RRSet) rr = rr->RRSet;
-			return(rr);
-		}
-	}
-	return(mDNSNULL);
-}
-
-// PacketRRConflict is called when we've received an RR (pktrr) which has the same name
-// as one of our records (our) but different rdata.
-// 1. If our record is not a type that's supposed to be unique, we don't care.
-// 2a. If our record is marked as dependent on some other record for conflict detection, ignore this one.
-// 2b. If the packet rr exactly matches one of our other RRs, and *that* record's DependentOn pointer
-//     points to our record, ignore this conflict (e.g. the packet record matches one of our
-//     TXT records, and that record is marked as dependent on 'our', its SRV record).
-// 3. If we have some *other* RR that exactly matches the one from the packet, and that record and our record
-//    are members of the same RRSet, then this is not a conflict.
-mDNSlocal mDNSBool PacketRRConflict(const mDNS *const m, const AuthRecord *const our, const CacheRecord *const pktrr)
-{
-	const AuthRecord *ourset = our->RRSet ? our->RRSet : our;
-
-	// If not supposed to be unique, not a conflict
-	if (!(our->resrec.RecordType & kDNSRecordTypeUniqueMask)) return(mDNSfalse);
-
-	// If a dependent record, not a conflict
-	if (our->DependentOn || MatchDependentOn(m, pktrr, our)) return(mDNSfalse);
-
-	// If the pktrr matches a member of ourset, not a conflict
-	if (FindRRSet(m, pktrr) == ourset) return(mDNSfalse);
-
-	// Okay, this is a conflict
-	return(mDNStrue);
-}
-
-// NOTE: ResolveSimultaneousProbe calls mDNS_Deregister_internal which can call a user callback, which may change
-// the record list and/or question list.
-// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
-mDNSlocal void ResolveSimultaneousProbe(mDNS *const m, const DNSMessage *const query, const mDNSu8 *const end,
-					DNSQuestion *q, AuthRecord *our)
-{
-	int i;
-	const mDNSu8 *ptr = LocateAuthorities(query, end);
-	mDNSBool FoundUpdate = mDNSfalse;
-	LargeCacheRecord *pkt = tls_mem_alloc(sizeof(LargeCacheRecord));
-
-	if(!pkt) goto exit;
-	for (i = 0; i < query->h.numAuthorities; i++)
-	{
-		memset(pkt, 0, sizeof(LargeCacheRecord));
-		ptr = GetLargeResourceRecord(m, query, ptr, end, q->InterfaceID, 0, pkt);
-		if (!ptr) break;
-		if (ResourceRecordAnswersQuestion(&pkt->r.resrec, q))
-		{
-			FoundUpdate = mDNStrue;
-			if (PacketRRConflict(m, our, &pkt->r))
-			{
-				int result          = (int)our->resrec.rrclass - (int)pkt->r.resrec.rrclass;
-				if (!result) result = (int)our->resrec.rrtype  - (int)pkt->r.resrec.rrtype;
-				if (!result) result = CompareRData(our, &pkt->r);
-				switch (result)
-				{
-				case  1:	debugf("ResolveSimultaneousProbe: %##s (%s): We won",  our->resrec.name.c, DNSTypeName(our->resrec.rrtype));
-					break;
-				case  0:	break;
-				case -1:	debugf("ResolveSimultaneousProbe: %##s (%s): We lost", our->resrec.name.c, DNSTypeName(our->resrec.rrtype));
-					mDNS_Deregister_internal(m, our, mDNS_Dereg_conflict);
-					goto exit;
-				}
-			}
-		}
-	}
-exit:
-	if(pkt)
-		tls_mem_free(pkt);
-	if (!FoundUpdate)
-		debugf("ResolveSimultaneousProbe: %##s (%s): No Update Record found", our->resrec.name.c, DNSTypeName(our->resrec.rrtype));
-}
-
-mDNSlocal CacheRecord *FindIdenticalRecordInCache(const mDNS *const m, ResourceRecord *pktrr)
-{
-	CacheRecord *rr;
-	for (rr = m->rrcache_hash[HashSlot(&pktrr->name)]; rr; rr=rr->next)
-		if (pktrr->InterfaceID == rr->resrec.InterfaceID && IdenticalResourceRecord(pktrr, &rr->resrec)) break;
-	return(rr);
-}
-
-// ProcessQuery examines a received query to see if we have any answers to give
-mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, const mDNSu8 *const end,
-			       const mDNSAddr *srcaddr, const mDNSInterfaceID InterfaceID, mDNSBool LegacyQuery, mDNSBool QueryWasMulticast,
-			       DNSMessage *const response)
-{
-	AuthRecord  *ResponseRecords = mDNSNULL;
-	AuthRecord **nrp             = &ResponseRecords;
-	CacheRecord  *ExpectedAnswers = mDNSNULL;			// Records in our cache we expect to see updated
-	CacheRecord **eap             = &ExpectedAnswers;
-	DNSQuestion     *DupQuestions    = mDNSNULL;			// Our questions that are identical to questions in this packet
-	DNSQuestion    **dqp             = &DupQuestions;
-	mDNSs32          delayresponse   = 0;
-	mDNSBool         HaveUnicastAnswer = mDNSfalse;
-	const mDNSu8    *ptr             = query->data;
-	mDNSu8          *responseptr     = mDNSNULL;
-	AuthRecord  *rr, *rr2;
-	int i;
-
-	// If TC flag is set, it means we should expect that additional known answers may be coming in another packet.
-	if (query->h.flags.b[0] & kDNSFlag0_TC) delayresponse = mDNSPlatformOneSecond;	// Divided by 50 = 20ms
-
-	// ***
-	// *** 1. Parse Question Section and mark potential answers
-	// ***
-	for (i=0; i<query->h.numQuestions; i++)						// For each question...
-	{
-		mDNSBool QuestionNeedsMulticastResponse;
-		int NumAnswersForThisQuestion = 0;
-		DNSQuestion *pktq, *q;
-		pktq = tls_mem_alloc(sizeof(DNSQuestion));
-		if (!pktq) goto exit;
-		memset(pktq, 0, sizeof(DNSQuestion));
-		ptr = getQuestion(query, ptr, end, InterfaceID, pktq);	// get the question...
-		if (!ptr) { tls_mem_free(pktq); goto exit; }
-
-		// The only queries that *need* a multicast response are:
-		// * Queries sent via multicast
-		// * from port 5353
-		// * that don't have the kDNSQClass_UnicastResponse bit set
-		// These queries need multicast responses because other clients will:
-		// * suppress their own identical questions when they see these questions, and
-		// * expire their cache records if they don't see the expected responses
-		// For other queries, we may still choose to send the occasional multicast response anyway,
-		// to keep our neighbours caches warm, and for ongoing conflict detection.
-		QuestionNeedsMulticastResponse = QueryWasMulticast && !LegacyQuery && !(pktq->qclass & kDNSQClass_UnicastResponse);
-		// Clear the UnicastResponse flag -- don't want to confuse the rest of the code that follows later
-		pktq->qclass &= ~kDNSQClass_UnicastResponse;
-		
-		// Note: We use the m->CurrentRecord mechanism here because calling ResolveSimultaneousProbe
-		// can result in user callbacks which may change the record list and/or question list.
-		// Also note: we just mark potential answer records here, without trying to build the
-		// "ResponseRecords" list, because we don't want to risk user callbacks deleting records
-		// from that list while we're in the middle of trying to build it.
-		if (m->CurrentRecord) LogMsg("ProcessQuery ERROR m->CurrentRecord already set");
-		m->CurrentRecord = m->ResourceRecords;
-		while (m->CurrentRecord)
-		{
-			rr = m->CurrentRecord;
-			m->CurrentRecord = rr->next;
-			if (ResourceRecordAnswersQuestion(&rr->resrec, pktq))
-			{
-				if (rr->resrec.RecordType == kDNSRecordTypeUnique)
-					ResolveSimultaneousProbe(m, query, end, pktq, rr);
-				else if (ResourceRecordIsValidAnswer(rr))
-				{
-					NumAnswersForThisQuestion++;
-					// Notes:
-					// NR_AnswerTo pointing into query packet means "answer via unicast"
-					//                         (may also choose to do multicast as well)
-					// NR_AnswerTo == ~0 means "definitely answer via multicast" (can't downgrade to unicast later)
-					if (QuestionNeedsMulticastResponse)
-					{
-						// We only mark this question for sending if it is at least one second since the last time we multicast it
-						// on this interface. If it is more than a second, or LastMCInterface is different, then we should multicast it.
-						// This is to guard against the case where someone blasts us with queries as fast as they can.
-						if (m->timenow - (rr->LastMCTime + mDNSPlatformOneSecond) >= 0 ||
-						    (rr->LastMCInterface != mDNSInterfaceMark && rr->LastMCInterface != InterfaceID))
-							rr->NR_AnswerTo = (mDNSu8*)~0;
-					}
-					else if (!rr->NR_AnswerTo) rr->NR_AnswerTo = ptr;
-				}
-			}
-		}
-
-		// We only do the following accelerated cache expiration processing and duplicate question suppression processing
-		// for multicast queries with multicast responses.
-		// For any query generating a unicast response we don't do this because we can't assume we will see the response
-		if (QuestionNeedsMulticastResponse)
-		{
-			CacheRecord *rr;
-			// If we couldn't answer this question, someone else might be able to,
-			// so use random delay on response to reduce collisions
-			if (NumAnswersForThisQuestion == 0) delayresponse = mDNSPlatformOneSecond;	// Divided by 50 = 20ms
-
-			// Make a list indicating which of our own cache records we expect to see updated as a result of this query
-			// Note: Records larger than 1K are not habitually multicast, so don't expect those to be updated
-			for (rr = m->rrcache_hash[HashSlot(&pktq->qname)]; rr; rr=rr->next)
-				if (ResourceRecordAnswersQuestion(&rr->resrec, pktq) && rr->resrec.rdlength <= SmallRecordLimit)
-					if (!rr->NextInKAList && eap != &rr->NextInKAList)
-					{
-						*eap = rr;
-						eap = &rr->NextInKAList;
-						if (rr->MPUnansweredQ == 0 || m->timenow - rr->MPLastUnansweredQT >= mDNSPlatformOneSecond)
-						{
-							// Although MPUnansweredQ is only really used for multi-packet query processing,
-							// we increment it for both single-packet and multi-packet queries, so that it stays in sync
-							// with the MPUnansweredKA value, which by necessity is incremented for both query types.
-							rr->MPUnansweredQ++;
-							rr->MPLastUnansweredQT = m->timenow;
-							rr->MPExpectingKA = mDNStrue;
-						}
-					}
-	
-			// Check if this question is the same as any of mine.
-			// We only do this for non-truncated queries. Right now it would be too complicated to try
-			// to keep track of duplicate suppression state between multiple packets, especially when we
-			// can't guarantee to receive all of the Known Answer packets that go with a particular query.
-			if (!(query->h.flags.b[0] & kDNSFlag0_TC))
-				for (q = m->Questions; q; q=q->next)
-					if (ActiveQuestion(q) && m->timenow - q->LastQTxTime > mDNSPlatformOneSecond / 4)
-						if (!q->InterfaceID || q->InterfaceID == InterfaceID)
-							if (q->NextInDQList == mDNSNULL && dqp != &q->NextInDQList)
-								if (q->qtype == pktq->qtype && q->qclass == pktq->qclass && q->qnamehash == pktq->qnamehash && SameDomainName(&q->qname, &pktq->qname))
-								{ *dqp = q; dqp = &q->NextInDQList; }
-		}
-		tls_mem_free(pktq);
-	}
-
-	// ***
-	// *** 2. Now we can safely build the list of marked answers
-	// ***
-	for (rr = m->ResourceRecords; rr; rr=rr->next)				// Now build our list of potential answers
-		if (rr->NR_AnswerTo)									// If we marked the record...
-			AddRecordToResponseList(&nrp, rr, mDNSNULL);		// ... add it to the list
-
-	// ***
-	// *** 3. Add additional records
-	// ***
-	for (rr=ResponseRecords; rr; rr=rr->NextResponse)			// For each record we plan to put
-	{
-		// (Note: This is an "if", not a "while". If we add a record, we'll find it again
-		// later in the "for" loop, and we will follow further "additional" links then.)
-		if (rr->Additional1 && ResourceRecordIsValidInterfaceAnswer(rr->Additional1, InterfaceID))
-			AddRecordToResponseList(&nrp, rr->Additional1, rr);
-
-		if (rr->Additional2 && ResourceRecordIsValidInterfaceAnswer(rr->Additional2, InterfaceID))
-			AddRecordToResponseList(&nrp, rr->Additional2, rr);
-		
-		// For SRV records, automatically add the Address record(s) for the target host
-		if (rr->resrec.rrtype == kDNSType_SRV)
-			for (rr2=m->ResourceRecords; rr2; rr2=rr2->next)					// Scan list of resource records
-				if (RRIsAddressType(rr2) &&										// For all address records (A/AAAA) ...
-				    ResourceRecordIsValidInterfaceAnswer(rr2, InterfaceID) &&	// ... which are valid for answer ...
-				    rr->resrec.rdnamehash == rr2->resrec.namehash &&
-				    SameDomainName(&rr->resrec.rdata->u.srv.target, &rr2->resrec.name))		// ... whose name is the name of the SRV target
-					AddRecordToResponseList(&nrp, rr2, rr);
-	}
-
-	// ***
-	// *** 4. Parse Answer Section and cancel any records disallowed by Known-Answer list
-	// ***
-	for (i=0; i<query->h.numAnswers; i++)						// For each record in the query's answer section...
-	{
-		// Get the record...
-		LargeCacheRecord *pkt;
-		AuthRecord *rr;
-		CacheRecord *ourcacherr;
-		pkt = tls_mem_alloc(sizeof(LargeCacheRecord));
-		if (!pkt) goto exit;
-		memset(pkt, 0, sizeof(LargeCacheRecord));
-		ptr = GetLargeResourceRecord(m, query, ptr, end, InterfaceID, kDNSRecordTypePacketAns, pkt);
-		if (!ptr) { tls_mem_free(pkt); goto exit; }
-
-		// See if this Known-Answer suppresses any of our currently planned answers
-		for (rr=ResponseRecords; rr; rr=rr->NextResponse)
-			if (MustSendRecord(rr) && ShouldSuppressKnownAnswer(&pkt->r, rr))
-			{ rr->NR_AnswerTo = mDNSNULL; rr->NR_AdditionalTo = mDNSNULL; }
-
-		// See if this Known-Answer suppresses any previously scheduled answers (for multi-packet KA suppression)
-		for (rr=m->ResourceRecords; rr; rr=rr->next)
-		{
-			// If we're planning to send this answer on this interface, and only on this interface, then allow KA suppression
-			if (rr->ImmedAnswer == InterfaceID && ShouldSuppressKnownAnswer(&pkt->r, rr))
-			{
-				if (srcaddr->type == mDNSAddrType_IPv4)
-				{
-					if (mDNSSameIPv4Address(rr->v4Requester, srcaddr->ip.v4)) rr->v4Requester = zeroIPAddr;
-				}
-				else if (srcaddr->type == mDNSAddrType_IPv6)
-				{
-					if (mDNSSameIPv6Address(rr->v6Requester, srcaddr->ip.v6)) rr->v6Requester = zerov6Addr;
-				}
-				if (mDNSIPv4AddressIsZero(rr->v4Requester) && mDNSIPv6AddressIsZero(rr->v6Requester)) rr->ImmedAnswer = mDNSNULL;
-			}
-		}
-
-		// See if this Known-Answer suppresses any answers we were expecting for our cache records. We do this always,
-		// even if the TC bit is not set (the TC bit will *not* be set in the *last* packet of a multi-packet KA list).
-		ourcacherr = FindIdenticalRecordInCache(m, &pkt->r.resrec);
-		if (ourcacherr && ourcacherr->MPExpectingKA && m->timenow - ourcacherr->MPLastUnansweredQT < mDNSPlatformOneSecond)
-		{
-			ourcacherr->MPUnansweredKA++;
-			ourcacherr->MPExpectingKA = mDNSfalse;
-		}
-
-		// Having built our ExpectedAnswers list from the questions in this packet, we can definitively
-		// remove from our ExpectedAnswers list any records that are suppressed in the very same packet.
-		// For answers that are suppressed in subsequent KA list packets, we rely on the MPQ/MPKA counting to track them.
-		eap = &ExpectedAnswers;
-		while (*eap)
-		{
-			CacheRecord *rr = *eap;
-			if (rr->resrec.InterfaceID == InterfaceID && IdenticalResourceRecord(&pkt->r.resrec, &rr->resrec))
-			{ *eap = rr->NextInKAList; rr->NextInKAList = mDNSNULL; }
-			else eap = &rr->NextInKAList;
-		}
-		
-		// See if this Known-Answer is a surprise to us. If so, we shouldn't suppress our own query.
-		if (!ourcacherr)
-		{
-			dqp = &DupQuestions;
-			while (*dqp)
-			{
-				DNSQuestion *q = *dqp;
-				if (ResourceRecordAnswersQuestion(&pkt->r.resrec, q))
-				{ *dqp = q->NextInDQList; q->NextInDQList = mDNSNULL; }
-				else dqp = &q->NextInDQList;
-			}
-		}
-		tls_mem_free(pkt);
-	}
-
-	// ***
-	// *** 5. Cancel any additionals that were added because of now-deleted records
-	// ***
-	for (rr=ResponseRecords; rr; rr=rr->NextResponse)
-		if (rr->NR_AdditionalTo && !MustSendRecord(rr->NR_AdditionalTo))
-		{ rr->NR_AnswerTo = mDNSNULL; rr->NR_AdditionalTo = mDNSNULL; }
-
-	// ***
-	// *** 6. Mark the send flags on the records we plan to send
-	// ***
-	for (rr=ResponseRecords; rr; rr=rr->NextResponse)
-	{
-		if (rr->NR_AnswerTo)
-		{
-			mDNSBool SendMulticastResponse = mDNSfalse;
-			
-			// If it's been a while since we multicast this, then send a multicast response for conflict detection, etc.
-			if (m->timenow - (rr->LastMCTime + TicksTTL(rr)/4) >= 0) SendMulticastResponse = mDNStrue;
-			
-			// If the client insists on a multicast response, then we'd better send one
-			if (rr->NR_AnswerTo == (mDNSu8*)~0) SendMulticastResponse = mDNStrue;
-			else if (rr->NR_AnswerTo) HaveUnicastAnswer = mDNStrue;
-	
-			if (SendMulticastResponse)
-			{
-				// If we're already planning to send this on another interface, just send it on all interfaces
-				if (rr->ImmedAnswer && rr->ImmedAnswer != InterfaceID)
-				{
-					rr->ImmedAnswer = mDNSInterfaceMark;
-					m->NextScheduledResponse = m->timenow;
-					debugf("ProcessQuery: %##s (%s) : Will send on all interfaces", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-				}
-				else
-				{
-					rr->ImmedAnswer = InterfaceID;			// Record interface to send it on
-					m->NextScheduledResponse = m->timenow;
-					if (srcaddr->type == mDNSAddrType_IPv4)
-					{
-						if      (mDNSIPv4AddressIsZero(rr->v4Requester))                rr->v4Requester = srcaddr->ip.v4;
-						else if (!mDNSSameIPv4Address(rr->v4Requester, srcaddr->ip.v4)) rr->v4Requester = onesIPv4Addr;
-					}
-					else if (srcaddr->type == mDNSAddrType_IPv6)
-					{
-						if      (mDNSIPv6AddressIsZero(rr->v6Requester))                rr->v6Requester = srcaddr->ip.v6;
-						else if (!mDNSSameIPv6Address(rr->v6Requester, srcaddr->ip.v6)) rr->v6Requester = onesIPv6Addr;
-					}
-				}
-			}
-			if (rr->resrec.RecordType == kDNSRecordTypeShared)
-			{
-				if (query->h.flags.b[0] & kDNSFlag0_TC) delayresponse = mDNSPlatformOneSecond * 20;	// Divided by 50 = 400ms
-				else                                    delayresponse = mDNSPlatformOneSecond;		// Divided by 50 = 20ms
-			}
-		}
-		else if (rr->NR_AdditionalTo && rr->NR_AdditionalTo->NR_AnswerTo == (mDNSu8*)~0)
-		{
-			// Since additional records are an optimization anyway, we only ever send them on one interface at a time
-			// If two clients on different interfaces do queries that invoke the same optional additional answer,
-			// then the earlier client is out of luck
-			rr->ImmedAdditional = InterfaceID;
-			// No need to set m->NextScheduledResponse here
-			// We'll send these additional records when we send them, or not, as the case may be
-		}
-	}
-
-	// ***
-	// *** 7. If we think other machines are likely to answer these questions, set our packet suppression timer
-	// ***
-	if (delayresponse && (!m->SuppressSending || (m->SuppressSending - m->timenow) < (delayresponse + 49) / 50))
-	{
-		// Pick a random delay:
-		// We start with the base delay chosen above (typically either 1 second or 20 seconds),
-		// and add a random value in the range 0-5 seconds (making 1-6 seconds or 20-25 seconds).
-		// This is an integer value, with resolution determined by the platform clock rate.
-		// We then divide that by 50 to get the delay value in ticks. We defer the division until last
-		// to get better results on platforms with coarse clock granularity (e.g. ten ticks per second).
-		// The +49 before dividing is to ensure we round up, not down, to ensure that even
-		// on platforms where the native clock rate is less than fifty ticks per second,
-		// we still guarantee that the final calculated delay is at least one platform tick.
-		// We want to make sure we don't ever allow the delay to be zero ticks,
-		// because if that happens we'll fail the Rendezvous Conformance Test.
-		// Our final computed delay is 20-120ms for normal delayed replies,
-		// or 400-500ms in the case of multi-packet known-answer lists.
-		m->SuppressSending = m->timenow + (delayresponse + (mDNSs32)mDNSRandom((mDNSu32)mDNSPlatformOneSecond*5) + 49) / 50;
-		if (m->SuppressSending == 0) m->SuppressSending = 1;
-	}
-
-	// ***
-	// *** 8. If query is from a legacy client, generate a unicast response too
-	// ***
-	if (HaveUnicastAnswer)
-		responseptr = GenerateUnicastResponse(query, end, InterfaceID, LegacyQuery, response, ResponseRecords);
-
- exit:
-	// ***
-	// *** 9. Finally, clear our link chains ready for use next time
-	// ***
-	while (ResponseRecords)
-	{
-		rr = ResponseRecords;
-		ResponseRecords = rr->NextResponse;
-		rr->NextResponse    = mDNSNULL;
-		rr->NR_AnswerTo     = mDNSNULL;
-		rr->NR_AdditionalTo = mDNSNULL;
-	}
-	
-	while (ExpectedAnswers)
-	{
-		CacheRecord *rr;
-		rr = ExpectedAnswers;
-		ExpectedAnswers = rr->NextInKAList;
-		rr->NextInKAList = mDNSNULL;
-		
-		// For non-truncated queries, we can definitively say that we should expect
-		// to be seeing a response for any records still left in the ExpectedAnswers list
-		if (!(query->h.flags.b[0] & kDNSFlag0_TC))
-			if (rr->UnansweredQueries == 0 || m->timenow - rr->LastUnansweredTime >= mDNSPlatformOneSecond)
-			{
-				rr->UnansweredQueries++;
-				rr->LastUnansweredTime = m->timenow;
-				if (rr->UnansweredQueries > 1)
-					debugf("ProcessQuery: (!TC) UAQ %lu MPQ %lu MPKA %lu %s",
-					       rr->UnansweredQueries, rr->MPUnansweredQ, rr->MPUnansweredKA, GetRRDisplayString(m, rr));
-				SetNextCacheCheckTime(m, rr);
-			}
-
-		// If we've seen multiple unanswered queries for this record,
-		// then mark it to expire in five seconds if we don't get a response by then.
-		if (rr->UnansweredQueries >= MaxUnansweredQueries)
-		{
-			// Only show debugging message if this record was not about to expire anyway
-			if (RRExpireTime(rr) - m->timenow > 4 * mDNSPlatformOneSecond)
-				debugf("ProcessQuery: (Max) UAQ %lu MPQ %lu MPKA %lu mDNS_Reconfirm() for %s",
-				       rr->UnansweredQueries, rr->MPUnansweredQ, rr->MPUnansweredKA, GetRRDisplayString(m, rr));
-			mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForNoAnswer);
-		}
-		// Make a guess, based on the multi-packet query / known answer counts, whether we think we
-		// should have seen an answer for this. (We multiply MPQ by 4 and MPKA by 5, to allow for
-		// possible packet loss of up to 20% of the additional KA packets.)
-		else if (rr->MPUnansweredQ * 4 > rr->MPUnansweredKA * 5 + 8)
-		{
-			// We want to do this conservatively.
-			// If there are so many machines on the network that they have to use multi-packet known-answer lists,
-			// then we don't want them to all hit the network simultaneously with their final expiration queries.
-			// By setting the record to expire in four minutes, we achieve two things:
-			// (a) the 90-95% final expiration queries will be less bunched together
-			// (b) we allow some time for us to witness enough other failed queries that we don't have to do our own
-			mDNSu32 remain = (mDNSu32)(RRExpireTime(rr) - m->timenow) / 4;
-			if (remain > 240 * (mDNSu32)mDNSPlatformOneSecond)
-				remain = 240 * (mDNSu32)mDNSPlatformOneSecond;
-			
-			// Only show debugging message if this record was not about to expire anyway
-			if (RRExpireTime(rr) - m->timenow > 4 * mDNSPlatformOneSecond)
-				debugf("ProcessQuery: (MPQ) UAQ %lu MPQ %lu MPKA %lu mDNS_Reconfirm() for %s",
-				       rr->UnansweredQueries, rr->MPUnansweredQ, rr->MPUnansweredKA, GetRRDisplayString(m, rr));
-
-			if (remain <= 60 * (mDNSu32)mDNSPlatformOneSecond)
-				rr->UnansweredQueries++;	// Treat this as equivalent to one definite unanswered query
-			rr->MPUnansweredQ  = 0;			// Clear MPQ/MPKA statistics
-			rr->MPUnansweredKA = 0;
-			rr->MPExpectingKA  = mDNSfalse;
-			
-			if (remain < kDefaultReconfirmTimeForNoAnswer)
-				remain = kDefaultReconfirmTimeForNoAnswer;
-			mDNS_Reconfirm_internal(m, rr, remain);
-		}
-	}
-	
-	while (DupQuestions)
-	{
-#if MDNS_DEBUGMSGS
-		int i;
-#endif
-		DNSQuestion *q = DupQuestions;
-		DupQuestions = q->NextInDQList;
-		q->NextInDQList = mDNSNULL;
-		i = RecordDupSuppressInfo(q->DupSuppress, m->timenow, InterfaceID, srcaddr->type);
-		debugf("ProcessQuery: Recorded DSI for %##s (%s) on %p/%s %d", q->qname.c, DNSTypeName(q->qtype), InterfaceID,
-		       srcaddr->type == mDNSAddrType_IPv4 ? "v4" : "v6", i);
-	}
-
-	return(responseptr);
-}
-
-mDNSlocal void mDNSCoreReceiveQuery(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end,
-				    const mDNSAddr *srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, mDNSIPPort dstport,
-				    const mDNSInterfaceID InterfaceID)
-{
-	DNSMessage    *response;
-	const mDNSu8 *responseend    = mDNSNULL;
-	
-	verbosedebugf("Received Query from %#-15a:%d to %#-15a:%d on 0x%.8X with %2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s",
-		      srcaddr, (mDNSu16)srcport.b[0]<<8 | srcport.b[1],
-		      dstaddr, (mDNSu16)dstport.b[0]<<8 | dstport.b[1],
-		      InterfaceID,
-		      msg->h.numQuestions,   msg->h.numQuestions   == 1 ? ", " : "s,",
-		      msg->h.numAnswers,     msg->h.numAnswers     == 1 ? ", " : "s,",
-		      msg->h.numAuthorities, msg->h.numAuthorities == 1 ? "y,  " : "ies,",
-		      msg->h.numAdditionals, msg->h.numAdditionals == 1 ? "" : "s");
-
-	response = tls_mem_alloc(sizeof(DNSMessage));
-	if(!response) return;
-	responseend = ProcessQuery(m, msg, end, srcaddr, InterfaceID,
-				   (srcport.NotAnInteger != MulticastDNSPort.NotAnInteger), mDNSAddrIsDNSMulticast(dstaddr), response);
-
-	if (responseend)	// If responseend is non-null, that means we built a unicast response packet
-	{
-		debugf("Unicast Response: %d Question%s, %d Answer%s, %d Additional%s to %#-15a:%d on %p/%ld",
-		       response->h.numQuestions,   response->h.numQuestions   == 1 ? "" : "s",
-		       response->h.numAnswers,     response->h.numAnswers     == 1 ? "" : "s",
-		       response->h.numAdditionals, response->h.numAdditionals == 1 ? "" : "s",
-		       srcaddr, (mDNSu16)srcport.b[0]<<8 | srcport.b[1], InterfaceID, srcaddr->type);
-		mDNSSendDNSMessage(m, response, responseend, InterfaceID, dstport, srcaddr, srcport);
-	}
-	tls_mem_free(response);
-}
-
-// NOTE: mDNSCoreReceiveResponse calls mDNS_Deregister_internal which can call a user callback, which may change
-// the record list and/or question list.
-// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
-mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
-				       const DNSMessage *const response, const mDNSu8 *end, const mDNSAddr *srcaddr, const mDNSAddr *dstaddr,
-				       const mDNSInterfaceID InterfaceID, mDNSu8 ttl)
-{
-	int i;
-	const mDNSu8 *ptr = LocateAnswers(response, end);	// We ignore questions (if any) in a DNS response packet
-	CacheRecord *CacheFlushRecords = mDNSNULL;
-	CacheRecord **cfp = &CacheFlushRecords;
-		
-	// All records in a DNS response packet are treated as equally valid statements of truth. If we want
-	// to guard against spoof responses, then the only credible protection against that is cryptographic
-	// security, e.g. DNSSEC., not worring about which section in the spoof packet contained the record
-	int totalrecords = response->h.numAnswers + response->h.numAuthorities + response->h.numAdditionals;
-
-	(void)srcaddr;	// Currently used only for display in debugging message
-
-	verbosedebugf("Received Response from %#-15a addressed to %#-15a on %p TTL %d with %2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s",
-		      srcaddr, dstaddr, InterfaceID, ttl,
-		      response->h.numQuestions,   response->h.numQuestions   == 1 ? ", " : "s,",
-		      response->h.numAnswers,     response->h.numAnswers     == 1 ? ", " : "s,",
-		      response->h.numAuthorities, response->h.numAuthorities == 1 ? "y,  " : "ies,",
-		      response->h.numAdditionals, response->h.numAdditionals == 1 ? "" : "s");
-
-	// TTL should be 255
-	// In the case of overlayed subnets that aren't using RFC 3442, some packets may incorrectly
-	// go to the router first and then come back with a TTL of 254, so we allow that too.
-	// Anything lower than 254 is a pretty good sign of an off-net spoofing attack.
-	// Also, if we get a unicast response when we weren't expecting one, then we assume it is someone trying to spoof us
-	if (ttl < 254 || (!mDNSAddrIsDNSMulticast(dstaddr) && (mDNSu32)(m->timenow - m->ExpectUnicastResponse) > (mDNSu32)mDNSPlatformOneSecond))
-	{
-		debugf("** Ignored apparent spoof mDNS Response from %#-15a to %#-15a TTL %d on %p with %2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s",
-		       srcaddr, dstaddr, ttl, InterfaceID,
-		       response->h.numQuestions,   response->h.numQuestions   == 1 ? ", " : "s,",
-		       response->h.numAnswers,     response->h.numAnswers     == 1 ? ", " : "s,",
-		       response->h.numAuthorities, response->h.numAuthorities == 1 ? "y,  " : "ies,",
-		       response->h.numAdditionals, response->h.numAdditionals == 1 ? "" : "s");
-		return;
-	}
-
-	for (i = 0; i < totalrecords && ptr && ptr < end; i++)
-	{
-		LargeCacheRecord *pkt = tls_mem_alloc(sizeof(LargeCacheRecord));
-		const mDNSu8 RecordType = (mDNSu8)((i < response->h.numAnswers) ? kDNSRecordTypePacketAns : kDNSRecordTypePacketAdd);
-		if (!pkt) break;
-		memset(pkt, 0, sizeof(LargeCacheRecord));
-		ptr = GetLargeResourceRecord(m, response, ptr, end, InterfaceID, RecordType, pkt);
-		if (!ptr) { tls_mem_free(pkt); break; }		// Break out of the loop and clean up our CacheFlushRecords list before exiting
-
-		// 1. Check that this packet resource record does not conflict with any of ours
-		if (m->CurrentRecord) LogMsg("mDNSCoreReceiveResponse ERROR m->CurrentRecord already set");
-		m->CurrentRecord = m->ResourceRecords;
-		while (m->CurrentRecord)
-		{
-			AuthRecord *rr = m->CurrentRecord;
-			m->CurrentRecord = rr->next;
-			if (PacketRRMatchesSignature(&pkt->r, rr))		// If interface, name, type (if verified) and class match...
-			{
-				// ... check to see if rdata is identical
-				if (SameRData(&pkt->r.resrec, &rr->resrec))
-				{
-					// If the RR in the packet is identical to ours, just check they're not trying to lower the TTL on us
-					if (pkt->r.resrec.rroriginalttl >= rr->resrec.rroriginalttl/2 || m->SleepState)
-					{
-						// If we were planning to send on this -- and only this -- interface, then we don't need to any more
-						if (rr->ImmedAnswer == InterfaceID) rr->ImmedAnswer = mDNSNULL;
-					}
-					else
-					{
-						if      (rr->ImmedAnswer == mDNSNULL)    { rr->ImmedAnswer = InterfaceID;       m->NextScheduledResponse = m->timenow; }
-						else if (rr->ImmedAnswer != InterfaceID) { rr->ImmedAnswer = mDNSInterfaceMark; m->NextScheduledResponse = m->timenow; }
-					}
-				}
-				else
-				{
-					// else, the packet RR has different rdata -- check to see if this is a conflict
-					if (pkt->r.resrec.rroriginalttl > 0 && PacketRRConflict(m, rr, &pkt->r))
-					{
-						debugf("mDNSCoreReceiveResponse: Our Record: %08X %08X %s", rr->  resrec.rdatahash, rr->  resrec.rdnamehash, GetRRDisplayString(m, rr));
-						debugf("mDNSCoreReceiveResponse: Pkt Record: %08X %08X %s", pkt->r.resrec.rdatahash, pkt->r.resrec.rdnamehash, GetRRDisplayString(m, &pkt->r));
-
-						// If this record is marked DependentOn another record for conflict detection purposes,
-						// then *that* record has to be bumped back to probing state to resolve the conflict
-						while (rr->DependentOn) rr = rr->DependentOn;
-
-						// If we've just whacked this record's ProbeCount, don't need to do it again
-						if (rr->ProbeCount <= DefaultProbeCountForTypeUnique)
-						{
-							// If we'd previously verified this record, put it back to probing state and try again
-							if (rr->resrec.RecordType == kDNSRecordTypeVerified)
-							{
-								debugf("mDNSCoreReceiveResponse: Reseting to Probing: %##s (%s)", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-								rr->resrec.RecordType     = kDNSRecordTypeUnique;
-								rr->ProbeCount     = DefaultProbeCountForTypeUnique + 1;
-								rr->ThisAPInterval = DefaultAPIntervalForRecordType(kDNSRecordTypeUnique);
-								InitializeLastAPTime(m, rr);
-								RecordProbeFailure(m, rr);	// Repeated late conflicts also cause us to back off to the slower probing rate
-							}
-							// If we're probing for this record, we just failed
-							else if (rr->resrec.RecordType == kDNSRecordTypeUnique)
-							{
-								debugf("mDNSCoreReceiveResponse: Will rename %##s (%s)", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-								mDNS_Deregister_internal(m, rr, mDNS_Dereg_conflict);
-							}
-							// We assumed this record must be unique, but we were wrong.
-							// (e.g. There are two mDNSResponders on the same machine giving
-							// different answers for the reverse mapping record.)
-							// This is simply a misconfiguration, and we don't try to recover from it.
-							else if (rr->resrec.RecordType == kDNSRecordTypeKnownUnique)
-							{
-								debugf("mDNSCoreReceiveResponse: Unexpected conflict on %##s (%s) -- discarding our record",
-								       rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-								mDNS_Deregister_internal(m, rr, mDNS_Dereg_conflict);
-							}
-							else
-								debugf("mDNSCoreReceiveResponse: Unexpected record type %X %##s (%s)",
-								       rr->resrec.RecordType, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
-						}
-					}
-					// Else, matching signature, different rdata, but not a considered a conflict.
-					// If the packet record has the cache-flush bit set, then we check to see if we have to re-assert our record(s)
-					// to rescue them (see note about "multi-homing and bridged networks" at the end of this function).
-					else if ((pkt->r.resrec.RecordType & kDNSRecordTypePacketUniqueMask) && m->timenow - rr->LastMCTime > mDNSPlatformOneSecond/2)
-					{ rr->ImmedAnswer = mDNSInterfaceMark; m->NextScheduledResponse = m->timenow; }
-				}
-			}
-		}
-
-		// 2. See if we want to add this packet resource record to our cache
-		if (m->rrcache_size)	// Only try to cache answers if we have a cache to put them in
-		{
-			mDNSu32 slot = HashSlot(&pkt->r.resrec.name);
-			CacheRecord *rr;
-			// 2a. Check if this packet resource record is already in our cache
-			for (rr = m->rrcache_hash[slot]; rr; rr=rr->next)
-			{
-				// If we found this exact resource record, refresh its TTL
-				if (rr->resrec.InterfaceID == InterfaceID && IdenticalResourceRecord(&pkt->r.resrec, &rr->resrec))
-				{
-					if (pkt->r.resrec.rdlength > InlineCacheRDSize)
-						verbosedebugf("Found record size %5d interface %p already in cache: %s",
-							      pkt->r.resrec.rdlength, InterfaceID, GetRRDisplayString(m, &pkt->r));
-					rr->TimeRcvd  = m->timenow;
-					
-					if (pkt->r.resrec.RecordType & kDNSRecordTypePacketUniqueMask)
-					{
-						// If this packet record has the kDNSClass_UniqueRRSet flag set, then add it to our cache flushing list
-						if (rr->NextInCFList == mDNSNULL && cfp != &rr->NextInCFList)
-						{ *cfp = rr; cfp = &rr->NextInCFList; }
-
-						// If this packet record is marked unique, and our previous cached copy was not, then fix it
-						if (!(rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask))
-						{
-							DNSQuestion *q;
-							for (q = m->Questions; q; q=q->next) if (ResourceRecordAnswersQuestion(&rr->resrec, q)) q->UniqueAnswers++;
-							rr->resrec.RecordType = pkt->r.resrec.RecordType;
-						}
-					}
-
-					if (pkt->r.resrec.rroriginalttl > 0)
-					{
-						rr->resrec.rroriginalttl = pkt->r.resrec.rroriginalttl;
-						rr->UnansweredQueries = 0;
-						rr->MPUnansweredQ     = 0;
-						rr->MPUnansweredKA    = 0;
-						rr->MPExpectingKA     = mDNSfalse;
-					}
-					else
-					{
-						// If the packet TTL is zero, that means we're deleting this record.
-						// To give other hosts on the network a chance to protest, we push the deletion
-						// out one second into the future. Also, we set UnansweredQueries to MaxUnansweredQueries.
-						// Otherwise, we'll do final queries for this record at 80% and 90% of its apparent
-						// lifetime (800ms and 900ms from now) which is a pointless waste of network bandwidth.
-						rr->resrec.rroriginalttl = 1;
-						rr->UnansweredQueries = MaxUnansweredQueries;
-					}
-					SetNextCacheCheckTime(m, rr);
-					break;
-				}
-			}
-
-			// If packet resource record not in our cache, add it now
-			// (unless it is just a deletion of a record we never had, in which case we don't care)
-			if (!rr && pkt->r.resrec.rroriginalttl > 0)
-			{
-				rr = GetFreeCacheRR(m, pkt->r.resrec.rdlength);
-				if (!rr) debugf("No cache space to add record for %#s", pkt->r.resrec.name.c);
-				else
-				{
-					RData *saveptr = rr->resrec.rdata;		// Save the rr->resrec.rdata pointer
-					*rr = pkt->r;
-					rr->resrec.rdata = saveptr;			// and then restore it after the structure assignment
-					
-					if (rr->resrec.RecordType & kDNSRecordTypePacketUniqueMask)
-					{ *cfp = rr; cfp = &rr->NextInCFList; }
-					// If this is an oversized record with external storage allocated, copy rdata to external storage
-					if (pkt->r.resrec.rdlength > InlineCacheRDSize)
-						mDNSPlatformMemCopy(pkt->r.resrec.rdata, rr->resrec.rdata, sizeofRDataHeader + pkt->r.resrec.rdlength);
-					rr->next = mDNSNULL;					// Clear 'next' pointer
-					*(m->rrcache_tail[slot]) = rr;			// Append this record to tail of cache slot list
-					m->rrcache_tail[slot] = &(rr->next);	// Advance tail pointer
-					m->rrcache_used[slot]++;
-					//debugf("Adding RR %##s to cache (%d)", pkt.r.name.c, m->rrcache_used);
-					memcpy(&rr->resrec.addr,srcaddr,sizeof(mDNSAddr)); // Shiro, I want to keep sender IP
-					CacheRecordAdd(m, rr);
-					// MUST do this AFTER CacheRecordAdd(), because that's what sets CRActiveQuestion for us
-					SetNextCacheCheckTime(m, rr);
-				}
-			}
-		}
-		tls_mem_free(pkt);
-	}
-
-	// If we've just received one or more records with their cache flush bits set,
-	// then scan that cache slot to see if there are any old stale records we need to flush
-	while (CacheFlushRecords)
-	{
-		CacheRecord *r1 = CacheFlushRecords, *r2;
-		CacheFlushRecords = CacheFlushRecords->NextInCFList;
-		r1->NextInCFList = mDNSNULL;
-		for (r2 = m->rrcache_hash[HashSlot(&r1->resrec.name)]; r2; r2=r2->next)
-			if (SameResourceRecordSignature(&r1->resrec, &r2->resrec) && m->timenow - r2->TimeRcvd > mDNSPlatformOneSecond)
-			{
-				verbosedebugf("Cache flush %p X %p %##s (%s)", r1, r2, r2->resrec.name.c, DNSTypeName(r2->resrec.rrtype));
-				// We set stale records to expire in one second.
-				// This gives the owner a chance to rescue it if necessary.
-				// This is important in the case of multi-homing and bridged networks:
-				//   Suppose host X is on Ethernet. X then connects to an AirPort base station, which happens to be
-				//   bridged onto the same Ethernet. When X announces its AirPort IP address with the cache-flush bit
-				//   set, the AirPort packet will be bridged onto the Ethernet, and all other hosts on the Ethernet
-				//   will promptly delete their cached copies of the (still valid) Ethernet IP address record.
-				//   By delaying the deletion by one second, we give X a change to notice that this bridging has
-				//   happened, and re-announce its Ethernet IP address to rescue it from deletion from all our caches.
-				// We set UnansweredQueries to MaxUnansweredQueries to avoid expensive and unnecessary
-				// final expiration queries for this record.
-				r2->resrec.rroriginalttl = 1;
-				r2->TimeRcvd          = m->timenow;
-				r2->UnansweredQueries = MaxUnansweredQueries;
-				SetNextCacheCheckTime(m, r2);
-			}
-	}
-}
-
-mDNSexport void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end,
-				const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *const dstaddr, const mDNSIPPort dstport,
-				const mDNSInterfaceID InterfaceID, mDNSu8 ttl)
-{
-	const mDNSu8 StdQ  = kDNSFlag0_QR_Query    | kDNSFlag0_OP_StdQuery;
-	const mDNSu8 StdR  = kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery;
-	const mDNSu8 QR_OP = (mDNSu8)(msg->h.flags.b[0] & kDNSFlag0_QROP_Mask);
-	
-	// Read the integer parts which are in IETF byte-order (MSB first, LSB second)
-	mDNSu8 *ptr = (mDNSu8 *)&msg->h.numQuestions;
-	msg->h.numQuestions   = (mDNSu16)((mDNSu16)ptr[0] <<  8 | ptr[1]);
-	msg->h.numAnswers     = (mDNSu16)((mDNSu16)ptr[2] <<  8 | ptr[3]);
-	msg->h.numAuthorities = (mDNSu16)((mDNSu16)ptr[4] <<  8 | ptr[5]);
-	msg->h.numAdditionals = (mDNSu16)((mDNSu16)ptr[6] <<  8 | ptr[7]);
-	
-	if (!m) { LogMsg("mDNSCoreReceive ERROR m is NULL"); return; }
-	
-	// We use zero addresses and all-ones addresses at various places in the code to indicate special values like "no address"
-	// If we accept and try to process a packet with zero or all-ones source address, that could really mess things up
-	if (!mDNSAddressIsValid(srcaddr)) { debugf("mDNSCoreReceive ignoring packet from %#a", srcaddr); return; }
-	
-	mDNS_Lock(m);
-	if      (QR_OP == StdQ) mDNSCoreReceiveQuery   (m, msg, end, srcaddr, srcport, dstaddr, dstport, InterfaceID);
-	else if (QR_OP == StdR) mDNSCoreReceiveResponse(m, msg, end, srcaddr,          dstaddr,          InterfaceID, ttl);
-	else debugf("Unknown DNS packet type %02X%02X (ignored)", msg->h.flags.b[0], msg->h.flags.b[1]);
-
-	// Packet reception often causes a change to the task list:
-	// 1. Inbound queries can cause us to need to send responses
-	// 2. Conflicing response packets received from other hosts can cause us to need to send defensive responses
-	// 3. Other hosts announcing deletion of shared records can cause us to need to re-assert those records
-	// 4. Response packets that answer questions may cause our client to issue new questions
-	mDNS_Unlock(m);
-}
-
-// ***************************************************************************
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark -
-#pragma mark - Searcher Functions
-#endif
-#if 0
-mDNSlocal DNSQuestion *FindDuplicateQuestion(const mDNS *const m, const DNSQuestion *const question)
-{
-	DNSQuestion *q;
-	// Note: A question can only be marked as a duplicate of one that occurs *earlier* in the list.
-	// This prevents circular references, where two questions are each marked as a duplicate of the other.
-	// Accordingly, we break out of the loop when we get to 'question', because there's no point searching
-	// further in the list.
-	for (q = m->Questions; q && q != question; q=q->next)		// Scan our list of questions
-		if (q->InterfaceID == question->InterfaceID &&			// for another question with the same InterfaceID,
-		    q->qtype       == question->qtype       &&			// type,
-		    q->qclass      == question->qclass      &&			// class,
-		    q->qnamehash   == question->qnamehash   &&
-		    SameDomainName(&q->qname, &question->qname))		// and name
-			return(q);
-	return(mDNSNULL);
-}
-
-// This is called after a question is deleted, in case other identical questions were being
-// suppressed as duplicates
-mDNSlocal void UpdateQuestionDuplicates(mDNS *const m, const DNSQuestion *const question)
-{
-	DNSQuestion *q;
-	for (q = m->Questions; q; q=q->next)		// Scan our list of questions
-		if (q->DuplicateOf == question)			// To see if any questions were referencing this as their duplicate
-		{
-			q->ThisQInterval = question->ThisQInterval;
-			q->LastQTime     = question->LastQTime;
-			q->RecentAnswers = 0;
-			q->DuplicateOf   = FindDuplicateQuestion(m, q);
-			q->LastQTxTime   = question->LastQTxTime;
-			SetNextQueryTime(m,q);
-		}
-}
-
-mDNSlocal mStatus mDNS_StartQuery_internal(mDNS *const m, DNSQuestion *const question)
-{
-#if TEST_LOCALONLY_FOR_EVERYTHING
-	question->InterfaceID = (mDNSInterfaceID)~0;
-#endif
-	if (m->rrcache_size == 0)	// Can't do queries if we have no cache space allocated
-		return(mStatus_NoCache);
-	else
-	{
-		int i;
-		// Note: It important that new questions are appended at the *end* of the list, not prepended at the start
-		DNSQuestion **q = &m->Questions;
-		if (question->InterfaceID == ((mDNSInterfaceID)~0)) q = &m->LocalOnlyQuestions;
-		while (*q && *q != question) q=&(*q)->next;
-
-		if (*q)
-		{
-			LogMsg("Error! Tried to add a question %##s (%s) that's already in the active list",
-			       question->qname.c, DNSTypeName(question->qtype));
-			return(mStatus_AlreadyRegistered);
-		}
-
-		// If this question is referencing a specific interface, make sure it exists
-		if (question->InterfaceID && question->InterfaceID != ((mDNSInterfaceID)~0))
-		{
-			NetworkInterfaceInfo *intf;
-			for (intf = m->HostInterfaces; intf; intf = intf->next)
-				if (intf->InterfaceID == question->InterfaceID) break;
-			if (!intf)
-			{
-				debugf("mDNS_StartQuery_internal: Question %##s InterfaceID %p not found", question->qname.c, question->InterfaceID);
-				return(mStatus_BadReferenceErr);
-			}
-		}
-
-		// Note: In the case where we already have the answer to this question in our cache, that may be all the client
-		// wanted, and they may immediately cancel their question. In this case, sending an actual query on the wire would
-		// be a waste. For that reason, we schedule our first query to go out in half a second. If AnswerNewQuestion() finds
-		// that we have *no* relevant answers currently in our cache, then it will accelerate that to go out immediately.
-		if (!ValidateDomainName(&question->qname))
-		{
-			LogMsg("Attempt to start query with invalid qname %##s %s", question->qname.c, DNSTypeName(question->qtype));
-			return(mStatus_Invalid);
-		}
-
-		if (!m->RandomQueryDelay) m->RandomQueryDelay = 1 + (mDNSs32)mDNSRandom((mDNSu32)InitialQuestionInterval);
-
-		question->next           = mDNSNULL;
-		question->qnamehash      = DomainNameHashValue(&question->qname);	// MUST do this before FindDuplicateQuestion()
-		question->ThisQInterval  = InitialQuestionInterval * 2;				// MUST be > zero for an active question
-		question->LastQTime      = m->timenow - m->RandomQueryDelay;		// Avoid inter-machine synchronization
-		question->RecentAnswers  = 0;
-		question->CurrentAnswers = 0;
-		question->LargeAnswers   = 0;
-		question->UniqueAnswers  = 0;
-		question->DuplicateOf    = FindDuplicateQuestion(m, question);
-		question->NextInDQList   = mDNSNULL;
-		for (i=0; i<DupSuppressInfoSize; i++)
-			question->DupSuppress[i].InterfaceID = mDNSNULL;
-		// question->InterfaceID must be already set by caller
-		question->SendQNow       = mDNSNULL;
-		question->SendOnAll      = mDNSfalse;
-		question->LastQTxTime    = m->timenow;
-
-		if (!question->DuplicateOf)
-			verbosedebugf("mDNS_StartQuery_internal: Question %##s %s %p (%p) started",
-				      question->qname.c, DNSTypeName(question->qtype), question->InterfaceID, question);
-		else
-			verbosedebugf("mDNS_StartQuery_internal: Question %##s %s %p (%p) duplicate of (%p)",
-				      question->qname.c, DNSTypeName(question->qtype), question->InterfaceID, question, question->DuplicateOf);
-
-		*q = question;
-		if (question->InterfaceID == ((mDNSInterfaceID)~0))
-		{
-			if (!m->NewLocalOnlyQuestions) m->NewLocalOnlyQuestions = question;
-		}
-		else
-		{
-			if (!m->NewQuestions) m->NewQuestions = question;
-			SetNextQueryTime(m,question);
-		}
-
-		return(mStatus_NoError);
-	}
-}
-
-mDNSlocal mStatus mDNS_StopQuery_internal(mDNS *const m, DNSQuestion *const question)
-{
-	CacheRecord *rr;
-	DNSQuestion **q = &m->Questions;
-	if (question->InterfaceID == ((mDNSInterfaceID)~0)) q = &m->LocalOnlyQuestions;
-	while (*q && *q != question) q=&(*q)->next;
-	if (*q) *q = (*q)->next;
-	else
-	{
-		if (question->ThisQInterval >= 0)	// Only log error message if the query was supposed to be active
-			LogMsg("mDNS_StopQuery_internal: Question %##s (%s) not found in active list",
-			       question->qname.c, DNSTypeName(question->qtype));
-		return(mStatus_BadReferenceErr);
-	}
-
-	// Take care to cut question from list *before* calling UpdateQuestionDuplicates
-	UpdateQuestionDuplicates(m, question);
-	// But don't trash ThisQInterval until afterwards.
-	question->ThisQInterval = -1;
-
-	// If there are any cache records referencing this as their active question, then see if any other
-	// question that is also referencing them, else their CRActiveQuestion needs to get set to NULL.
-	for (rr = m->rrcache_hash[HashSlot(&question->qname)]; rr; rr=rr->next)
-	{
-		if (rr->CRActiveQuestion == question)
-		{
-			DNSQuestion *q;
-			for (q = m->Questions; q; q=q->next)		// Scan our list of questions
-				if (ActiveQuestion(q) && ResourceRecordAnswersQuestion(&rr->resrec, q))
-					break;
-			verbosedebugf("mDNS_StopQuery_internal: Cache RR %##s (%s) setting CRActiveQuestion to %X", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype), q);
-			rr->CRActiveQuestion = q;		// Question used to be active; new value may or may not be null
-			if (!q) m->rrcache_active--;	// If no longer active, decrement rrcache_active count
-		}
-	}
-
-	// If we just deleted the question that CacheRecordAdd() or CacheRecordRmv()is about to look at,
-	// bump its pointer forward one question.
-	if (m->CurrentQuestion == question)
-	{
-		debugf("mDNS_StopQuery_internal: Just deleted the currently active question: %##s (%s)",
-		       question->qname.c, DNSTypeName(question->qtype));
-		m->CurrentQuestion = question->next;
-	}
-
-	if (m->NewQuestions == question)
-	{
-		debugf("mDNS_StopQuery_internal: Just deleted a new question that wasn't even answered yet: %##s (%s)",
-		       question->qname.c, DNSTypeName(question->qtype));
-		m->NewQuestions = question->next;
-	}
-
-	if (m->NewLocalOnlyQuestions == question) m->NewLocalOnlyQuestions = question->next;
-
-	// Take care not to trash question->next until *after* we've updated m->CurrentQuestion and m->NewQuestions
-	question->next = mDNSNULL;
-	return(mStatus_NoError);
-}
-
-mDNSexport mStatus mDNS_StartQuery(mDNS *const m, DNSQuestion *const question)
-{
-	mStatus status;
-	mDNS_Lock(m);
-	status = mDNS_StartQuery_internal(m, question);
-	mDNS_Unlock(m);
-	return(status);
-}
-
-mDNSexport mStatus mDNS_StopQuery(mDNS *const m, DNSQuestion *const question)
-{
-	mStatus status;
-	mDNS_Lock(m);
-	status = mDNS_StopQuery_internal(m, question);
-	mDNS_Unlock(m);
-	return(status);
-}
-
-mDNSexport mStatus mDNS_Reconfirm(mDNS *const m, CacheRecord *const rr)
-{
-	mStatus status;
-	mDNS_Lock(m);
-	status = mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForNoAnswer);
-	mDNS_Unlock(m);
-	return(status);
-}
-
-mDNSexport mStatus mDNS_ReconfirmByValue(mDNS *const m, ResourceRecord *const rr)
-{
-	mStatus status = mStatus_BadReferenceErr;
-	CacheRecord *cr;
-	mDNS_Lock(m);
-	cr = FindIdenticalRecordInCache(m, rr);
-	if (cr) status = mDNS_Reconfirm_internal(m, cr, kDefaultReconfirmTimeForNoAnswer);
-	mDNS_Unlock(m);
-	return(status);
-}
-
-mDNSexport mStatus mDNS_StartBrowse(mDNS *const m, DNSQuestion *const question,
-				    const domainname *const srv, const domainname *const domain,
-				    const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *Callback, void *Context)
-{
-	question->ThisQInterval     = -1;				// Indicate that query is not yet active
-	question->InterfaceID       = InterfaceID;
-	question->qtype             = kDNSType_PTR;
-	question->qclass            = kDNSClass_IN;
-	question->QuestionCallback  = Callback;
-	question->QuestionContext   = Context;
-	if (!ConstructServiceName(&question->qname, mDNSNULL, srv, domain)) return(mStatus_BadParamErr);
-	return(mDNS_StartQuery(m, question));
-}
-
-mDNSlocal void FoundServiceInfoSRV(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
-{
-	ServiceInfoQuery *query = (ServiceInfoQuery *)question->QuestionContext;
-	mDNSBool PortChanged = (mDNSBool)(query->info->port.NotAnInteger != answer->rdata->u.srv.port.NotAnInteger);
-	if (!AddRecord) return;
-	if (answer->rrtype != kDNSType_SRV) return;
-
-	query->info->port = answer->rdata->u.srv.port;
-
-	// If this is our first answer, then set the GotSRV flag and start the address query
-	if (!query->GotSRV)
-	{
-		query->GotSRV             = mDNStrue;
-		query->qAv4.InterfaceID   = answer->InterfaceID;
-		AssignDomainName(query->qAv4.qname, answer->rdata->u.srv.target);
-		query->qAv6.InterfaceID   = answer->InterfaceID;
-		AssignDomainName(query->qAv6.qname, answer->rdata->u.srv.target);
-		mDNS_StartQuery_internal(m, &query->qAv4);
-		mDNS_StartQuery_internal(m, &query->qAv6);
-	}
-	// If this is not our first answer, only re-issue the address query if the target host name has changed
-	else if ((query->qAv4.InterfaceID != query->qSRV.InterfaceID && query->qAv4.InterfaceID != answer->InterfaceID) ||
-		 !SameDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target))
-	{
-		mDNS_StopQuery_internal(m, &query->qAv4);
-		mDNS_StopQuery_internal(m, &query->qAv6);
-		if (SameDomainName(&query->qAv4.qname, &answer->rdata->u.srv.target) && !PortChanged)
-		{
-			// If we get here, it means:
-			// 1. This is not our first SRV answer
-			// 2. The interface ID is different, but the target host and port are the same
-			// This implies that we're seeing the exact same SRV record on more than one interface, so we should
-			// make our address queries at least as broad as the original SRV query so that we catch all the answers.
-			query->qAv4.InterfaceID = query->qSRV.InterfaceID;	// Will be mDNSInterface_Any, or a specific interface
-			query->qAv6.InterfaceID = query->qSRV.InterfaceID;
-		}
-		else
-		{
-			query->qAv4.InterfaceID   = answer->InterfaceID;
-			AssignDomainName(query->qAv4.qname, answer->rdata->u.srv.target);
-			query->qAv6.InterfaceID   = answer->InterfaceID;
-			AssignDomainName(query->qAv6.qname, answer->rdata->u.srv.target);
-		}
-		debugf("FoundServiceInfoSRV: Restarting address queries for %##s", query->qAv4.qname.c);
-		mDNS_StartQuery_internal(m, &query->qAv4);
-		mDNS_StartQuery_internal(m, &query->qAv6);
-	}
-	else if (query->ServiceInfoQueryCallback && query->GotADD && query->GotTXT && PortChanged)
-	{
-		if (++query->Answers >= 100)
-			debugf("**** WARNING **** Have given %lu answers for %##s (SRV) %##s %u",
-			       query->Answers, query->qSRV.qname.c, answer->rdata->u.srv.target.c,
-			       ((mDNSu16)answer->rdata->u.srv.port.b[0] << 8) | answer->rdata->u.srv.port.b[1]);
-		query->ServiceInfoQueryCallback(m, query);
-	}
-	// CAUTION: MUST NOT do anything more with query after calling query->Callback(), because the client's
-	// callback function is allowed to do anything, including deleting this query and freeing its memory.
-}
-
-mDNSlocal void FoundServiceInfoTXT(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
-{
-	ServiceInfoQuery *query = (ServiceInfoQuery *)question->QuestionContext;
-	if (!AddRecord) return;
-	if (answer->rrtype != kDNSType_TXT) return;
-	if (answer->rdlength > sizeof(query->info->TXTinfo)) return;
-
-	query->GotTXT       = mDNStrue;
-	query->info->TXTlen = answer->rdlength;
-	mDNSPlatformMemCopy(answer->rdata->u.txt.c, query->info->TXTinfo, answer->rdlength);
-
-	verbosedebugf("FoundServiceInfoTXT: %##s GotADD=%d", query->info->name.c, query->GotADD);
-
-	// CAUTION: MUST NOT do anything more with query after calling query->Callback(), because the client's
-	// callback function is allowed to do anything, including deleting this query and freeing its memory.
-	if (query->ServiceInfoQueryCallback && query->GotADD)
-	{
-		if (++query->Answers >= 100)
-			debugf("**** WARNING **** have given %lu answers for %##s (TXT) %#s...",
-			       query->Answers, query->qSRV.qname.c, answer->rdata->u.txt.c);
-		query->ServiceInfoQueryCallback(m, query);
-	}
-}
-
-mDNSlocal void FoundServiceInfo(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord)
-{
-	ServiceInfoQuery *query = (ServiceInfoQuery *)question->QuestionContext;
-	if (!AddRecord) return;
-	
-	if (answer->rrtype == kDNSType_A)
-	{
-		query->info->ip.type = mDNSAddrType_IPv4;
-		query->info->ip.ip.v4 = answer->rdata->u.ip;
-	}
-	else if (answer->rrtype == kDNSType_AAAA)
-	{
-		query->info->ip.type = mDNSAddrType_IPv6;
-		query->info->ip.ip.v6 = answer->rdata->u.ipv6;
-	}
-	else
-	{
-		debugf("FoundServiceInfo: answer %##s type %d (%s) unexpected", answer->name.c, answer->rrtype, DNSTypeName(answer->rrtype));
-		return;
-	}
-
-	query->GotADD = mDNStrue;
-	query->info->InterfaceID = answer->InterfaceID;
-
-	verbosedebugf("FoundServiceInfo v%d: %##s GotTXT=%d", query->info->ip.type, query->info->name.c, query->GotTXT);
-
-	// CAUTION: MUST NOT do anything more with query after calling query->Callback(), because the client's
-	// callback function is allowed to do anything, including deleting this query and freeing its memory.
-	if (query->ServiceInfoQueryCallback && query->GotTXT)
-	{
-		if (++query->Answers >= 100)
-		{
-			if (answer->rrtype == kDNSType_A)
-				debugf("**** WARNING **** have given %lu answers for %##s (A) %.4a",     query->Answers, query->qSRV.qname.c, &answer->rdata->u.ip);
-			else
-				debugf("**** WARNING **** have given %lu answers for %##s (AAAA) %.16a", query->Answers, query->qSRV.qname.c, &answer->rdata->u.ipv6);
-		}
-		query->ServiceInfoQueryCallback(m, query);
-	}
-}
-
-// On entry, the client must have set the name and InterfaceID fields of the ServiceInfo structure
-// If the query is not interface-specific, then InterfaceID may be zero
-// Each time the Callback is invoked, the remainder of the fields will have been filled in
-// In addition, InterfaceID will be updated to give the interface identifier corresponding to that response
-mDNSexport mStatus mDNS_StartResolveService(mDNS *const m,
-					    ServiceInfoQuery *query, ServiceInfo *info, mDNSServiceInfoQueryCallback *Callback, void *Context)
-{
-	mStatus status;
-	mDNS_Lock(m);
-
-	query->qSRV.ThisQInterval       = -1;		// This question not yet in the question list
-	query->qSRV.InterfaceID         = info->InterfaceID;
-	AssignDomainName(query->qSRV.qname, info->name);
-	query->qSRV.qtype               = kDNSType_SRV;
-	query->qSRV.qclass              = kDNSClass_IN;
-	query->qSRV.QuestionCallback    = FoundServiceInfoSRV;
-	query->qSRV.QuestionContext     = query;
-
-	query->qTXT.ThisQInterval       = -1;		// This question not yet in the question list
-	query->qTXT.InterfaceID         = info->InterfaceID;
-	AssignDomainName(query->qTXT.qname, info->name);
-	query->qTXT.qtype               = kDNSType_TXT;
-	query->qTXT.qclass              = kDNSClass_IN;
-	query->qTXT.QuestionCallback    = FoundServiceInfoTXT;
-	query->qTXT.QuestionContext     = query;
-
-	query->qAv4.ThisQInterval       = -1;		// This question not yet in the question list
-	query->qAv4.InterfaceID         = info->InterfaceID;
-	query->qAv4.qname.c[0]          = 0;
-	query->qAv4.qtype               = kDNSType_A;
-	query->qAv4.qclass              = kDNSClass_IN;
-	query->qAv4.QuestionCallback    = FoundServiceInfo;
-	query->qAv4.QuestionContext     = query;
-
-	query->qAv6.ThisQInterval       = -1;		// This question not yet in the question list
-	query->qAv6.InterfaceID         = info->InterfaceID;
-	query->qAv6.qname.c[0]          = 0;
-	query->qAv6.qtype               = kDNSType_AAAA;
-	query->qAv6.qclass              = kDNSClass_IN;
-	query->qAv6.QuestionCallback    = FoundServiceInfo;
-	query->qAv6.QuestionContext     = query;
-
-	query->GotSRV                   = mDNSfalse;
-	query->GotTXT                   = mDNSfalse;
-	query->GotADD                   = mDNSfalse;
-	query->Answers                  = 0;
-
-	query->info                     = info;
-	query->ServiceInfoQueryCallback = Callback;
-	query->ServiceInfoQueryContext  = Context;
-
-//	info->name      = Must already be set up by client
-//	info->interface = Must already be set up by client
-	info->ip        = zeroAddr;
-	info->port      = zeroIPPort;
-	info->TXTlen    = 0;
-
-	status = mDNS_StartQuery_internal(m, &query->qSRV);
-	if (status == mStatus_NoError) status = mDNS_StartQuery_internal(m, &query->qTXT);
-	if (status != mStatus_NoError) mDNS_StopResolveService(m, query);
-
-	mDNS_Unlock(m);
-	return(status);
-}
-
-mDNSexport void    mDNS_StopResolveService (mDNS *const m, ServiceInfoQuery *query)
-{
-	mDNS_Lock(m);
-	if (query->qSRV.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &query->qSRV);
-	if (query->qTXT.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &query->qTXT);
-	if (query->qAv4.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &query->qAv4);
-	if (query->qAv6.ThisQInterval >= 0) mDNS_StopQuery_internal(m, &query->qAv6);
-	mDNS_Unlock(m);
-}
-
-mDNSexport mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, mDNS_DomainType DomainType,
-				   const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *Callback, void *Context)
-{
-	MakeDomainNameFromDNSNameString(&question->qname, mDNS_DomainTypeNames[DomainType]);
-	question->InterfaceID      = InterfaceID;
-	question->qtype            = kDNSType_PTR;
-	question->qclass           = kDNSClass_IN;
-	question->QuestionCallback = Callback;
-	question->QuestionContext  = Context;
-
-	// No sense doing this until we actually support unicast query/update
-	//return(mDNS_StartQuery(m, question));
-	(void)m; // Unused
-	return(mStatus_NoError);
-}
-#endif
-// ***************************************************************************
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark - Responder Functions
-#endif
-
-// Set up a AuthRecord with sensible default values.
-// These defaults may be overwritten with new values before mDNS_Register is called
-mDNSexport void mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mDNSInterfaceID InterfaceID,
-					 mDNSu16 rrtype, mDNSu32 ttl, mDNSu8 RecordType, mDNSRecordCallback Callback, void *Context)
-{
-	// Don't try to store a TTL bigger than we can represent in platform time units
-	if (ttl > 0x7FFFFFFFUL / mDNSPlatformOneSecond)
-		ttl = 0x7FFFFFFFUL / mDNSPlatformOneSecond;
-	else if (ttl == 0)		// And Zero TTL is illegal
-		ttl = kDefaultTTLforShared;
-
-	// Field Group 1: Persistent metadata for Authoritative Records
-	rr->Additional1       = mDNSNULL;
-	rr->Additional2       = mDNSNULL;
-	rr->DependentOn       = mDNSNULL;
-	rr->RRSet             = mDNSNULL;
-	rr->RecordCallback    = Callback;
-	rr->RecordContext     = Context;
-
-	rr->resrec.RecordType        = RecordType;
-	rr->HostTarget        = mDNSfalse;
-	
-	// Field Group 2: Transient state for Authoritative Records (set in mDNS_Register_internal)
-	// Field Group 3: Transient state for Cache Records         (set in mDNS_Register_internal)
-
-	// Field Group 4: The actual information pertaining to this resource record
-	rr->resrec.InterfaceID       = InterfaceID;
-	rr->resrec.name.c[0]         = 0;		// MUST be set by client
-	rr->resrec.rrtype            = rrtype;
-	rr->resrec.rrclass           = kDNSClass_IN;
-	rr->resrec.rroriginalttl     = ttl;
-//	rr->resrec.rdlength          = MUST set by client and/or in mDNS_Register_internal
-//	rr->resrec.rdestimate        = set in mDNS_Register_internal
-//	rr->resrec.rdata             = MUST be set by client
-
-	if (RDataStorage)
-		rr->resrec.rdata = RDataStorage;
-	else
-	{
-		rr->resrec.rdata = &rr->rdatastorage;
-		rr->resrec.rdata->MaxRDLength = sizeof(RDataBody);
-	}
-}
-
-mDNSexport mStatus mDNS_Register(mDNS *const m, AuthRecord *const rr)
-{
-	mStatus status;
-	mDNS_Lock(m);
-	status = mDNS_Register_internal(m, rr);
-	mDNS_Unlock(m);
-	return(status);
-}
-#if 1
-mDNSexport mStatus mDNS_Update(mDNS *const m, AuthRecord *const rr, mDNSu32 newttl,
-			       const mDNSu16 newrdlength,
-			       RData *const newrdata, mDNSRecordUpdateCallback *Callback)
-{
-	if (!ValidateRData(rr->resrec.rrtype, newrdlength, newrdata))
-	{ LogMsg("Attempt to update record with invalid rdata: %s", GetRRDisplayString_rdb(m, &rr->resrec, &newrdata->u)); return(mStatus_Invalid); }
-
-	mDNS_Lock(m);
-
-	// If TTL is unspecified, leave TTL unchanged
-	if (newttl == 0) newttl = rr->resrec.rroriginalttl;
-
-	// If we already have an update queued up which has not gone through yet,
-	// give the client a chance to free that memory
-	if (rr->NewRData)
-	{
-		RData *n = rr->NewRData;
-		rr->NewRData = mDNSNULL;			// Clear the NewRData pointer ...
-		if (rr->UpdateCallback)
-			rr->UpdateCallback(m, rr, n);	// ...and let the client free this memory, if necessary
-	}
-	
-	if (rr->AnnounceCount < ReannounceCount)
-		rr->AnnounceCount = ReannounceCount;
-	rr->ThisAPInterval       = DefaultAPIntervalForRecordType(rr->resrec.RecordType);
-	InitializeLastAPTime(m, rr);
-	rr->NewRData             = newrdata;
-	rr->newrdlength          = newrdlength;
-	rr->UpdateCallback       = Callback;
-	if (!rr->UpdateBlocked && rr->UpdateCredits) rr->UpdateCredits--;
-	if (!rr->NextUpdateCredit) rr->NextUpdateCredit = (m->timenow + mDNSPlatformOneSecond * 60) | 1;
-	if (rr->AnnounceCount > rr->UpdateCredits + 1) rr->AnnounceCount = (mDNSu8)(rr->UpdateCredits + 1);
-	if (rr->UpdateCredits <= 5)
-	{
-		mDNSs32 delay = 1 << (5 - rr->UpdateCredits);
-		if (!rr->UpdateBlocked) rr->UpdateBlocked = (m->timenow + delay * mDNSPlatformOneSecond) | 1;
-		rr->LastAPTime = rr->UpdateBlocked;
-		rr->ThisAPInterval *= 4;
-		LogMsg("Excessive update rate for %##s; delaying announcement by %d seconds", rr->resrec.name.c, delay);
-	}
-	rr->resrec.rroriginalttl = newttl;
-	mDNS_Unlock(m);
-	return(mStatus_NoError);
-}
-#endif
-// NOTE: mDNS_Deregister calls mDNS_Deregister_internal which can call a user callback, which may change
-// the record list and/or question list.
-// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
-mDNSexport mStatus mDNS_Deregister(mDNS *const m, AuthRecord *const rr)
-{
-	mStatus status;
-	mDNS_Lock(m);
-	status = mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
-	mDNS_Unlock(m);
-	return(status);
-}
-
-mDNSlocal void HostNameCallback(mDNS *const m, AuthRecord *const rr, mStatus result);
-
-mDNSlocal NetworkInterfaceInfo *FindFirstAdvertisedInterface(mDNS *const m)
-{
-	NetworkInterfaceInfo *intf;
-	for (intf = m->HostInterfaces; intf; intf = intf->next)
-		if (intf->Advertise) break;
-	return(intf);
-}
-
-mDNSlocal void mDNS_AdvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set)
-{
-	char *buffer = tls_mem_alloc(256);
-	NetworkInterfaceInfo *primary = FindFirstAdvertisedInterface(m);
-	if (!primary) primary = set; // If no existing advertised interface, this new NetworkInterfaceInfo becomes our new primary
-	if(!buffer) return ;
-	
-	mDNS_SetupResourceRecord(&set->RR_A,     mDNSNULL, set->InterfaceID, kDNSType_A,     kDefaultTTLforUnique, kDNSRecordTypeUnique,      HostNameCallback, set);
-	mDNS_SetupResourceRecord(&set->RR_PTR,   mDNSNULL, set->InterfaceID, kDNSType_PTR,   kDefaultTTLforUnique, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
-	mDNS_SetupResourceRecord(&set->RR_HINFO, mDNSNULL, set->InterfaceID, kDNSType_HINFO, kDefaultTTLforUnique, kDNSRecordTypeUnique,      mDNSNULL, mDNSNULL);
-
-	// 1. Set up Address record to map from host name ("foo.local.") to IP address
-	// 2. Set up reverse-lookup PTR record to map from our address back to our host name
-	AssignDomainName(set->RR_A.resrec.name, m->hostname);
-	if (set->ip.type == mDNSAddrType_IPv4)
-	{
-		set->RR_A.resrec.rrtype = kDNSType_A;
-		set->RR_A.resrec.rdata->u.ip = set->ip.ip.v4;
-		// Note: This is reverse order compared to a normal dotted-decimal IP address
-		mDNS_snprintf(buffer, 256, "%d.%d.%d.%d.in-addr.arpa.",
-			      set->ip.ip.v4.b[3], set->ip.ip.v4.b[2], set->ip.ip.v4.b[1], set->ip.ip.v4.b[0]);
-	}
-	else if (set->ip.type == mDNSAddrType_IPv6)
-	{
-		int i;
-		set->RR_A.resrec.rrtype = kDNSType_AAAA;
-		set->RR_A.resrec.rdata->u.ipv6 = set->ip.ip.v6;
-		for (i = 0; i < 16; i++)
-		{
-			static const char hexValues[] = "0123456789ABCDEF";
-			buffer[i * 4    ] = hexValues[set->ip.ip.v6.b[15 - i] & 0x0F];
-			buffer[i * 4 + 1] = '.';
-			buffer[i * 4 + 2] = hexValues[set->ip.ip.v6.b[15 - i] >> 4];
-			buffer[i * 4 + 3] = '.';
-		}
-		mDNS_snprintf(&buffer[64], 256-64, "ip6.arpa.");
-	}
-
-	MakeDomainNameFromDNSNameString(&set->RR_PTR.resrec.name, buffer);
-	tls_mem_free(buffer);
-	set->RR_PTR.HostTarget = mDNStrue;	// Tell mDNS that the target of this PTR is to be kept in sync with our host name
-
-	set->RR_A.RRSet = &primary->RR_A;	// May refer to self
-
-	mDNS_Register_internal(m, &set->RR_A);
-	mDNS_Register_internal(m, &set->RR_PTR);
-
-	if (m->HIHardware.c[0] > 0 && m->HISoftware.c[0] > 0 && m->HIHardware.c[0] + m->HISoftware.c[0] <= 254)
-	{
-		mDNSu8 *p = set->RR_HINFO.resrec.rdata->u.data;
-		AssignDomainName(set->RR_HINFO.resrec.name, m->hostname);
-		set->RR_HINFO.DependentOn = &set->RR_A;
-		mDNSPlatformMemCopy(&m->HIHardware, p, 1 + (mDNSu32)m->HIHardware.c[0]);
-		p += 1 + (int)p[0];
-		mDNSPlatformMemCopy(&m->HISoftware, p, 1 + (mDNSu32)m->HISoftware.c[0]);
-		mDNS_Register_internal(m, &set->RR_HINFO);
-	}
-	else
-	{
-		debugf("Not creating HINFO record: platform support layer provided no information");
-		set->RR_HINFO.resrec.RecordType = kDNSRecordTypeUnregistered;
-	}
-}
-
-mDNSlocal void mDNS_DeadvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set)
-{
-	NetworkInterfaceInfo *intf;
-	// If we still have address records referring to this one, update them
-	NetworkInterfaceInfo *primary = FindFirstAdvertisedInterface(m);
-	AuthRecord *A = primary ? &primary->RR_A : mDNSNULL;
-	for (intf = m->HostInterfaces; intf; intf = intf->next)
-		if (intf->RR_A.RRSet == &set->RR_A)
-			intf->RR_A.RRSet = A;
-
-	// Unregister these records.
-	// When doing the mDNS_Close processing, we first call mDNS_DeadvertiseInterface for each interface, so by the time the platform
-	// support layer gets to call mDNS_DeregisterInterface, the address and PTR records have already been deregistered for it.
-	// Also, in the event of a name conflict, one or more of our records will have been forcibly deregistered.
-	// To avoid unnecessary and misleading warning messages, we check the RecordType before calling mDNS_Deregister_internal().
-	if (set->RR_A.    resrec.RecordType) mDNS_Deregister_internal(m, &set->RR_A,     mDNS_Dereg_normal);
-	if (set->RR_PTR.  resrec.RecordType) mDNS_Deregister_internal(m, &set->RR_PTR,   mDNS_Dereg_normal);
-	if (set->RR_HINFO.resrec.RecordType) mDNS_Deregister_internal(m, &set->RR_HINFO, mDNS_Dereg_normal);
-}
-
-mDNSexport void mDNS_GenerateFQDN(mDNS *const m)
-{
-	domainname newname;
-	mDNS_Lock(m);
-
-	newname.c[0] = 0;
-	if (!AppendDomainLabel(&newname, &m->hostlabel))  LogMsg("ERROR! Cannot create dot-local hostname");
-	if (!AppendLiteralLabelString(&newname, "local")) LogMsg("ERROR! Cannot create dot-local hostname");
-	if (!SameDomainName(&m->hostname, &newname))
-	{
-		NetworkInterfaceInfo *intf;
-		AuthRecord *rr;
-
-		m->hostname = newname;
-
-		// 1. Stop advertising our address records on all interfaces
-		for (intf = m->HostInterfaces; intf; intf = intf->next)
-			if (intf->Advertise) mDNS_DeadvertiseInterface(m, intf);
-
-		// 2. Start advertising our address records using the new name
-		for (intf = m->HostInterfaces; intf; intf = intf->next)
-			if (intf->Advertise) mDNS_AdvertiseInterface(m, intf);
-
-		// 3. Make sure that any SRV records (and the like) that reference our
-		// host name in their rdata get updated to reference this new host name
-		for (rr = m->ResourceRecords;  rr; rr=rr->next) if (rr->HostTarget) SetTargetToHostName(m, rr);
-		for (rr = m->DuplicateRecords; rr; rr=rr->next) if (rr->HostTarget) SetTargetToHostName(m, rr);
-	}
-
-	mDNS_Unlock(m);
-}
-
-mDNSlocal void HostNameCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
-{
-	(void)rr;	// Unused parameter
-
-#if MDNS_DEBUGMSGS
-	{
-		char *msg = "Unknown result";
-		if      (result == mStatus_NoError)      msg = "Name registered";
-		else if (result == mStatus_NameConflict) msg = "Name conflict";
-		debugf("HostNameCallback: %##s (%s) %s (%ld)", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype), msg, result);
-	}
-#endif
-
-	if (result == mStatus_NoError)
-	{
-		// Notify the client that the host name is successfully registered
-		if (m->MainCallback)
-			m->MainCallback(m, result);
-	}
-	else if (result == mStatus_NameConflict)
-	{
-		domainlabel oldlabel = m->hostlabel;
-
-		// 1. First give the client callback a chance to pick a new name
-		if (m->MainCallback)
-			m->MainCallback(m, mStatus_NameConflict);
-
-		// 2. If the client callback didn't do it, add (or increment) an index ourselves
-		if (SameDomainLabel(m->hostlabel.c, oldlabel.c))
-			IncrementLabelSuffix(&m->hostlabel, mDNSfalse);
-
-		// 3. Generate the FQDNs from the hostlabel,
-		// and make sure all SRV records, etc., are updated to reference our new hostname
-		mDNS_GenerateFQDN(m);
-	}
-}
-
-mDNSlocal void UpdateInterfaceProtocols(mDNS *const m, NetworkInterfaceInfo *active)
-{
-	NetworkInterfaceInfo *intf;
-	active->IPv4Available = mDNSfalse;
-	active->IPv6Available = mDNSfalse;
-	for (intf = m->HostInterfaces; intf; intf = intf->next)
-		if (intf->InterfaceID == active->InterfaceID)
-		{
-			if (intf->ip.type == mDNSAddrType_IPv4 && intf->TxAndRx) active->IPv4Available = mDNStrue;
-			if (intf->ip.type == mDNSAddrType_IPv6 && intf->TxAndRx) active->IPv6Available = mDNStrue;
-		}
-}
-
-mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *set)
-{
-	mDNSBool FirstOfType = mDNStrue;
-	NetworkInterfaceInfo **p = &m->HostInterfaces;
-	mDNS_Lock(m);
-	
-	// Assume this interface will be active
-	set->InterfaceActive = mDNStrue;
-	set->IPv4Available   = (set->ip.type == mDNSAddrType_IPv4 && set->TxAndRx);
-	set->IPv6Available   = (set->ip.type == mDNSAddrType_IPv6 && set->TxAndRx);
-
-	while (*p)
-	{
-		if (*p == set)
-		{
-			LogMsg("Error! Tried to register a NetworkInterfaceInfo that's already in the list");
-			mDNS_Unlock(m);
-			return(mStatus_AlreadyRegistered);
-		}
-
-		// This InterfaceID is already in the list, so mark this interface inactive for now
-		if ((*p)->InterfaceID == set->InterfaceID)
-		{
-			set->InterfaceActive = mDNSfalse;
-			if (set->ip.type == (*p)->ip.type) FirstOfType = mDNSfalse;
-			if (set->ip.type == mDNSAddrType_IPv4 && set->TxAndRx) (*p)->IPv4Available = mDNStrue;
-			if (set->ip.type == mDNSAddrType_IPv6 && set->TxAndRx) (*p)->IPv6Available = mDNStrue;
-		}
-
-		p=&(*p)->next;
-	}
-
-	set->next = mDNSNULL;
-	*p = set;
-	
-	debugf("mDNS_RegisterInterface: InterfaceID %p %#a %s", set->InterfaceID, &set->ip,
-	       set->InterfaceActive ?
-	       "not represented in list; marking active and retriggering queries" :
-	       "already represented in list; marking inactive for now");
-
-	// In some versions of OS X the IPv6 address remains on an interface even when the interface is turned off,
-	// giving the false impression that there's an active representative of this interface when there really isn't.
-	// Therefore, when registering an interface, we want to re-trigger our questions and re-probe our Resource Records,
-	// even if we believe that we previously had an active representative of this interface.
-	if ((m->KnownBugs & mDNS_KnownBug_PhantomInterfaces) || FirstOfType || set->InterfaceActive)
-	{
-		DNSQuestion *q;
-		AuthRecord *rr;
-		// Use a small amount of randomness:
-		// In the case of a network administrator turning on an Ethernet hub so that all the connected machines establish link at
-		// exactly the same time, we don't want them to all go and hit the network with identical queries at exactly the same moment.
-		if (!m->SuppressSending) m->SuppressSending = m->timenow + (mDNSs32)mDNSRandom((mDNSu32)InitialQuestionInterval);
-		for (q = m->Questions; q; q=q->next)							// Scan our list of questions
-			if (!q->InterfaceID || q->InterfaceID == set->InterfaceID)	// If non-specific Q, or Q on this specific interface,
-			{														// then reactivate this question
-				q->ThisQInterval = InitialQuestionInterval;				// MUST be > zero for an active question
-				q->LastQTime     = m->timenow - q->ThisQInterval;
-				q->RecentAnswers = 0;
-				if (ActiveQuestion(q)) m->NextScheduledQuery = m->timenow;
-			}
-		
-		// For all our non-specific authoritative resource records (and any dormant records specific to this interface)
-		// we now need them to re-probe if necessary, and then re-announce.
-		for (rr = m->ResourceRecords; rr; rr=rr->next)
-			if (!rr->resrec.InterfaceID || rr->resrec.InterfaceID == set->InterfaceID)
-			{
-				if (rr->resrec.RecordType == kDNSRecordTypeVerified && !rr->DependentOn) rr->resrec.RecordType = kDNSRecordTypeUnique;
-				rr->ProbeCount        = DefaultProbeCountForRecordType(rr->resrec.RecordType);
-				if (rr->AnnounceCount < ReannounceCount)
-					rr->AnnounceCount = ReannounceCount;
-				rr->ThisAPInterval    = DefaultAPIntervalForRecordType(rr->resrec.RecordType);
-				InitializeLastAPTime(m, rr);
-			}
-	}
-
-	if (set->Advertise)
-		mDNS_AdvertiseInterface(m, set);
-
-	mDNS_Unlock(m);
-	return(mStatus_NoError);
-}
-
-// NOTE: mDNS_DeregisterInterface calls mDNS_Deregister_internal which can call a user callback, which may change
-// the record list and/or question list.
-// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
-mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set)
-{
-	NetworkInterfaceInfo **p = &m->HostInterfaces;
-	
-	mDNSBool revalidate = mDNSfalse;
-	// If this platform has the "phantom interfaces" known bug (e.g. Jaguar), we have to revalidate records every
-	// time an interface goes away. Otherwise, when you disconnect the Ethernet cable, the system reports that it
-	// still has an IPv6 address, and if we don't revalidate those records don't get deleted in a timely fashion.
-	if (m->KnownBugs & mDNS_KnownBug_PhantomInterfaces) revalidate = mDNStrue;
-
-	mDNS_Lock(m);
-
-	// Find this record in our list
-	while (*p && *p != set) p=&(*p)->next;
-	if (!*p) { debugf("mDNS_DeregisterInterface: NetworkInterfaceInfo not found in list"); mDNS_Unlock(m); return; }
-
-	// Unlink this record from our list
-	*p = (*p)->next;
-	set->next = mDNSNULL;
-
-	if (!set->InterfaceActive)
-	{
-		// If this interface not the active member of its set, update the v4/v6Available flags for the active member
-		NetworkInterfaceInfo *intf;
-		for (intf = m->HostInterfaces; intf; intf = intf->next)
-			if (intf->InterfaceActive && intf->InterfaceID == set->InterfaceID)
-				UpdateInterfaceProtocols(m, intf);
-	}
-	else
-	{
-		NetworkInterfaceInfo *intf;
-		for (intf = m->HostInterfaces; intf; intf = intf->next)
-			if (intf->InterfaceID == set->InterfaceID)
-				break;
-		if (intf)
-		{
-			debugf("mDNS_DeregisterInterface: Another representative of InterfaceID %p exists; making it active",
-			       set->InterfaceID);
-			intf->InterfaceActive = mDNStrue;
-			UpdateInterfaceProtocols(m, intf);
-			
-			// See if another representative *of the same type* exists. If not, we mave have gone from
-			// dual-stack to v6-only (or v4-only) so we need to reconfirm which records are still valid.
-			for (intf = m->HostInterfaces; intf; intf = intf->next)
-				if (intf->InterfaceID == set->InterfaceID && intf->ip.type == set->ip.type)
-					break;
-			if (!intf) revalidate = mDNStrue;
-		}
-		else
-		{
-			CacheRecord *rr;
-			DNSQuestion *q;
-			mDNSu32 slot;
-			debugf("mDNS_DeregisterInterface: Last representative of InterfaceID %p deregistered; marking questions etc. dormant",
-			       set->InterfaceID);
-
-			// 1. Deactivate any questions specific to this interface
-			for (q = m->Questions; q; q=q->next)
-				if (q->InterfaceID == set->InterfaceID)
-					q->ThisQInterval = 0;
-
-			// 2. Flush any cache records received on this interface
-			revalidate = mDNSfalse;		// Don't revalidate if we're flushing the records
-			for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
-				for (rr = m->rrcache_hash[slot]; rr; rr=rr->next)
-					if (rr->resrec.InterfaceID == set->InterfaceID)
-						PurgeCacheResourceRecord(m, rr);
-		}
-	}
-
-	// If we were advertising on this interface, deregister those address and reverse-lookup records now
-	if (set->Advertise)
-		mDNS_DeadvertiseInterface(m, set);
-
-	// If we have any cache records received on this interface that went away, then re-verify them.
-	// In some versions of OS X the IPv6 address remains on an interface even when the interface is turned off,
-	// giving the false impression that there's an active representative of this interface when there really isn't.
-	// Don't need to do this when shutting down, because *all* interfaces are about to go away
-	if (revalidate && !m->mDNS_shutdown)
-	{
-		mDNSu32 slot;
-		CacheRecord *rr;
-		m->NextCacheCheck = m->timenow;
-		for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
-			for (rr = m->rrcache_hash[slot]; rr; rr=rr->next)
-				if (rr->resrec.InterfaceID == set->InterfaceID)
-					mDNS_Reconfirm_internal(m, rr, kDefaultReconfirmTimeForCableDisconnect);
-	}
-
-	mDNS_Unlock(m);
-}
-
-mDNSlocal void ServiceCallback(mDNS *const m, AuthRecord *const rr, mStatus result)
-{
-	ServiceRecordSet *sr = (ServiceRecordSet *)rr->RecordContext;
-	(void)m;	// Unused parameter
-
-#if MDNS_DEBUGMSGS
-	{
-		char *msg = "Unknown result";
-		if      (result == mStatus_NoError)      msg = "Name Registered";
-		else if (result == mStatus_NameConflict) msg = "Name Conflict";
-		else if (result == mStatus_MemFree)      msg = "Memory Free";
-		debugf("ServiceCallback: %##s (%s) %s (%ld)", rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype), msg, result);
-	}
-#endif
-
-	// If we got a name conflict on either SRV or TXT, forcibly deregister this service, and record that we did that
-	if (result == mStatus_NameConflict)
-	{
-		sr->Conflict = mDNStrue;							// Record that this service set had a conflict
-		sr->RR_PTR.AnnounceCount = InitialAnnounceCount;	// Make sure we don't send a goodbye for the PTR record
-		mDNS_DeregisterService(m, sr);						// Unlink the records from our list
-		return;
-	}
-	
-	if (result == mStatus_MemFree)
-	{
-		// If the PTR record or any of the subtype PTR record are still in the process of deregistering,
-		// don't pass on the NameConflict/MemFree message until every record is finished cleaning up.
-		mDNSu32 i;
-		if (sr->RR_PTR.resrec.RecordType != kDNSRecordTypeUnregistered) return;
-		for (i=0; i<sr->NumSubTypes; i++) if (sr->SubTypes[i].resrec.RecordType != kDNSRecordTypeUnregistered) return;
-
-		// If this ServiceRecordSet was forcibly deregistered, and now its memory is ready for reuse,
-		// then we can now report the NameConflict to the client
-		if (sr->Conflict) result = mStatus_NameConflict;
-	}
-
-	// CAUTION: MUST NOT do anything more with sr after calling sr->Callback(), because the client's callback
-	// function is allowed to do anything, including deregistering this service and freeing its memory.
-	if (sr->ServiceCallback)
-		sr->ServiceCallback(m, sr, result);
-}
-
-// Note:
-// Name is first label of domain name (any dots in the name are actual dots, not label separators)
-// Type is service type (e.g. "_printer._tcp.")
-// Domain is fully qualified domain name (i.e. ending with a null label)
-// We always register a TXT, even if it is empty (so that clients are not
-// left waiting forever looking for a nonexistent record.)
-// If the host parameter is mDNSNULL or the root domain (ASCII NUL),
-// then the default host name (m->hostname1) is automatically used
-mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr,
-					const domainlabel *const name, const domainname *const type, const domainname *const domain,
-					const domainname *const host, mDNSIPPort port, const mDNSu8 txtinfo[], mDNSu16 txtlen,
-					AuthRecord *SubTypes, mDNSu32 NumSubTypes,
-					const mDNSInterfaceID InterfaceID, mDNSServiceCallback Callback, void *Context)
-{
-	mStatus err;
-	mDNSu32 i;
-
-	sr->ServiceCallback = Callback;
-	sr->ServiceContext  = Context;
-	sr->Extras          = mDNSNULL;
-	sr->NumSubTypes     = NumSubTypes;
-	sr->SubTypes        = SubTypes;
-	sr->Conflict        = mDNSfalse;
-	if (host && host->c[0]) sr->Host = *host;
-	else sr->Host.c[0] = 0;
-	
-	// Initialize the AuthRecord objects to sane values
-	mDNS_SetupResourceRecord(&sr->RR_ADV, mDNSNULL, InterfaceID, kDNSType_PTR, kDefaultTTLforShared, kDNSRecordTypeAdvisory, ServiceCallback, sr);
-	mDNS_SetupResourceRecord(&sr->RR_PTR, mDNSNULL, InterfaceID, kDNSType_PTR, kDefaultTTLforShared, kDNSRecordTypeShared,   ServiceCallback, sr);
-	mDNS_SetupResourceRecord(&sr->RR_SRV, mDNSNULL, InterfaceID, kDNSType_SRV, kDefaultTTLforUnique, kDNSRecordTypeUnique,   ServiceCallback, sr);
-	mDNS_SetupResourceRecord(&sr->RR_TXT, mDNSNULL, InterfaceID, kDNSType_TXT, kDefaultTTLforUnique, kDNSRecordTypeUnique,   ServiceCallback, sr);
-	
-	// If the client is registering an oversized TXT record,
-	// it is the client's responsibility to alloate a ServiceRecordSet structure that is large enough for it
-	if (sr->RR_TXT.resrec.rdata->MaxRDLength < txtlen)
-		sr->RR_TXT.resrec.rdata->MaxRDLength = txtlen;
-
-	// Set up the record names
-	// For now we only create an advisory record for the main type, not for subtypes
-	// We need to gain some operational experience before we decide if there's a need to create them for subtypes too
-	if (ConstructServiceName(&sr->RR_ADV.resrec.name, (domainlabel*)"\x09_services", (domainname*)"\x07_dns-sd\x04_udp", domain) == mDNSNULL)
-		return(mStatus_BadParamErr);
-	if (ConstructServiceName(&sr->RR_PTR.resrec.name, mDNSNULL, type, domain) == mDNSNULL) return(mStatus_BadParamErr);
-	if (ConstructServiceName(&sr->RR_SRV.resrec.name, name,     type, domain) == mDNSNULL) return(mStatus_BadParamErr);
-	AssignDomainName(sr->RR_TXT.resrec.name, sr->RR_SRV.resrec.name);
-	
-	// 1. Set up the ADV record rdata to advertise our service type
-	AssignDomainName(sr->RR_ADV.resrec.rdata->u.name, sr->RR_PTR.resrec.name);
-
-	// 2. Set up the PTR record rdata to point to our service name
-	// We set up two additionals, so when a client asks for this PTR we automatically send the SRV and the TXT too
-	AssignDomainName(sr->RR_PTR.resrec.rdata->u.name, sr->RR_SRV.resrec.name);
-	sr->RR_PTR.Additional1 = &sr->RR_SRV;
-	sr->RR_PTR.Additional2 = &sr->RR_TXT;
-
-	// 2a. Set up any subtype PTRs to point to our service name
-	// If the client is using subtypes, it is the client's responsibility to have
-	// already set the first label of the record name to the subtype being registered
-	for (i=0; i<NumSubTypes; i++)
-	{
-		domainlabel s = *(domainlabel*)&sr->SubTypes[i].resrec.name;
-		mDNS_SetupResourceRecord(&sr->SubTypes[i], mDNSNULL, InterfaceID, kDNSType_PTR, kDefaultTTLforShared, kDNSRecordTypeShared, ServiceCallback, sr);
-		if (ConstructServiceName(&sr->SubTypes[i].resrec.name, &s, type, domain) == mDNSNULL) return(mStatus_BadParamErr);
-		AssignDomainName(sr->SubTypes[i].resrec.rdata->u.name, sr->RR_SRV.resrec.name);
-		sr->SubTypes[i].Additional1 = &sr->RR_SRV;
-		sr->SubTypes[i].Additional2 = &sr->RR_TXT;
-	}
-
-	// 3. Set up the SRV record rdata.
-	sr->RR_SRV.resrec.rdata->u.srv.priority = 0;
-	sr->RR_SRV.resrec.rdata->u.srv.weight   = 0;
-	sr->RR_SRV.resrec.rdata->u.srv.port     = port;
-
-	// Setting HostTarget tells DNS that the target of this SRV is to be automatically kept in sync with our host name
-	if (sr->Host.c[0]) AssignDomainName(sr->RR_SRV.resrec.rdata->u.srv.target, sr->Host);
-	else sr->RR_SRV.HostTarget = mDNStrue;
-
-	// 4. Set up the TXT record rdata,
-	// and set DependentOn because we're depending on the SRV record to find and resolve conflicts for us
-	if (txtinfo == mDNSNULL) sr->RR_TXT.resrec.rdlength = 0;
-	else if (txtinfo != sr->RR_TXT.resrec.rdata->u.txt.c)
-	{
-		sr->RR_TXT.resrec.rdlength = txtlen;
-		if (sr->RR_TXT.resrec.rdlength > sr->RR_TXT.resrec.rdata->MaxRDLength) return(mStatus_BadParamErr);
-		mDNSPlatformMemCopy(txtinfo, sr->RR_TXT.resrec.rdata->u.txt.c, txtlen);
-	}
-	sr->RR_TXT.DependentOn = &sr->RR_SRV;
-
-	mDNS_Lock(m);
-	err = mDNS_Register_internal(m, &sr->RR_SRV);
-	if (!err) err = mDNS_Register_internal(m, &sr->RR_TXT);
-	// We register the RR_PTR last, because we want to be sure that in the event of a forced call to
-	// mDNS_Close, the RR_PTR will be the last one to be forcibly deregistered, since that is what triggers
-	// the mStatus_MemFree callback to ServiceCallback, which in turn passes on the mStatus_MemFree back to
-	// the client callback, which is then at liberty to free the ServiceRecordSet memory at will. We need to
-	// make sure we've deregistered all our records and done any other necessary cleanup before that happens.
-	if (!err) err = mDNS_Register_internal(m, &sr->RR_ADV);
-	for (i=0; i<NumSubTypes; i++) if (!err) err = mDNS_Register_internal(m, &sr->SubTypes[i]);
-	if (!err) err = mDNS_Register_internal(m, &sr->RR_PTR);
-	mDNS_Unlock(m);
-
-	if (err) mDNS_DeregisterService(m, sr);
-	return(err);
-}
-
-mDNSexport mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr,
-					   ExtraResourceRecord *extra, RData *rdata, mDNSu32 ttl)
-{
-	mStatus result = mStatus_UnknownErr;
-	ExtraResourceRecord **e = &sr->Extras;
-	while (*e) e = &(*e)->next;
-
-	// If TTL is unspecified, make it the same as the service's TXT and SRV default
-	if (ttl == 0) ttl = kDefaultTTLforUnique;
-
-	extra->next          = mDNSNULL;
-	mDNS_SetupResourceRecord(&extra->r, rdata, sr->RR_PTR.resrec.InterfaceID, extra->r.resrec.rrtype, ttl, kDNSRecordTypeUnique, ServiceCallback, sr);
-	AssignDomainName(extra->r.resrec.name, sr->RR_SRV.resrec.name);
-	extra->r.DependentOn = &sr->RR_SRV;
-	
-	debugf("mDNS_AddRecordToService adding record to %##s", extra->r.resrec.name.c);
-	
-	result = mDNS_Register(m, &extra->r);
-	if (!result) *e = extra;
-	return result;
-}
-
-mDNSexport mStatus mDNS_RemoveRecordFromService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra)
-{
-	ExtraResourceRecord **e = &sr->Extras;
-	while (*e && *e != extra) e = &(*e)->next;
-	if (!*e)
-	{
-		debugf("mDNS_RemoveRecordFromService failed to remove record from %##s", extra->r.resrec.name.c);
-		return(mStatus_BadReferenceErr);
-	}
-
-	debugf("mDNS_RemoveRecordFromService removing record from %##s", extra->r.resrec.name.c);
-	
-	*e = (*e)->next;
-	return(mDNS_Deregister(m, &extra->r));
-}
-
-mDNSexport mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordSet *const sr, const domainlabel *newname)
-{
-	domainlabel name;
-	domainname type, domain;
-	domainname *host = mDNSNULL;
-	ExtraResourceRecord *extras = sr->Extras;
-	mStatus err;
-
-	DeconstructServiceName(&sr->RR_SRV.resrec.name, &name, &type, &domain);
-	if (!newname)
-	{
-		IncrementLabelSuffix(&name, mDNStrue);
-		newname = &name;
-	}
-	debugf("Reregistering as %#s", newname->c);
-	if (sr->RR_SRV.HostTarget == mDNSfalse && sr->Host.c[0]) host = &sr->Host;
-	
-	err = mDNS_RegisterService(m, sr, newname, &type, &domain,
-				   host, sr->RR_SRV.resrec.rdata->u.srv.port, sr->RR_TXT.resrec.rdata->u.txt.c, sr->RR_TXT.resrec.rdlength,
-				   sr->SubTypes, sr->NumSubTypes,
-				   sr->RR_PTR.resrec.InterfaceID, sr->ServiceCallback, sr->ServiceContext);
-
-	// mDNS_RegisterService() just reset sr->Extras to NULL.
-	// Fortunately we already grabbed ourselves a copy of this pointer (above), so we can now run
-	// through the old list of extra records, and re-add them to our freshly created service registration
-	while (!err && extras)
-	{
-		ExtraResourceRecord *e = extras;
-		extras = extras->next;
-		err = mDNS_AddRecordToService(m, sr, e, e->r.resrec.rdata, e->r.resrec.rroriginalttl);
-	}
-	
-	return(err);
-}
-
-// NOTE: mDNS_DeregisterService calls mDNS_Deregister_internal which can call a user callback,
-// which may change the record list and/or question list.
-// Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this.
-mDNSexport mStatus mDNS_DeregisterService(mDNS *const m, ServiceRecordSet *sr)
-{
-	if (sr->RR_PTR.resrec.RecordType == kDNSRecordTypeUnregistered)
-	{
-		debugf("Service set for %##s already deregistered", sr->RR_PTR.resrec.name.c);
-		return(mStatus_BadReferenceErr);
-	}
-	else if (sr->RR_PTR.resrec.RecordType == kDNSRecordTypeDeregistering)
-	{
-		debugf("Service set for %##s already in the process of deregistering", sr->RR_PTR.resrec.name.c);
-		return(mStatus_NoError);
-	}
-	else
-	{
-		mDNSu32 i;
-		mStatus status;
-		ExtraResourceRecord *e;
-		mDNS_Lock(m);
-		e = sr->Extras;
-	
-		// We use mDNS_Dereg_repeat because, in the event of a collision, some or all of the
-		// SRV, TXT, or Extra records could have already been automatically deregistered, and that's okay
-		mDNS_Deregister_internal(m, &sr->RR_SRV, mDNS_Dereg_repeat);
-		mDNS_Deregister_internal(m, &sr->RR_TXT, mDNS_Dereg_repeat);
-		
-		mDNS_Deregister_internal(m, &sr->RR_ADV, mDNS_Dereg_normal);
-	
-		// We deregister all of the extra records, but we leave the sr->Extras list intact
-		// in case the client wants to do a RenameAndReregister and reinstate the registration
-		while (e)
-		{
-			mDNS_Deregister_internal(m, &e->r, mDNS_Dereg_repeat);
-			e = e->next;
-		}
-
-		for (i=0; i<sr->NumSubTypes; i++)
-			mDNS_Deregister_internal(m, &sr->SubTypes[i], mDNS_Dereg_normal);
-
-		// Be sure to deregister the PTR last!
-		// Deregistering this record is what triggers the mStatus_MemFree callback to ServiceCallback,
-		// which in turn passes on the mStatus_MemFree (or mStatus_NameConflict) back to the client callback,
-		// which is then at liberty to free the ServiceRecordSet memory at will. We need to make sure
-		// we've deregistered all our records and done any other necessary cleanup before that happens.
-		status = mDNS_Deregister_internal(m, &sr->RR_PTR, mDNS_Dereg_normal);
-		mDNS_Unlock(m);
-		return(status);
-	}
-}
-#if 0
-// Create a registration that asserts that no such service exists with this name.
-// This can be useful where there is a given function is available through several protocols.
-// For example, a printer called "Stuart's Printer" may implement printing via the "pdl-datastream" and "IPP"
-// protocols, but not via "LPR". In this case it would be prudent for the printer to assert the non-existence of an
-// "LPR" service called "Stuart's Printer". Without this precaution, another printer than offers only "LPR" printing
-// could inadvertently advertise its service under the same name "Stuart's Printer", which might be confusing for users.
-mDNSexport mStatus mDNS_RegisterNoSuchService(mDNS *const m, AuthRecord *const rr,
-					      const domainlabel *const name, const domainname *const type, const domainname *const domain,
-					      const domainname *const host,
-					      const mDNSInterfaceID InterfaceID, mDNSRecordCallback Callback, void *Context)
-{
-	mDNS_SetupResourceRecord(rr, mDNSNULL, InterfaceID, kDNSType_SRV, kDefaultTTLforUnique, kDNSRecordTypeUnique, Callback, Context);
-	if (ConstructServiceName(&rr->resrec.name, name, type, domain) == mDNSNULL) return(mStatus_BadParamErr);
-	rr->resrec.rdata->u.srv.priority    = 0;
-	rr->resrec.rdata->u.srv.weight      = 0;
-	rr->resrec.rdata->u.srv.port        = zeroIPPort;
-	if (host && host->c[0]) AssignDomainName(rr->resrec.rdata->u.srv.target, *host);
-	else rr->HostTarget = mDNStrue;
-	return(mDNS_Register(m, rr));
-}
-
-mDNSexport mStatus mDNS_AdvertiseDomains(mDNS *const m, AuthRecord *rr,
-					 mDNS_DomainType DomainType, const mDNSInterfaceID InterfaceID, char *domname)
-{
-	mDNS_SetupResourceRecord(rr, mDNSNULL, InterfaceID, kDNSType_PTR, kDefaultTTLforShared, kDNSRecordTypeShared, mDNSNULL, mDNSNULL);
-	if (!MakeDomainNameFromDNSNameString(&rr->resrec.name, mDNS_DomainTypeNames[DomainType])) return(mStatus_BadParamErr);
-	if (!MakeDomainNameFromDNSNameString(&rr->resrec.rdata->u.name, domname))                 return(mStatus_BadParamErr);
-	return(mDNS_Register(m, rr));
-}
-#endif
-// ***************************************************************************
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark -
-#pragma mark -
-#pragma mark - Startup and Shutdown
-#endif
-
-mDNSexport void mDNS_GrowCache(mDNS *const m, CacheRecord *storage, mDNSu32 numrecords)
-{
-	if (storage && numrecords)
-	{
-		mDNSu32 i;
-		for (i=0; i<numrecords; i++) storage[i].next = &storage[i+1];
-		storage[numrecords-1].next = m->rrcache_free;
-		m->rrcache_free = storage;
-		m->rrcache_size += numrecords;
-	}
-}
-
-mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
-			     CacheRecord *rrcachestorage, mDNSu32 rrcachesize,
-			     mDNSBool AdvertiseLocalAddresses, mDNSCallback *Callback, void *Context)
-{
-	mDNSu32 slot;
-	mDNSs32 timenow;
-	mStatus result = mDNSPlatformTimeInit(&timenow);
-	if (result != mStatus_NoError) return(result);
-	
-	if (!rrcachestorage) rrcachesize = 0;
-	
-	m->p                       = p;
-	m->KnownBugs               = 0;
-	m->AdvertiseLocalAddresses = AdvertiseLocalAddresses;
-	m->mDNSPlatformStatus      = mStatus_Waiting;
-	m->MainCallback            = Callback;
-	m->MainContext             = Context;
-
-	// For debugging: To catch and report locking failures
-	m->mDNS_busy               = 0;
-	m->mDNS_reentrancy         = 0;
-	m->mDNS_shutdown           = mDNSfalse;
-	m->lock_rrcache            = 0;
-	m->lock_Questions          = 0;
-	m->lock_Records            = 0;
-
-	// Task Scheduling variables
-	m->timenow                 = 0;		// MUST only be set within mDNS_Lock/mDNS_Unlock section
-	m->timenow_last            = timenow;
-	m->timenow_adjust          = 0;
-	m->NextScheduledEvent      = timenow;
-	m->SuppressSending         = timenow;
-	m->NextCacheCheck          = timenow + kNextScheduledTime;
-	m->NextScheduledQuery      = timenow + kNextScheduledTime;
-	m->NextScheduledProbe      = timenow + kNextScheduledTime;
-	m->NextScheduledResponse   = timenow + kNextScheduledTime;
-	m->ExpectUnicastResponse   = timenow + kNextScheduledTime;
-	m->RandomQueryDelay        = 0;
-	m->SendDeregistrations     = mDNSfalse;
-	m->SendImmediateAnswers    = mDNSfalse;
-	m->SleepState              = mDNSfalse;
-
-	// These fields only required for mDNS Searcher...
-	m->Questions               = mDNSNULL;
-	m->NewQuestions            = mDNSNULL;
-	m->CurrentQuestion         = mDNSNULL;
-	m->LocalOnlyQuestions      = mDNSNULL;
-	m->NewLocalOnlyQuestions   = mDNSNULL;
-	m->rrcache_size            = 0;
-	m->rrcache_totalused       = 0;
-	m->rrcache_active          = 0;
-	m->rrcache_report          = 10;
-	m->rrcache_free            = mDNSNULL;
-
-	for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
-	{
-		m->rrcache_hash[slot] = mDNSNULL;
-		m->rrcache_tail[slot] = &m->rrcache_hash[slot];
-		m->rrcache_used[slot] = 0;
-	}
-
-	mDNS_GrowCache(m, rrcachestorage, rrcachesize);
-
-	// Fields below only required for mDNS Responder...
-	m->hostlabel.c[0]          = 0;
-	m->nicelabel.c[0]          = 0;
-	m->hostname.c[0]           = 0;
-	m->HIHardware.c[0]         = 0;
-	m->HISoftware.c[0]         = 0;
-	m->ResourceRecords         = mDNSNULL;
-	m->DuplicateRecords        = mDNSNULL;
-	m->LocalOnlyRecords        = mDNSNULL;
-	m->NewLocalOnlyRecords     = mDNSNULL;
-	m->DiscardLocalOnlyRecords = mDNSfalse;
-	m->CurrentRecord           = mDNSNULL;
-	m->HostInterfaces          = mDNSNULL;
-	m->ProbeFailTime           = 0;
-	m->NumFailedProbes         = 0;
-	m->SuppressProbes          = 0;
-
-	result = mDNSPlatformInit(m);
-
-	return(result);
-}
-
-mDNSexport void mDNSCoreInitComplete(mDNS *const m, mStatus result)
-{
-	m->mDNSPlatformStatus = result;
-	if (m->MainCallback)
-		m->MainCallback(m, mStatus_NoError);
-}
-
-mDNSexport void mDNS_Close(mDNS *const m)
-{
-	mDNSu32 rrcache_active = 0;
-#if MDNS_DEBUGMSGS
-	mDNSu32 rrcache_totalused = 0;
-#endif
-	mDNSu32 slot;
-	NetworkInterfaceInfo *intf;
-	mDNS_Lock(m);
-
-	m->mDNS_shutdown = mDNStrue;
-#if MDNS_DEBUGMSGS
-	rrcache_totalused = m->rrcache_totalused;
-#endif
-	for (slot = 0; slot < CACHE_HASH_SLOTS; slot++)
-	{
-		while (m->rrcache_hash[slot])
-		{
-			CacheRecord *rr = m->rrcache_hash[slot];
-			m->rrcache_hash[slot] = rr->next;
-			if (rr->CRActiveQuestion) rrcache_active++;
-			m->rrcache_used[slot]--;
-			ReleaseCacheRR(m, rr);
-		}
-		// Reset tail pointer back to empty state (not that it really matters on exit, but we'll do it anyway, for the sake of completeness)
-		m->rrcache_tail[slot] = &m->rrcache_hash[slot];
-	}
-	debugf("mDNS_Close: RR Cache was using %ld records, %d active", rrcache_totalused, rrcache_active);
-	if (rrcache_active != m->rrcache_active)
-		LogMsg("*** ERROR *** rrcache_active %lu != m->rrcache_active %lu", rrcache_active, m->rrcache_active);
-
-	m->Questions = mDNSNULL;		// We won't be answering any more questions!
-	
-	for (intf = m->HostInterfaces; intf; intf = intf->next)
-		if (intf->Advertise)
-			mDNS_DeadvertiseInterface(m, intf);
-
-	// Make sure there are nothing but deregistering records remaining in the list
-	if (m->CurrentRecord) LogMsg("mDNS_Close ERROR m->CurrentRecord already set");
-	m->CurrentRecord = m->ResourceRecords;
-	while (m->CurrentRecord)
-	{
-		AuthRecord *rr = m->CurrentRecord;
-		m->CurrentRecord = rr->next;
-		if (rr->resrec.RecordType != kDNSRecordTypeDeregistering)
-		{
-			debugf("mDNS_Close: Record type %X still in ResourceRecords list %##s", rr->resrec.RecordType, rr->resrec.name.c);
-			mDNS_Deregister_internal(m, rr, mDNS_Dereg_normal);
-		}
-	}
-
-	if (m->ResourceRecords) debugf("mDNS_Close: Sending final packets for deregistering records");
-	else debugf("mDNS_Close: No deregistering records remain");
-
-	// If any deregistering records remain, send their deregistration announcements before we exit
-	if (m->mDNSPlatformStatus != mStatus_NoError)
-		DiscardDeregistrations(m);
-	else
-		while (m->ResourceRecords)
-			SendResponses(m);
-	
-	mDNS_Unlock(m);
-	debugf("mDNS_Close: mDNSPlatformClose");
-	mDNSPlatformClose(m);
-	debugf("mDNS_Close: done");
-}

+ 0 - 7
src/app/mDNS/mDNSCore/mDNS.h

@@ -1,7 +0,0 @@
-#ifndef __MDNS_H_
-#define __MDNS_H_
-
-#define CLIENT_PROGRAM "mDNSClient"
-#define MDNS_RECORD_PRE "/tmp/mdns."
-
-#endif

+ 0 - 1486
src/app/mDNS/mDNSCore/mDNSClientAPI.h

@@ -1,1486 +0,0 @@
-/*
- * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
-
- Change History (most recent first):
-
- $Log: mDNSClientAPI.h,v $
- Revision 1.1.1.1  2005/07/23 13:57:05  shiro
- raop_play project
-
- Revision 1.1.2.1  2004/09/18 03:29:20  shiro
- *** empty log message ***
-
- Revision 1.114.2.9  2004/04/22 03:17:35  cheshire
- Fix use of "struct __attribute__((__packed__))" so it only applies on GCC >= 2.9
-
- Revision 1.114.2.8  2004/03/30 06:55:37  cheshire
- Gave name to anonymous struct, to avoid errors on certain compilers.
- (Thanks to ramaprasad.kr@hp.com for reporting this.)
-
- Revision 1.114.2.7  2004/03/09 02:31:27  cheshire
- Remove erroneous underscore in 'packed_struct' (makes no difference now, but might in future)
-
- Revision 1.114.2.6  2004/03/02 02:55:25  cheshire
- <rdar://problem/3549576> Properly support "_services._dns-sd._udp" meta-queries
-
- Revision 1.114.2.5  2004/02/18 23:35:17  cheshire
- <rdar://problem/3488559>: Hard code domain enumeration functions to return ".local" only
- Also make mDNS_StopGetDomains() a no-op too, so that we don't get warning messages in syslog
-
- Revision 1.114.2.4  2004/01/28 23:29:20  cheshire
- Fix structure packing (only affects third-party Darwin developers)
-
- Revision 1.114.2.3  2003/12/05 00:03:34  cheshire
- <rdar://problem/3487869> Use buffer size MAX_ESCAPED_DOMAIN_NAME instead of 256
-
- Revision 1.114.2.2  2003/12/04 23:30:00  cheshire
- Add "#define MAX_ESCAPED_DOMAIN_NAME 1005", needed for Posix folder to build
-
- Revision 1.114.2.1  2003/12/03 11:07:58  cheshire
- <rdar://problem/3457718>: Stop and start of a service uses old ip address (with old port number)
-
- Revision 1.114  2003/08/29 19:44:15  cheshire
- <rdar://problem/3400967> Traffic reduction: Eliminate synchronized QUs when a new service appears
- 1. Use m->RandomQueryDelay to impose a random delay in the range 0-500ms on queries
- that already have at least one unique answer in the cache
- 2. For these queries, go straight to QM, skipping QU
-
- Revision 1.113  2003/08/21 19:31:58  cheshire
- Cosmetic: Swap order of fields
-
- Revision 1.112  2003/08/21 19:27:36  cheshire
- <rdar://problem/3387878> Traffic reduction: No need to announce record for longer than TTL
-
- Revision 1.111  2003/08/21 02:21:50  cheshire
- <rdar://problem/3386473> Efficiency: Reduce repeated queries
-
- Revision 1.110  2003/08/20 23:39:31  cheshire
- <rdar://problem/3344098> Review syslog messages, and remove as appropriate
-
- Revision 1.109  2003/08/19 22:24:10  cheshire
- Comment change
-
- Revision 1.108  2003/08/19 22:20:00  cheshire
- <rdar://problem/3376721> Don't use IPv6 on interfaces that have a routable IPv4 address configured
- More minor refinements
-
- Revision 1.107  2003/08/19 06:48:25  cheshire
- <rdar://problem/3376552> Guard against excessive record updates
- Each record starts with 10 UpdateCredits.
- Every update consumes one UpdateCredit.
- UpdateCredits are replenished at a rate of one one per minute, up to a maximum of 10.
- As the number of UpdateCredits declines, the number of announcements is similarly scaled back.
- When fewer than 5 UpdateCredits remain, the first announcement is also delayed by an increasing amount.
-
- Revision 1.106  2003/08/19 04:49:28  cheshire
- <rdar://problem/3368159> Interaction between v4, v6 and dual-stack hosts not working quite right
- 1. A dual-stack host should only suppress its own query if it sees the same query from other hosts on BOTH IPv4 and IPv6.
- 2. When we see the first v4 (or first v6) member of a group, we re-trigger questions and probes on that interface.
- 3. When we see the last v4 (or v6) member of a group go away, we revalidate all the records received on that interface.
-
- Revision 1.105  2003/08/19 02:33:37  cheshire
- Update comments
-
- Revision 1.104  2003/08/19 02:31:11  cheshire
- <rdar://problem/3378386> mDNSResponder overenthusiastic with final expiration queries
- Final expiration queries now only mark the question for sending on the particular interface
- pertaining to the record that's expiring.
-
- Revision 1.103  2003/08/18 19:05:44  cheshire
- <rdar://problem/3382423> UpdateRecord not working right
- Added "newrdlength" field to hold new length of updated rdata
-
- Revision 1.102  2003/08/16 03:39:00  cheshire
- <rdar://problem/3338440> InterfaceID -1 indicates "local only"
-
- Revision 1.101  2003/08/15 20:16:02  cheshire
- <rdar://problem/3366590> mDNSResponder takes too much RPRVT
- We want to avoid touching the rdata pages, so we don't page them in.
- 1. RDLength was stored with the rdata, which meant touching the page just to find the length.
- Moved this from the RData to the ResourceRecord object.
- 2. To avoid unnecessarily touching the rdata just to compare it,
- compute a hash of the rdata and store the hash in the ResourceRecord object.
-
- Revision 1.100  2003/08/14 19:29:04  cheshire
- <rdar://problem/3378473> Include cache records in SIGINFO output
- Moved declarations of DNSTypeName() and GetRRDisplayString to mDNSClientAPI.h so daemon.c can use them
-
- Revision 1.99  2003/08/14 02:17:05  cheshire
- <rdar://problem/3375491> Split generic ResourceRecord type into two separate types: AuthRecord and CacheRecord
-
- Revision 1.98  2003/08/12 19:56:23  cheshire
- Update to APSL 2.0
-
- Revision 1.97  2003/08/12 14:59:27  cheshire
- <rdar://problem/3374490> Rate-limiting blocks some legitimate responses
- When setting LastMCTime also record LastMCInterface. When checking LastMCTime to determine
- whether to suppress the response, also check LastMCInterface to see if it matches.
-
- Revision 1.96  2003/08/12 13:57:04  cheshire
- <rdar://problem/3323817> Improve cache performance
- Changed the number of hash table slots from 37 to 499
-
- Revision 1.95  2003/08/09 00:55:02  cheshire
- <rdar://problem/3366553> mDNSResponder is taking 20-30% of the CPU
- Don't scan the whole cache after every packet.
-
- Revision 1.94  2003/08/09 00:35:29  cheshire
-
- Revision 1.93  2003/08/08 18:55:48  cheshire
- <rdar://problem/3370365> Guard against time going backwards
-
- Revision 1.92  2003/08/08 18:36:04  cheshire
- <rdar://problem/3344154> Only need to revalidate on interface removal on platforms that have the PhantomInterfaces bug
-
- Revision 1.91  2003/08/06 21:33:39  cheshire
- Fix compiler warnings on PocketPC 2003 (Windows CE)
-
- Revision 1.90  2003/08/06 20:30:17  cheshire
- Add structure definition for rdataMX (not currently used, but good to have it for completeness)
-
- Revision 1.89  2003/08/06 18:58:19  cheshire
- Update comments
-
- Revision 1.88  2003/07/24 23:45:44  cheshire
- To eliminate compiler warnings, changed definition of mDNSBool from
- "unsigned char" to "int", since "int" is in fact truly the type that C uses
- for the result of comparison operators (a<b) and logical operators (a||b)
-
- Revision 1.87  2003/07/22 23:57:20  cheshire
- Move platform-layer function prototypes from mDNSClientAPI.h to mDNSPlatformFunctions.h where they belong
-
- Revision 1.86  2003/07/20 03:52:02  ksekar
- Bug #: <rdar://problem/3320722>: Feature: New Rendezvous APIs (#7875) (mDNSResponder component)
- Added error type for incompatibility between daemon and client versions
-
- Revision 1.85  2003/07/19 03:23:13  cheshire
- <rdar://problem/2986147> mDNSResponder needs to receive and cache larger records
-
- Revision 1.84  2003/07/18 23:52:12  cheshire
- To improve consistency of field naming, global search-and-replace:
- NextProbeTime    -> NextScheduledProbe
- NextResponseTime -> NextScheduledResponse
-
- Revision 1.83  2003/07/18 00:29:59  cheshire
- <rdar://problem/3268878> Remove mDNSResponder version from packet header and use HINFO record instead
-
- Revision 1.82  2003/07/17 17:35:04  cheshire
- <rdar://problem/3325583> Rate-limit responses, to guard against packet flooding
-
- Revision 1.81  2003/07/16 05:01:36  cheshire
- Add fields 'LargeAnswers' and 'ExpectUnicastResponse' in preparation for
- <rdar://problem/3315761> Need to implement "unicast response" request, using top bit of qclass
-
- Revision 1.80  2003/07/15 01:55:12  cheshire
- <rdar://problem/3315777> Need to implement service registration with subtypes
-
- Revision 1.79  2003/07/13 02:28:00  cheshire
- <rdar://problem/3325166> SendResponses didn't all its responses
- Delete all references to RRInterfaceActive -- it's now superfluous
-
- Revision 1.78  2003/07/13 01:47:53  cheshire
- Fix one error and one warning in the Windows build
-
- Revision 1.77  2003/07/11 01:32:38  cheshire
- Syntactic cleanup (no change to funcationality): Now that we only have one host name,
- rename field "hostname1" to "hostname", and field "RR_A1" to "RR_A".
-
- Revision 1.76  2003/07/11 01:28:00  cheshire
- <rdar://problem/3161289> No more local.arpa
-
- Revision 1.75  2003/07/02 21:19:45  cheshire
- <rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
- Revision 1.74  2003/07/02 02:41:23  cheshire
- <rdar://problem/2986146> mDNSResponder needs to start with a smaller cache and then grow it as needed
-
- Revision 1.73  2003/06/10 04:24:39  cheshire
- <rdar://problem/3283637> React when we observe other people query unsuccessfully for a record that's in our cache
- Some additional refinements:
- Don't try to do this for unicast-response queries
- better tracking of Qs and KAs in multi-packet KA lists
-
- Revision 1.72  2003/06/10 01:46:27  cheshire
- Add better comments explaining how these data structures are intended to be used from the client layer
-
- Revision 1.71  2003/06/07 06:45:05  cheshire
- <rdar://problem/3283666> No need for multiple machines to all be sending the same queries
-
- Revision 1.70  2003/06/07 04:50:53  cheshire
- <rdar://problem/3283637> React when we observe other people query unsuccessfully for a record that's in our cache
-
- Revision 1.69  2003/06/07 04:22:17  cheshire
- Add MsgBuffer for error log and debug messages
-
- Revision 1.68  2003/06/07 01:46:38  cheshire
- <rdar://problem/3283540> When query produces zero results, call mDNS_Reconfirm() on any antecedent records
-
- Revision 1.67  2003/06/07 01:22:14  cheshire
- <rdar://problem/3283516> mDNSResponder needs an mDNS_Reconfirm() function
-
- Revision 1.66  2003/06/07 00:59:43  cheshire
- <rdar://problem/3283454> Need some randomness to spread queries on the network
-
- Revision 1.65  2003/06/06 21:41:11  cheshire
- For consistency, mDNS_StopQuery() should return an mStatus result, just like all the other mDNSCore routines
-
- Revision 1.64  2003/06/06 21:38:55  cheshire
- Renamed 'NewData' as 'FreshData' (The data may not be new data, just a refresh of data that we
- already had in our cache. This refreshes our TTL on the data, but the data itself stays the same.)
-
- Revision 1.63  2003/06/06 17:20:14  cheshire
- For clarity, rename question fields name/rrtype/rrclass as qname/qtype/qclass
- (Global search-and-replace; no functional change to code execution.)
-
- Revision 1.62  2003/06/04 01:25:33  cheshire
- <rdar://problem/3274950> Cannot perform multi-packet known-answer suppression messages
- Display time interval between first and subsequent queries
-
- Revision 1.61  2003/06/03 05:02:16  cheshire
- <rdar://problem/3277080> Duplicate registrations not handled as efficiently as they should be
-
- Revision 1.60  2003/05/31 00:09:49  cheshire
- <rdar://problem/3274862> Add ability to discover what services are on a network
-
- Revision 1.59  2003/05/29 06:11:35  cheshire
- <rdar://problem/3272214>:	Report if there appear to be too many "Resolve" callbacks
-
- Revision 1.58  2003/05/29 05:48:06  cheshire
- Minor fix for when generating printf warnings: mDNS_snprintf arguments are now 3,4
-
- Revision 1.57  2003/05/26 03:21:27  cheshire
- Tidy up address structure naming:
- mDNSIPAddr         => mDNSv4Addr (for consistency with mDNSv6Addr)
- mDNSAddr.addr.ipv4 => mDNSAddr.ip.v4
- mDNSAddr.addr.ipv6 => mDNSAddr.ip.v6
-
- Revision 1.56  2003/05/26 03:01:27  cheshire
- <rdar://problem/3268904> sprintf/vsprintf-style functions are unsafe; use snprintf/vsnprintf instead
-
- Revision 1.55  2003/05/26 00:47:30  cheshire
- Comment clarification
-
- Revision 1.54  2003/05/24 16:39:48  cheshire
- <rdar://problem/3268631> SendResponses also needs to handle multihoming better
-
- Revision 1.53  2003/05/23 02:15:37  cheshire
- Fixed misleading use of the term "duplicate suppression" where it should have
- said "known answer suppression". (Duplicate answer suppression is something
- different, and duplicate question suppression is yet another thing, so the use
- of the completely vague term "duplicate suppression" was particularly bad.)
-
- Revision 1.52  2003/05/22 02:29:22  cheshire
- <rdar://problem/2984918> SendQueries needs to handle multihoming better
- Complete rewrite of SendQueries. Works much better now :-)
-
- Revision 1.51  2003/05/21 20:14:55  cheshire
- Fix comments and warnings
-
- Revision 1.50  2003/05/14 07:08:36  cheshire
- <rdar://problem/3159272> mDNSResponder should be smarter about reconfigurations
- Previously, when there was any network configuration change, mDNSResponder
- would tear down the entire list of active interfaces and start again.
- That was very disruptive, and caused the entire cache to be flushed,
- and caused lots of extra network traffic. Now it only removes interfaces
- that have really gone, and only adds new ones that weren't there before.
-
- Revision 1.49  2003/05/07 01:49:36  cheshire
- Remove "const" in ConstructServiceName prototype
-
- Revision 1.48  2003/05/07 00:18:44  cheshire
- Fix typo: "kDNSQClass_Mask" should be "kDNSClass_Mask"
-
- Revision 1.47  2003/05/06 00:00:46  cheshire
- <rdar://problem/3248914> Rationalize naming of domainname manipulation functions
-
- Revision 1.46  2003/04/30 20:39:09  cheshire
- Add comment
-
- Revision 1.45  2003/04/29 00:40:50  cheshire
- Fix compiler warnings
-
- Revision 1.44  2003/04/26 02:41:56  cheshire
- <rdar://problem/3241281> Change timenow from a local variable to a structure member
-
- Revision 1.43  2003/04/25 01:45:56  cheshire
- <rdar://problem/3240002> mDNS_RegisterNoSuchService needs to include a host name
-
- Revision 1.42  2003/04/15 20:58:31  jgraessl
-
- Bug #: 3229014
- Added a hash to lookup records in the cache.
-
- Revision 1.41  2003/04/15 18:09:13  jgraessl
-
- Bug #: 3228892
- Reviewed by: Stuart Cheshire
- Added code to keep track of when the next cache item will expire so we can
- call TidyRRCache only when necessary.
-
- Revision 1.40  2003/03/29 01:55:19  cheshire
- <rdar://problem/3212360> mDNSResponder sometimes suffers false self-conflicts when it sees its own packets
- Solution: Major cleanup of packet timing and conflict handling rules
-
- Revision 1.39  2003/03/27 03:30:55  cheshire
- <rdar://problem/3210018> Name conflicts not handled properly, resulting in memory corruption, and eventual crash
- Problem was that HostNameCallback() was calling mDNS_DeregisterInterface(), which is not safe in a callback
- Fixes:
- 1. Make mDNS_DeregisterInterface() safe to call from a callback
- 2. Make HostNameCallback() use mDNS_DeadvertiseInterface() instead
- (it never really needed to deregister the interface at all)
-
- Revision 1.38  2003/03/15 04:40:36  cheshire
- Change type called "mDNSOpaqueID" to the more descriptive name "mDNSInterfaceID"
-
- Revision 1.37  2003/03/14 21:34:11  cheshire
- <rdar://problem/3176950> Can't setup and print to Lexmark PS printers via Airport Extreme
- Increase size of cache rdata from 512 to 768
-
- Revision 1.36  2003/03/05 03:38:35  cheshire
- Bug #: 3185731 Bogus error message in console: died or deallocated, but no record of client can be found!
- Fixed by leaving client in list after conflict, until client explicitly deallocates
-
- Revision 1.35  2003/02/21 02:47:54  cheshire
- Bug #: 3099194 mDNSResponder needs performance improvements
- Several places in the code were calling CacheRRActive(), which searched the entire
- question list every time, to see if this cache resource record answers any question.
- Instead, we now have a field "CRActiveQuestion" in the resource record structure
-
- Revision 1.34  2003/02/21 01:54:08  cheshire
- Bug #: 3099194 mDNSResponder needs performance improvements
- Switched to using new "mDNS_Execute" model (see "Implementer Notes.txt")
-
- Revision 1.33  2003/02/20 06:48:32  cheshire
- Bug #: 3169535 Xserve RAID needs to do interface-specific registrations
- Reviewed by: Josh Graessley, Bob Bradley
-
- Revision 1.32  2003/01/31 03:35:59  cheshire
- Bug #: 3147097 mDNSResponder sometimes fails to find the correct results
- When there were *two* active questions in the list, they were incorrectly
- finding *each other* and *both* being marked as duplicates of another question
-
- Revision 1.31  2003/01/29 02:46:37  cheshire
- Fix for IPv6:
- A physical interface is identified solely by its InterfaceID (not by IP and type).
- On a given InterfaceID, mDNSCore may send both v4 and v6 multicasts.
- In cases where the requested outbound protocol (v4 or v6) is not supported on
- that InterfaceID, the platform support layer should simply discard that packet.
-
- Revision 1.30  2003/01/29 01:47:08  cheshire
- Rename 'Active' to 'CRActive' or 'InterfaceActive' for improved clarity
-
- Revision 1.29  2003/01/28 05:23:43  cheshire
- Bug #: 3147097 mDNSResponder sometimes fails to find the correct results
- Add 'Active' flag for interfaces
-
- Revision 1.28  2003/01/28 01:35:56  cheshire
- Revise comment about ThisQInterval to reflect new semantics
-
- Revision 1.27  2003/01/13 23:49:42  jgraessl
- Merged changes for the following fixes in to top of tree:
- 3086540  computer name changes not handled properly
- 3124348  service name changes are not properly handled
- 3124352  announcements sent in pairs, failing chattiness test
-
- Revision 1.26  2002/12/23 22:13:28  jgraessl
-
- Reviewed by: Stuart Cheshire
- Initial IPv6 support for mDNSResponder.
-
- Revision 1.25  2002/09/21 20:44:49  zarzycki
- Added APSL info
-
- Revision 1.24  2002/09/19 23:47:35  cheshire
- Added mDNS_RegisterNoSuchService() function for assertion of non-existance
- of a particular named service
-
- Revision 1.23  2002/09/19 21:25:34  cheshire
- mDNS_snprintf() doesn't need to be in a separate file
-
- Revision 1.22  2002/09/19 04:20:43  cheshire
- Remove high-ascii characters that confuse some systems
-
- Revision 1.21  2002/09/17 01:06:35  cheshire
- Change mDNS_AdvertiseLocalAddresses to be a parameter to mDNS_Init()
-
- Revision 1.20  2002/09/16 18:41:41  cheshire
- Merge in license terms from Quinn's copy, in preparation for Darwin release
-
-*/
-
-#ifndef __mDNSClientAPI_h
-#define __mDNSClientAPI_h
-
-#include <stdarg.h>		// stdarg.h is required for for va_list support for the mDNS_vsnprintf declaration
-#include "mDNSDebug.h"
-
-#ifdef	__cplusplus
-extern "C" {
-#endif
-
-// ***************************************************************************
-// Function scope indicators
-
-// If you see "mDNSlocal" before a function name in a C file, it means the function is not callable outside this file
-#ifndef mDNSlocal
-#define mDNSlocal static
-#endif
-// If you see "mDNSexport" before a symbol in a C file, it means the symbol is exported for use by clients
-// For every "mDNSexport" in a C file, there needs to be a corresponding "extern" declaration in some header file
-// (When a C file #includes a header file, the "extern" declarations tell the compiler:
-// "This symbol exists -- but not necessarily in this C file.")
-#ifndef mDNSexport
-#define mDNSexport
-#endif
-
-// ***************************************************************************
-// Structure packing macro
-
-// If we're not using GNUC, it's not fatal.
-// Most compilers naturally pack the on-the-wire structures correctly anyway, so a plain "struct" is usually fine.
-// In the event that structures are not packed correctly, mDNS_Init() will detect this and report an error, so the
-// developer will know what's wrong, and can investigate what needs to be done on that compiler to provide proper packing.
-#ifndef packedstruct
-#if ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9)))
-#define packedstruct struct __attribute__((__packed__))
-#define packedunion  union  __attribute__((__packed__))
-#else
-#define packedstruct struct
-#define packedunion  union
-#endif
-#endif
-
-// ***************************************************************************
-#if 0
-#pragma mark - DNS Resource Record class and type constants
-#endif
-
-	typedef enum							// From RFC 1035
-	{
-		kDNSClass_IN               = 1,		// Internet
-		kDNSClass_CS               = 2,		// CSNET
-		kDNSClass_CH               = 3,		// CHAOS
-		kDNSClass_HS               = 4,		// Hesiod
-		kDNSClass_NONE             = 254,	// Used in DNS UPDATE [RFC 2136]
-
-		kDNSClass_Mask             = 0x7FFF,// Multicast DNS uses the bottom 15 bits to identify the record class...
-		kDNSClass_UniqueRRSet      = 0x8000,// ... and the top bit indicates that all other cached records are now invalid
-
-		kDNSQClass_ANY             = 255,	// Not a DNS class, but a DNS query class, meaning "all classes"
-		kDNSQClass_UnicastResponse = 0x8000	// Top bit set in a question means "unicast response acceptable"
-	} DNS_ClassValues;
-
-	typedef enum				// From RFC 1035
-	{
-		kDNSType_A = 1,			//  1 Address
-		kDNSType_NS,			//  2 Name Server
-		kDNSType_MD,			//  3 Mail Destination
-		kDNSType_MF,			//  4 Mail Forwarder
-		kDNSType_CNAME,			//  5 Canonical Name
-		kDNSType_SOA,			//  6 Start of Authority
-		kDNSType_MB,			//  7 Mailbox
-		kDNSType_MG,			//  8 Mail Group
-		kDNSType_MR,			//  9 Mail Rename
-		kDNSType_NULL,			// 10 NULL RR
-		kDNSType_WKS,			// 11 Well-known-service
-		kDNSType_PTR,			// 12 Domain name pointer
-		kDNSType_HINFO,			// 13 Host information
-		kDNSType_MINFO,			// 14 Mailbox information
-		kDNSType_MX,			// 15 Mail Exchanger
-		kDNSType_TXT,			// 16 Arbitrary text string
-
-		kDNSType_AAAA = 28,		// 28 IPv6 address
-		kDNSType_SRV = 33,		// 33 Service record
-
-		kDNSQType_ANY = 255		// Not a DNS type, but a DNS query type, meaning "all types"
-	} DNS_TypeValues;
-
-// ***************************************************************************
-#if 0
-#pragma mark - Simple types
-#endif
-
-// mDNS defines its own names for these common types to simplify portability across
-// multiple platforms that may each have their own (different) names for these types.
-	typedef          int   mDNSBool;
-	typedef   signed char  mDNSs8;
-	typedef unsigned char  mDNSu8;
-	typedef   signed short mDNSs16;
-	typedef unsigned short mDNSu16;
-#if _LP64
-	typedef   signed int   mDNSs32;
-	typedef unsigned int   mDNSu32;
-#else
-	typedef   signed long  mDNSs32;
-	typedef unsigned long  mDNSu32;
-#endif
-
-// To enforce useful type checking, we make mDNSInterfaceID be a pointer to a dummy struct
-// This way, mDNSInterfaceIDs can be assigned, and compared with each other, but not with other types
-// Declaring the type to be the typical generic "void *" would lack this type checking
-	typedef struct mDNSInterfaceID_dummystruct { void *dummy; } *mDNSInterfaceID;
-
-// These types are for opaque two- and four-byte identifiers.
-// The "NotAnInteger" fields of the unions allow the value to be conveniently passed around in a
-// register for the sake of efficiency, and compared for equality or inequality, but don't forget --
-// just because it is in a register doesn't mean it is an integer. Operations like greater than,
-// less than, add, multiply, increment, decrement, etc., are undefined for opaque identifiers,
-// and if you make the mistake of trying to do those using the NotAnInteger field, then you'll
-// find you get code that doesn't work consistently on big-endian and little-endian machines.
-	typedef packedunion { mDNSu8 b[2]; mDNSu16 NotAnInteger; } mDNSOpaque16;
-	typedef packedunion { mDNSu8 b[4]; mDNSu32 NotAnInteger; } mDNSOpaque32;
-	typedef packedunion { mDNSu8 b[16]; mDNSu16 w[8]; mDNSu32 l[4]; } mDNSOpaque128;
-
-	typedef mDNSOpaque16  mDNSIPPort;		// An IP port is a two-byte opaque identifier (not an integer)
-	typedef mDNSOpaque32  mDNSv4Addr;		// An IP address is a four-byte opaque identifier (not an integer)
-	typedef mDNSOpaque128 mDNSv6Addr;		// An IPv6 address is a 16-byte opaque identifier (not an integer)
-
-	enum
-	{
-		mDNSAddrType_None    = 0,
-		mDNSAddrType_IPv4    = 4,
-		mDNSAddrType_IPv6    = 6,
-		mDNSAddrType_Unknown = ~0	// Special marker value used in known answer list recording
-	};
-
-	typedef struct
-	{
-		mDNSs32 type;
-		union { mDNSv6Addr v6; mDNSv4Addr v4; } ip;
-	} mDNSAddr;
-
-	enum { mDNSfalse = 0, mDNStrue = 1 };
-
-#define mDNSNULL 0L
-
-	enum
-	{
-		mStatus_Waiting           = 1,
-		mStatus_NoError           = 0,
-
-		// mDNS return values are in the range FFFE FF00 (-65792) to FFFE FFFF (-65537)
-		// The top end of the range (FFFE FFFF) is used for error codes;
-		// the bottom end of the range (FFFE FF00) is used for non-error values;
-
-		// Error codes:
-		mStatus_UnknownErr        = -65537,		// 0xFFFE FFFF
-		mStatus_NoSuchNameErr     = -65538,
-		mStatus_NoMemoryErr       = -65539,
-		mStatus_BadParamErr       = -65540,
-		mStatus_BadReferenceErr   = -65541,
-		mStatus_BadStateErr       = -65542,
-		mStatus_BadFlagsErr       = -65543,
-		mStatus_UnsupportedErr    = -65544,
-		mStatus_NotInitializedErr = -65545,
-		mStatus_NoCache           = -65546,
-		mStatus_AlreadyRegistered = -65547,
-		mStatus_NameConflict      = -65548,
-		mStatus_Invalid           = -65549,
-		//                        = -65550,
-		mStatus_Incompatible      = -65551,
-		mStatus_BadInterfaceErr   = -65552,
-
-		// -65553 - -65789 currently unused
-
-		// Non-error values:
-		mStatus_GrowCache         = -65790,
-		mStatus_ConfigChanged     = -65791,
-		mStatus_MemFree           = -65792		// 0xFFFE FF00
-	};
-
-	typedef mDNSs32 mStatus;
-
-// RFC 1034/1035 specify that a domain label consists of a length byte plus up to 63 characters
-#define MAX_DOMAIN_LABEL 63
-	typedef struct { mDNSu8 c[ 64]; } domainlabel;		// One label: length byte and up to 63 characters
-
-// RFC 1034/1035 specify that a domain name, including length bytes, data bytes, and terminating zero, may be up to 255 bytes long
-#define MAX_DOMAIN_NAME 255
-	typedef struct { mDNSu8 c[256]; } domainname;		// Up to 255 bytes of length-prefixed domainlabels
-
-	typedef struct { mDNSu8 c[256]; } UTF8str255;		// Null-terminated C string
-
-// The longest legal textual form of a DNS name is 1005 bytes, including the C-string terminating NULL at the end.
-// Explanation:
-// When a native domainname object is converted to printable textual form using ConvertDomainNameToCString(),
-// non-printing characters are represented in the conventional DNS way, as '\ddd', where ddd is a three-digit decimal number.
-// The longest legal domain name is 255 bytes, in the form of four labels as shown below:
-// Length byte, 63 data bytes, length byte, 63 data bytes, length byte, 63 data bytes, length byte, 61 data bytes, zero byte.
-// Each label is encoded textually as characters followed by a trailing dot.
-// If every character has to be represented as a four-byte escape sequence, then this makes the maximum textual form four labels
-// plus the C-string terminating NULL as shown below:
-// 63*4+1 + 63*4+1 + 63*4+1 + 61*4+1 + 1 = 1005.
-// Note that MAX_ESCAPED_DOMAIN_LABEL is not normally used: If you're only decoding a single label, escaping is usually not required.
-// It is for domain names, where dots are used as label separators, that proper escaping is vital.
-#define MAX_ESCAPED_DOMAIN_LABEL 254
-#define MAX_ESCAPED_DOMAIN_NAME 1005
-
-// ***************************************************************************
-#if 0
-#pragma mark - Resource Record structures
-#endif
-
-// Authoritative Resource Records:
-// There are four basic types: Shared, Advisory, Unique, Known Unique
-
-// * Shared Resource Records do not have to be unique
-// -- Shared Resource Records are used for DNS-SD service PTRs
-// -- It is okay for several hosts to have RRs with the same name but different RDATA
-// -- We use a random delay on responses to reduce collisions when all the hosts respond to the same query
-// -- These RRs typically have moderately high TTLs (e.g. one hour)
-// -- These records are announced on startup and topology changes for the benefit of passive listeners
-// -- These records send a goodbye packet when deregistering
-//
-// * Advisory Resource Records are like Shared Resource Records, except they don't send a goodbye packet
-//
-// * Unique Resource Records should be unique among hosts within any given mDNS scope
-// -- The majority of Resource Records are of this type
-// -- If two entities on the network have RRs with the same name but different RDATA, this is a conflict
-// -- Responses may be sent immediately, because only one host should be responding to any particular query
-// -- These RRs typically have low TTLs (e.g. ten seconds)
-// -- On startup and after topology changes, a host issues queries to verify uniqueness
-
-// * Known Unique Resource Records are treated like Unique Resource Records, except that mDNS does
-// not have to verify their uniqueness because this is already known by other means (e.g. the RR name
-// is derived from the host's IP or Ethernet address, which is already known to be a unique identifier).
-
-// Summary of properties of different record types:
-// Probe?    Does this record type send probes before announcing?
-// Conflict? Does this record type react if we observe an apparent conflict?
-// Goodbye?  Does this record type send a goodbye packet on departure?
-//
-//               Probe? Conflict? Goodbye? Notes
-// Unregistered                            Should not appear in any list (sanity check value)
-// Shared         No      No       Yes     e.g. Service PTR record
-// Deregistering  No      No       Yes     Shared record about to announce its departure and leave the list
-// Advisory       No      No       No
-// Unique         Yes     Yes      No      Record intended to be unique -- will probe to verify
-// Verified       Yes     Yes      No      Record has completed probing, and is verified unique
-// KnownUnique    No      Yes      No      Record is assumed by other means to be unique
-
-// Valid lifecycle of a record:
-// Unregistered ->                   Shared      -> Deregistering -(goodbye)-> Unregistered
-// Unregistered ->                   Advisory                               -> Unregistered
-// Unregistered -> Unique -(probe)-> Verified                               -> Unregistered
-// Unregistered ->                   KnownUnique                            -> Unregistered
-
-// Each Authoritative kDNSRecordType has only one bit set. This makes it easy to quickly see if a record
-// is one of a particular set of types simply by performing the appropriate bitwise masking operation.
-
-// Cache Resource Records (received from the network):
-// There are four basic types: Answer, Unique Answer, Additional, Unique Additional
-// Bit 7 (the top bit) of kDNSRecordType is always set for Cache Resource Records; always clear for Authoritative Resource Records
-// Bit 6 (value 0x40) is set for answer records; clear for additional records
-// Bit 5 (value 0x20) is set for records received with the kDNSClass_UniqueRRSet
-
-	enum
-	{
-		kDNSRecordTypeUnregistered     = 0x00,	// Not currently in any list
-		kDNSRecordTypeDeregistering    = 0x01,	// Shared record about to announce its departure and leave the list
-
-		kDNSRecordTypeUnique           = 0x02,	// Will become a kDNSRecordTypeVerified when probing is complete
-
-		kDNSRecordTypeAdvisory         = 0x04,	// Like Shared, but no goodbye packet
-		kDNSRecordTypeShared           = 0x08,	// Shared means record name does not have to be unique -- use random delay on responses
-		kDNSRecordTypeVerified         = 0x10,	// Unique means mDNS should check that name is unique (and then send immediate responses)
-		kDNSRecordTypeKnownUnique      = 0x20,	// Known Unique means mDNS can assume name is unique without checking
-
-		kDNSRecordTypeUniqueMask       = (kDNSRecordTypeUnique | kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique),
-		kDNSRecordTypeActiveMask       = (kDNSRecordTypeAdvisory | kDNSRecordTypeShared | kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique),
-
-		kDNSRecordTypePacketAdd        = 0x80,	// Received in the Additional Section of a DNS Response
-		kDNSRecordTypePacketAddUnique  = 0xA0,	// Received in the Additional Section of a DNS Response with kDNSClass_UniqueRRSet set
-		kDNSRecordTypePacketAns        = 0xC0,	// Received in the Answer Section of a DNS Response
-		kDNSRecordTypePacketAnsUnique  = 0xE0,	// Received in the Answer Section of a DNS Response with kDNSClass_UniqueRRSet set
-
-		kDNSRecordTypePacketAnsMask    = 0x40,	// True for PacketAns       and PacketAnsUnique
-		kDNSRecordTypePacketUniqueMask = 0x20	// True for PacketAddUnique and PacketAnsUnique
-	};
-
-	typedef packedstruct { mDNSu16 priority; mDNSu16 weight; mDNSIPPort port; domainname target; } rdataSRV;
-	typedef packedstruct { mDNSu16 preference; domainname exchange; } rdataMX;
-
-// StandardAuthRDSize is 264 (256+8), which is large enough to hold a maximum-sized SRV record
-// MaximumRDSize is 8K the absolute maximum we support (at least for now)
-#define StandardAuthRDSize 264
-#define MaximumRDSize 8192
-
-// InlineCacheRDSize is 64
-// Records received from the network with rdata this size or less have their rdata stored right in the CacheRecord object
-// Records received from the network with rdata larger than this have additional storage allocated for the rdata
-// A quick unscientific sample from a busy network at Apple with lots of machines revealed this:
-// 1461 records in cache
-// 292 were one-byte TXT records
-// 136 were four-byte A records
-// 184 were sixteen-byte AAAA records
-// 780 were various PTR, TXT and SRV records from 12-64 bytes
-// Only 69 records had rdata bigger than 64 bytes
-#define InlineCacheRDSize 64
-
-	typedef union
-	{
-		mDNSu8      data[StandardAuthRDSize];
-		mDNSv4Addr  ip;			// For 'A' record
-		mDNSv6Addr  ipv6;		// For 'AAAA' record
-		domainname  name;		// For PTR and CNAME records
-		UTF8str255  txt;		// For TXT record
-		rdataSRV    srv;		// For SRV record
-		rdataMX     mx;			// For MX record
-	} RDataBody;
-
-	typedef struct
-	{
-		mDNSu16    MaxRDLength;	// Amount of storage allocated for rdata (usually sizeof(RDataBody))
-		RDataBody  u;
-	} RData;
-#define sizeofRDataHeader (sizeof(RData) - sizeof(RDataBody))
-
-	typedef struct AuthRecord_struct AuthRecord;
-	typedef struct CacheRecord_struct CacheRecord;
-	typedef struct ResourceRecord_struct ResourceRecord;
-	typedef struct DNSQuestion_struct DNSQuestion;
-	typedef struct mDNS_struct mDNS;
-	typedef struct mDNS_PlatformSupport_struct mDNS_PlatformSupport;
-
-// Note: Within an mDNSRecordCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Close(), mDNS_Execute() 
-	typedef void mDNSRecordCallback(mDNS *const m, AuthRecord *const rr, mStatus result);
-
-// Note:
-// Restrictions: An mDNSRecordUpdateCallback may not make any mDNS API calls.
-// The intent of this callback is to allow the client to free memory, if necessary.
-// The internal data structures of the mDNS code may not be in a state where mDNS API calls may be made safely.
-	typedef void mDNSRecordUpdateCallback(mDNS *const m, AuthRecord *const rr, RData *OldRData);
-
-	struct ResourceRecord_struct
-	{
-		mDNSu8          RecordType;			// See enum above
-		mDNSInterfaceID InterfaceID;		// Set if this RR is specific to one interface
-		// For records received off the wire, InterfaceID is *always* set to the receiving interface
-		// For our authoritative records, InterfaceID is usually zero, except for those few records
-		// that are interface-specific (e.g. address records, especially linklocal addresses)
-		domainname      name;				
-		mDNSu16         rrtype;
-		mDNSu16         rrclass;
-		mDNSu32         rroriginalttl;		// In seconds
-		mDNSu16         rdlength;			// Size of the raw rdata, in bytes
-		mDNSu16         rdestimate;			// Upper bound on size of rdata after name compression
-		mDNSu32         namehash;			// Name-based (i.e. case insensitive) hash of name
-		mDNSu32         rdatahash;			// 32-bit hash of the raw rdata
-		mDNSu32         rdnamehash;			// Set if this rdata contains a domain name (e.g. PTR, SRV, CNAME etc.)
-		mDNSAddr	addr;				// Shiro, keeping sender ip here
-		RData           *rdata;				// Pointer to storage for this rdata
-	};
-
-	struct AuthRecord_struct
-	{
-		// For examples of how to set up this structure for use in mDNS_Register(),
-		// see mDNS_AdvertiseInterface() or mDNS_RegisterService().
-		// Basically, resrec and persistent metadata need to be set up before calling mDNS_Register().
-		// mDNS_SetupResourceRecord() is avaliable as a helper routine to set up most fields to sensible default values for you
-
-		AuthRecord     *next;				// Next in list; first element of structure for efficiency reasons
-		ResourceRecord  resrec;
-
-		// Persistent metadata for Authoritative Records
-		AuthRecord     *Additional1;		// Recommended additional record to include in response
-		AuthRecord     *Additional2;		// Another additional
-		AuthRecord     *DependentOn;		// This record depends on another for its uniqueness checking
-		AuthRecord     *RRSet;				// This unique record is part of an RRSet
-		mDNSRecordCallback *RecordCallback;	// Callback function to call for state changes
-		void           *RecordContext;		// Context parameter for the callback function
-		mDNSu8          HostTarget;			// Set if the target of this record (PTR, CNAME, SRV, etc.) is our host name
-
-		// Transient state for Authoritative Records
-		mDNSu8          Acknowledged;		// Set if we've given the success callback to the client
-		mDNSu8          ProbeCount;			// Number of probes remaining before this record is valid (kDNSRecordTypeUnique)
-		mDNSu8          AnnounceCount;		// Number of announcements remaining (kDNSRecordTypeShared)
-		mDNSu8          IncludeInProbe;		// Set if this RR is being put into a probe right now
-		mDNSInterfaceID ImmedAnswer;		// Someone on this interface issued a query we need to answer (all-ones for all interfaces)
-		mDNSInterfaceID ImmedAdditional;	// Hint that we might want to also send this record, just to be helpful
-		mDNSInterfaceID SendRNow;			// The interface this query is being sent on right now
-		mDNSv4Addr      v4Requester;		// Recent v4 query for this record, or all-ones if more than one recent query
-		mDNSv6Addr      v6Requester;		// Recent v6 query for this record, or all-ones if more than one recent query
-		AuthRecord     *NextResponse;		// Link to the next element in the chain of responses to generate
-		const mDNSu8   *NR_AnswerTo;		// Set if this record was selected by virtue of being a direct answer to a question
-		AuthRecord     *NR_AdditionalTo;	// Set if this record was selected by virtue of being additional to another
-		mDNSs32         ThisAPInterval;		// In platform time units: Current interval for announce/probe
-		mDNSs32         AnnounceUntil;		// In platform time units: Creation time + TTL
-		mDNSs32         LastAPTime;			// In platform time units: Last time we sent announcement/probe
-		mDNSs32         LastMCTime;			// Last time we multicast this record (used to guard against packet-storm attacks)
-		mDNSInterfaceID LastMCInterface;	// Interface this record was multicast on at the time LastMCTime was recorded
-		RData          *NewRData;			// Set if we are updating this record with new rdata
-		mDNSu16         newrdlength;		// ... and the length of the new RData
-		mDNSRecordUpdateCallback *UpdateCallback;
-		mDNSu32         UpdateCredits;		// Token-bucket rate limiting of excessive updates
-		mDNSs32         NextUpdateCredit;	// Time next token is added to bucket
-		mDNSs32         UpdateBlocked;		// Set if update delaying is in effect
-
-		RData           rdatastorage;		// Normally the storage is right here, except for oversized records
-		// rdatastorage MUST be the last thing in the structure -- when using oversized AuthRecords, extra bytes
-		// are appended after the end of the AuthRecord, logically augmenting the size of the rdatastorage
-		// DO NOT ADD ANY MORE FIELDS HERE
-	};
-
-	struct CacheRecord_struct
-	{
-		CacheRecord    *next;				// Next in list; first element of structure for efficiency reasons
-		ResourceRecord  resrec;
-
-		// Transient state for Cache Records
-		CacheRecord    *NextInKAList;		// Link to the next element in the chain of known answers to send
-		mDNSs32         TimeRcvd;			// In platform time units
-		mDNSs32         NextRequiredQuery;	// In platform time units
-		mDNSs32         LastUsed;			// In platform time units
-		mDNSu32         UseCount;			// Number of times this RR has been used to answer a question
-		DNSQuestion    *CRActiveQuestion;	// Points to an active question referencing this answer
-		mDNSu32         UnansweredQueries;	// Number of times we've issued a query for this record without getting an answer
-		mDNSs32         LastUnansweredTime;	// In platform time units; last time we incremented UnansweredQueries
-		mDNSu32         MPUnansweredQ;		// Multi-packet query handling: Number of times we've seen a query for this record
-		mDNSs32         MPLastUnansweredQT;	// Multi-packet query handling: Last time we incremented MPUnansweredQ
-		mDNSu32         MPUnansweredKA;		// Multi-packet query handling: Number of times we've seen this record in a KA list
-		mDNSBool        MPExpectingKA;		// Multi-packet query handling: Set when we increment MPUnansweredQ; allows one KA
-		CacheRecord    *NextInCFList;		// Set if this is in the list of records we just received with the cache flush bit set
-
-
-		struct { mDNSu16 MaxRDLength; mDNSu8 data[InlineCacheRDSize]; } rdatastorage;	// Storage for small records is right here
-	};
-
-	typedef struct
-	{
-		CacheRecord r;
-		mDNSu8 _extradata[MaximumRDSize-InlineCacheRDSize];		// Glue on the necessary number of extra bytes
-	} LargeCacheRecord;
-
-	typedef struct NetworkInterfaceInfo_struct NetworkInterfaceInfo;
-
-	struct NetworkInterfaceInfo_struct
-	{
-		// Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
-		NetworkInterfaceInfo *next;
-
-		mDNSBool        InterfaceActive;	// InterfaceActive is set if interface is sending & receiving packets
-		// InterfaceActive is clear if interface is here to represent an address with A
-		// and/or AAAA records, but there is already an earlier representative for this
-		// physical interface which will be used for the actual sending & receiving
-		// packets (this status may change as interfaces are added and removed)
-		mDNSBool        IPv4Available;		// If InterfaceActive, set if v4 available on this InterfaceID
-		mDNSBool        IPv6Available;		// If InterfaceActive, set if v6 available on this InterfaceID
-
-		// Standard AuthRecords that every Responder host should have (one per active IP address)
-		AuthRecord RR_A;					// 'A' or 'AAAA' (address) record for our ".local" name
-		AuthRecord RR_PTR;					// PTR (reverse lookup) record
-		AuthRecord RR_HINFO;
-
-		// Client API fields: The client must set up these fields *before* calling mDNS_RegisterInterface()
-		mDNSInterfaceID InterfaceID;
-		mDNSAddr        ip;
-		mDNSBool        Advertise;			// Set Advertise to false if you are only searching on this interface
-		mDNSBool        TxAndRx;			// Set to false if not sending and receiving packets on this interface
-	};
-
-	typedef struct ExtraResourceRecord_struct ExtraResourceRecord;
-	struct ExtraResourceRecord_struct
-	{
-		ExtraResourceRecord *next;
-		AuthRecord r;
-		// Note: Add any additional fields *before* the AuthRecord in this structure, not at the end.
-		// In some cases clients can allocate larger chunks of memory and set r->rdata->MaxRDLength to indicate
-		// that this extra memory is available, which would result in any fields after the AuthRecord getting smashed
-	};
-
-// Note: Within an mDNSServiceCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Close(), mDNS_Execute() 
-	typedef struct ServiceRecordSet_struct ServiceRecordSet;
-	typedef void mDNSServiceCallback(mDNS *const m, ServiceRecordSet *const sr, mStatus result);
-	struct ServiceRecordSet_struct
-	{
-		// Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
-		// No fields need to be set up by the client prior to calling mDNS_RegisterService();
-		// all required data is passed as parameters to that function.
-		mDNSServiceCallback *ServiceCallback;
-		void                *ServiceContext;
-		ExtraResourceRecord *Extras;	// Optional list of extra AuthRecords attached to this service registration
-		mDNSu32              NumSubTypes;
-		AuthRecord          *SubTypes;
-		mDNSBool             Conflict;	// Set if this record set was forcibly deregistered because of a conflict
-		domainname           Host;		// Set if this service record does not use the standard target host name
-		AuthRecord           RR_ADV;	// e.g. _services._dns-sd._udp.local. PTR _printer._tcp.local.
-		AuthRecord           RR_PTR;	// e.g. _printer._tcp.local.        PTR Name._printer._tcp.local.
-		AuthRecord           RR_SRV;	// e.g. Name._printer._tcp.local.   SRV 0 0 port target
-		AuthRecord           RR_TXT;	// e.g. Name._printer._tcp.local.   TXT PrintQueueName
-		// Don't add any fields after AuthRecord RR_TXT.
-		// This is where the implicit extra space goes if we allocate a ServiceRecordSet containing an oversized RR_TXT record
-	};
-
-// ***************************************************************************
-#if 0
-#pragma mark - Question structures
-#endif
-
-// We record the last eight instances of each duplicate query
-// This gives us v4/v6 on each of Ethernet/AirPort and Firewire, and two free slots "for future expansion"
-// If the host has more active interfaces that this it is not fatal -- duplicate question suppression will degrade gracefully.
-// Since we will still remember the last eight, the busiest interfaces will still get the effective duplicate question suppression.
-#define DupSuppressInfoSize 8
-
-	typedef struct
-	{
-		mDNSs32               Time;
-		mDNSInterfaceID       InterfaceID;
-		mDNSs32               Type;				// v4 or v6?
-	} DupSuppressInfo;
-
-// Note: Within an mDNSQuestionCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Close(), mDNS_Execute() 
-	typedef void mDNSQuestionCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord);
-	struct DNSQuestion_struct
-	{
-		// Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
-		DNSQuestion          *next;
-		mDNSu32               qnamehash;
-		mDNSs32               LastQTime;		// Last scheduled transmission of this Q on *all* applicable interfaces
-		mDNSs32               ThisQInterval;	// LastQTime + ThisQInterval is the next scheduled transmission of this Q
-		// ThisQInterval > 0 for an active question;
-		// ThisQInterval = 0 for a suspended question that's still in the list
-		// ThisQInterval = -1 for a cancelled question that's been removed from the list
-		mDNSu32               RecentAnswers;	// Number of answers since the last time we sent this query
-		mDNSu32               CurrentAnswers;	// Number of records currently in the cache that answer this question
-		mDNSu32               LargeAnswers;		// Number of answers with rdata > 1024 bytes
-		mDNSu32               UniqueAnswers;	// Number of answers received with kDNSClass_UniqueRRSet bit set
-		DNSQuestion          *DuplicateOf;
-		DNSQuestion          *NextInDQList;
-		DupSuppressInfo       DupSuppress[DupSuppressInfoSize];
-		mDNSInterfaceID       SendQNow;			// The interface this query is being sent on right now
-		mDNSBool              SendOnAll;		// Set if we're sending this question on all active interfaces
-		mDNSs32               LastQTxTime;		// Last time this Q was sent on one (but not necessarily all) interfaces
-
-		// Client API fields: The client must set up these fields *before* calling mDNS_StartQuery()
-		mDNSInterfaceID       InterfaceID;		// Non-zero if you want to issue link-local queries only on a single specific IP interface
-		domainname            qname;
-		mDNSu16               qtype;
-		mDNSu16               qclass;
-		mDNSQuestionCallback *QuestionCallback;
-		void                 *QuestionContext;
-	};
-
-	typedef struct
-	{
-		// Client API fields: The client must set up name and InterfaceID *before* calling mDNS_StartResolveService()
-		// When the callback is invoked, ip, port, TXTlen and TXTinfo will have been filled in with the results learned from the network.
-		domainname      name;
-		mDNSInterfaceID InterfaceID;		// ID of the interface the response was received on
-		mDNSAddr        ip;					// Remote (destination) IP address where this service can be accessed
-		mDNSIPPort      port;				// Port where this service can be accessed
-		mDNSu16         TXTlen;
-		mDNSu8          TXTinfo[2048];		// Additional demultiplexing information (e.g. LPR queue name)
-	} ServiceInfo;
-
-// Note: Within an mDNSServiceInfoQueryCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Close(), mDNS_Execute() 
-	typedef struct ServiceInfoQuery_struct ServiceInfoQuery;
-	typedef void mDNSServiceInfoQueryCallback(mDNS *const m, ServiceInfoQuery *query);
-	struct ServiceInfoQuery_struct
-	{
-		// Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
-		// No fields need to be set up by the client prior to calling mDNS_StartResolveService();
-		// all required data is passed as parameters to that function.
-		// The ServiceInfoQuery structure memory is working storage for mDNSCore to discover the requested information
-		// and place it in the ServiceInfo structure. After the client has called mDNS_StopResolveService(), it may
-		// dispose of the ServiceInfoQuery structure while retaining the results in the ServiceInfo structure.
-		DNSQuestion                   qSRV;
-		DNSQuestion                   qTXT;
-		DNSQuestion                   qAv4;
-		DNSQuestion                   qAv6;
-		mDNSu8                        GotSRV;
-		mDNSu8                        GotTXT;
-		mDNSu8                        GotADD;
-		mDNSu32                       Answers;
-		ServiceInfo                  *info;
-		mDNSServiceInfoQueryCallback *ServiceInfoQueryCallback;
-		void                         *ServiceInfoQueryContext;
-	};
-
-// ***************************************************************************
-#if 0
-#pragma mark - Main mDNS object, used to hold all the mDNS state
-#endif
-
-	typedef void mDNSCallback(mDNS *const m, mStatus result);
-
-#define CACHE_HASH_SLOTS 20//499
-
-	enum
-	{
-		mDNS_KnownBug_PhantomInterfaces = 1
-	};
-
-	struct mDNS_struct
-	{
-		// Internal state fields. These hold the main internal state of mDNSCore;
-		// the client layer needn't be concerned with them.
-		// No fields need to be set up by the client prior to calling mDNS_Init();
-		// all required data is passed as parameters to that function.
-
-		mDNS_PlatformSupport *p;			// Pointer to platform-specific data of indeterminite size
-		mDNSu32  KnownBugs;
-		mDNSBool AdvertiseLocalAddresses;
-		mStatus mDNSPlatformStatus;
-		mDNSCallback *MainCallback;
-		void         *MainContext;
-
-		// For debugging: To catch and report locking failures
-		mDNSu32 mDNS_busy;					// Incremented between mDNS_Lock/mDNS_Unlock section
-		mDNSu32 mDNS_reentrancy;			// Incremented when calling a client callback
-		mDNSu8  mDNS_shutdown;				// Set when we're shutting down, allows us to skip some unnecessary steps
-		mDNSu8  lock_rrcache;				// For debugging: Set at times when these lists may not be modified
-		mDNSu8  lock_Questions;
-		mDNSu8  lock_Records;
-		char MsgBuffer[80];					// Temp storage used while building error log messages
-
-		// Task Scheduling variables
-		mDNSs32  timenow;					// The time that this particular activation of the mDNS code started
-		mDNSs32  timenow_last;				// The time the last time we ran
-		mDNSs32  timenow_adjust;			// Correction applied if we ever discover time went backwards
-		mDNSs32  NextScheduledEvent;		// Derived from values below
-		mDNSs32  SuppressSending;			// Don't send *any* packets during this time
-		mDNSs32  NextCacheCheck;			// Next time to refresh cache record before it expires
-		mDNSs32  NextScheduledQuery;		// Next time to send query in its exponential backoff sequence
-		mDNSs32  NextScheduledProbe;		// Next time to probe for new authoritative record
-		mDNSs32  NextScheduledResponse;		// Next time to send authoritative record(s) in responses
-		mDNSs32  ExpectUnicastResponse;		// Set when we send a query with the kDNSQClass_UnicastResponse bit set
-		mDNSs32  RandomQueryDelay;			// For de-synchronization of query packets on the wire
-		mDNSBool SendDeregistrations;		// Set if we need to send deregistrations (immediately)
-		mDNSBool SendImmediateAnswers;		// Set if we need to send answers (immediately -- or as soon as SuppressSending clears)
-		mDNSBool SleepState;				// Set if we're sleeping (send no more packets)
-
-		// These fields only required for mDNS Searcher...
-		DNSQuestion *Questions;				// List of all registered questions, active and inactive
-		DNSQuestion *NewQuestions;			// Fresh questions not yet answered from cache
-		DNSQuestion *CurrentQuestion;		// Next question about to be examined in AnswerLocalQuestions()
-		DNSQuestion *LocalOnlyQuestions;	// Questions with InterfaceID set to ~0 ("local only")
-		DNSQuestion *NewLocalOnlyQuestions;	// Fresh local-only questions not yet answered
-		mDNSu32 rrcache_size;				// Total number of available cache entries
-		mDNSu32	rrcache_totalused;			// Number of cache entries currently occupied
-		mDNSu32 rrcache_active;				// Number of cache entries currently occupied by records that answer active questions
-		mDNSu32 rrcache_report;
-		CacheRecord *rrcache_free;
-		CacheRecord *rrcache_hash[CACHE_HASH_SLOTS];
-		CacheRecord **rrcache_tail[CACHE_HASH_SLOTS];
-		mDNSu32 rrcache_used[CACHE_HASH_SLOTS];
-
-		// Fields below only required for mDNS Responder...
-		domainlabel nicelabel;				// Rich text label encoded using canonically precomposed UTF-8
-		domainlabel hostlabel;				// Conforms to RFC 1034 "letter-digit-hyphen" ARPANET host name rules
-		domainname  hostname;				// Host Name, e.g. "Foo.local."
-		UTF8str255 HIHardware;
-		UTF8str255 HISoftware;
-		AuthRecord *ResourceRecords;
-		AuthRecord *DuplicateRecords;		// Records currently 'on hold' because they are duplicates of existing records
-		AuthRecord *LocalOnlyRecords;		// Local records registered with InterfaceID set to ~0 ("local only")
-		AuthRecord *NewLocalOnlyRecords;	// Fresh local-only records not yet delivered to local-only questions
-		mDNSBool    DiscardLocalOnlyRecords;// Set when we have "remove" events we need to deliver to local-only questions
-		AuthRecord *CurrentRecord;			// Next AuthRecord about to be examined
-		NetworkInterfaceInfo *HostInterfaces;
-		mDNSs32 ProbeFailTime;
-		mDNSs32 NumFailedProbes;
-		mDNSs32 SuppressProbes;
-	};
-
-// ***************************************************************************
-#if 0
-#pragma mark - Useful Static Constants
-#endif
-
-	extern const mDNSIPPort      zeroIPPort;
-	extern const mDNSv4Addr      zeroIPAddr;
-	extern const mDNSv6Addr      zerov6Addr;
-	extern const mDNSv4Addr      onesIPv4Addr;
-	extern const mDNSv6Addr      onesIPv6Addr;
-	extern const mDNSInterfaceID mDNSInterface_Any;
-
-	extern const mDNSIPPort      UnicastDNSPort;
-	extern const mDNSIPPort      MulticastDNSPort;
-	extern const mDNSv4Addr      AllDNSAdminGroup;
-	extern const mDNSv4Addr      AllDNSLinkGroup;
-	extern const mDNSv6Addr      AllDNSLinkGroupv6;
-	extern const mDNSAddr        AllDNSLinkGroup_v4;
-	extern const mDNSAddr        AllDNSLinkGroup_v6;
-
-// ***************************************************************************
-#if 0
-#pragma mark - Main Client Functions
-#endif
-
-// Every client should call mDNS_Init, passing in storage for the mDNS object, mDNS_PlatformSupport object, and rrcache.
-// The rrcachesize parameter is the size of (i.e. number of entries in) the rrcache array passed in.
-// Most clients use mDNS_Init_AdvertiseLocalAddresses. This causes mDNSCore to automatically
-// create the correct address records for all the hosts interfaces. If you plan to advertise
-// services being offered by the local machine, this is almost always what you want.
-// There are two cases where you might use mDNS_Init_DontAdvertiseLocalAddresses:
-// 1. A client-only device, that browses for services but doesn't advertise any of its own.
-// 2. A proxy-registration service, that advertises services being offered by other machines, and takes
-//    the appropriate steps to manually create the correct address records for those other machines.
-// In principle, a proxy-like registration service could manually create address records for its own machine too,
-// but this would be pointless extra effort when using mDNS_Init_AdvertiseLocalAddresses does that for you.
-//
-// When mDNS has finished setting up the client's callback is called
-// A client can also spin and poll the mDNSPlatformStatus field to see when it changes from mStatus_Waiting to mStatus_NoError
-//
-// Call mDNS_Close to tidy up before exiting
-//
-// Call mDNS_Register with a completed AuthRecord object to register a resource record
-// If the resource record type is kDNSRecordTypeUnique (or kDNSknownunique) then if a conflicting resource record is discovered,
-// the resource record's mDNSRecordCallback will be called with error code mStatus_NameConflict. The callback should deregister
-// the record, and may then try registering the record again after picking a new name (e.g. by automatically appending a number).
-//
-// Call mDNS_StartQuery to initiate a query. mDNS will proceed to issue Multicast DNS query packets, and any time a response
-// is received containing a record which matches the question, the DNSQuestion's mDNSAnswerCallback function will be called
-// Call mDNS_StopQuery when no more answers are required
-//
-// Care should be taken on multi-threaded or interrupt-driven environments.
-// The main mDNS routines call mDNSPlatformLock() on entry and mDNSPlatformUnlock() on exit;
-// each platform layer needs to implement these appropriately for its respective platform.
-// For example, if the support code on a particular platform implements timer callbacks at interrupt time, then
-// mDNSPlatformLock/Unlock need to disable interrupts or do similar concurrency control to ensure that the mDNS
-// code is not entered by an interrupt-time timer callback while in the middle of processing a client call.
-
-	extern mStatus mDNS_Init      (mDNS *const m, mDNS_PlatformSupport *const p,
-				       CacheRecord *rrcachestorage, mDNSu32 rrcachesize,
-				       mDNSBool AdvertiseLocalAddresses,
-				       mDNSCallback *Callback, void *Context);
-// See notes above on use of NoCache/ZeroCacheSize
-#define mDNS_Init_NoCache                     mDNSNULL
-#define mDNS_Init_ZeroCacheSize               0
-// See notes above on use of Advertise/DontAdvertiseLocalAddresses
-#define mDNS_Init_AdvertiseLocalAddresses     mDNStrue
-#define mDNS_Init_DontAdvertiseLocalAddresses mDNSfalse
-#define mDNS_Init_NoInitCallback              mDNSNULL
-#define mDNS_Init_NoInitCallbackContext       mDNSNULL
-
-	extern void    mDNS_GrowCache (mDNS *const m, CacheRecord *storage, mDNSu32 numrecords);
-	extern void    mDNS_Close     (mDNS *const m);
-	extern mDNSs32 mDNS_Execute   (mDNS *const m);
-
-	extern mStatus mDNS_Register  (mDNS *const m, AuthRecord *const rr);
-	extern mStatus mDNS_Update    (mDNS *const m, AuthRecord *const rr, mDNSu32 newttl,
-				       const mDNSu16 newrdlength, 
-				       RData *const newrdata, mDNSRecordUpdateCallback *Callback);
-	extern mStatus mDNS_Deregister(mDNS *const m, AuthRecord *const rr);
-
-	extern mStatus mDNS_StartQuery(mDNS *const m, DNSQuestion *const question);
-	extern mStatus mDNS_StopQuery (mDNS *const m, DNSQuestion *const question);
-	extern mStatus mDNS_Reconfirm (mDNS *const m, CacheRecord *const cacherr);
-	extern mStatus mDNS_ReconfirmByValue(mDNS *const m, ResourceRecord *const rr);
-
-// ***************************************************************************
-#if 0
-#pragma mark - Platform support functions that are accessible to the client layer too
-#endif
-
-	extern mDNSs32  mDNSPlatformOneSecond;
-	extern mDNSs32  mDNSPlatformTimeNow(void);
-
-// ***************************************************************************
-#if 0
-#pragma mark - General utility and helper functions
-#endif
-
-// mDNS_RegisterService is a single call to register the set of resource records associated with a given named service.
-//
-// mDNS_StartResolveService is single call which is equivalent to multiple calls to mDNS_StartQuery,
-// to find the IP address, port number, and demultiplexing information for a given named service.
-// As with mDNS_StartQuery, it executes asynchronously, and calls the ServiceInfoQueryCallback when the answer is
-// found. After the service is resolved, the client should call mDNS_StopResolveService to complete the transaction.
-// The client can also call mDNS_StopResolveService at any time to abort the transaction.
-//
-// mDNS_GetBrowseDomains is a special case of the mDNS_StartQuery call, where the resulting answers
-// are a list of PTR records indicating (in the rdata) domains that are recommended for browsing.
-// After getting the list of domains to browse, call mDNS_StopQuery to end the search.
-// mDNS_GetDefaultBrowseDomain returns the name of the domain that should be highlighted by default.
-//
-// mDNS_GetRegistrationDomains and mDNS_GetDefaultRegistrationDomain are the equivalent calls to get the list
-// of one or more domains that should be offered to the user as choices for where they may register their service,
-// and the default domain in which to register in the case where the user has made no selection.
-
-	extern void    mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mDNSInterfaceID InterfaceID,
-						mDNSu16 rrtype, mDNSu32 ttl, mDNSu8 RecordType, mDNSRecordCallback Callback, void *Context);
-
-	extern mStatus mDNS_RegisterService  (mDNS *const m, ServiceRecordSet *sr,
-					      const domainlabel *const name, const domainname *const type, const domainname *const domain,
-					      const domainname *const host, mDNSIPPort port, const mDNSu8 txtinfo[], mDNSu16 txtlen,
-					      AuthRecord *SubTypes, mDNSu32 NumSubTypes,
-					      const mDNSInterfaceID InterfaceID, mDNSServiceCallback Callback, void *Context);
-	extern mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra, RData *rdata, mDNSu32 ttl);
-	extern mStatus mDNS_RemoveRecordFromService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra);
-	extern mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordSet *const sr, const domainlabel *newname);
-	extern mStatus mDNS_DeregisterService(mDNS *const m, ServiceRecordSet *sr);
-
-	extern mStatus mDNS_RegisterNoSuchService(mDNS *const m, AuthRecord *const rr,
-						  const domainlabel *const name, const domainname *const type, const domainname *const domain,
-						  const domainname *const host,
-						  const mDNSInterfaceID InterfaceID, mDNSRecordCallback Callback, void *Context);
-#define        mDNS_DeregisterNoSuchService mDNS_Deregister
-
-	extern mStatus mDNS_StartBrowse(mDNS *const m, DNSQuestion *const question,
-					const domainname *const srv, const domainname *const domain,
-					const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *Callback, void *Context);
-#define        mDNS_StopBrowse mDNS_StopQuery
-
-	extern mStatus mDNS_StartResolveService(mDNS *const m, ServiceInfoQuery *query, ServiceInfo *info, mDNSServiceInfoQueryCallback *Callback, void *Context);
-	extern void    mDNS_StopResolveService (mDNS *const m, ServiceInfoQuery *query);
-
-	typedef enum
-	{
-		mDNS_DomainTypeBrowse              = 0,
-		mDNS_DomainTypeBrowseDefault       = 1,
-		mDNS_DomainTypeRegistration        = 2,
-		mDNS_DomainTypeRegistrationDefault = 3
-	} mDNS_DomainType;
-
-	extern mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, mDNS_DomainType DomainType, const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *Callback, void *Context);
-// In the Panther mDNSResponder we don't do unicast queries yet, so there's no point trying to do domain enumeration
-// mDNS_GetDomains() and mDNS_StopGetDomains() are set to be no-ops so that clients don't try to do browse/register operations that will fail
-//#define        mDNS_StopGetDomains mDNS_StopQuery
-#define        mDNS_StopGetDomains(m,q) ((void)(m),(void)(q))
-	extern mStatus mDNS_AdvertiseDomains(mDNS *const m, AuthRecord *rr, mDNS_DomainType DomainType, const mDNSInterfaceID InterfaceID, char *domname);
-#define        mDNS_StopAdvertiseDomains mDNS_Deregister
-
-// ***************************************************************************
-#if 0
-#pragma mark - DNS name utility functions
-#endif
-
-// In order to expose the full capabilities of the DNS protocol (which allows any arbitrary eight-bit values
-// in domain name labels, including unlikely characters like ascii nulls and even dots) all the mDNS APIs
-// work with DNS's native length-prefixed strings. For convenience in C, the following utility functions
-// are provided for converting between C's null-terminated strings and DNS's length-prefixed strings.
-
-// Assignment
-// A simple C structure assignment of a domainname can cause a protection fault by accessing unmapped memory,
-// because that object is defined to be 256 bytes long, but not all domainname objects are truly the full size.
-// This macro uses mDNSPlatformMemCopy() to make sure it only touches the actual bytes that are valid.
-#define AssignDomainName(DST, SRC) mDNSPlatformMemCopy((SRC).c, (DST).c, DomainNameLength(&(SRC)))
-
-// Comparison functions
-	extern mDNSBool SameDomainLabel(const mDNSu8 *a, const mDNSu8 *b);
-	extern mDNSBool SameDomainName(const domainname *const d1, const domainname *const d2);
-
-// Get total length of domain name, in native DNS format, including terminal root label
-//   (e.g. length of "com." is 5 (length byte, three data bytes, final zero)
-	extern mDNSu16  DomainNameLength(const domainname *const name);
-
-// Append functions to append one or more labels to an existing native format domain name:
-//   AppendLiteralLabelString adds a single label from a literal C string, with no escape character interpretation.
-//   AppendDNSNameString      adds zero or more labels from a C string using conventional DNS dots-and-escaping interpretation
-//   AppendDomainLabel        adds a single label from a native format domainlabel
-//   AppendDomainName         adds zero or more labels from a native format domainname
-	extern mDNSu8  *AppendLiteralLabelString(domainname *const name, const char *cstr);
-	extern mDNSu8  *AppendDNSNameString     (domainname *const name, const char *cstr);
-	extern mDNSu8  *AppendDomainLabel       (domainname *const name, const domainlabel *const label);
-	extern mDNSu8  *AppendDomainName        (domainname *const name, const domainname *const append);
-
-// Convert from null-terminated string to native DNS format:
-//   The DomainLabel form makes a single label from a literal C string, with no escape character interpretation.
-//   The DomainName form makes native format domain name from a C string using conventional DNS interpretation:
-//     dots separate labels, and within each label, '\.' represents a literal dot, '\\' represents a literal
-//     backslash and backslash with three decimal digits (e.g. \000) represents an arbitrary byte value.
-	extern mDNSBool MakeDomainLabelFromLiteralString(domainlabel *const label, const char *cstr);
-	extern mDNSu8  *MakeDomainNameFromDNSNameString (domainname  *const name,  const char *cstr);
-
-// Convert native format domainlabel or domainname back to C string format
-// IMPORTANT:
-// When using ConvertDomainLabelToCString, the target buffer must be MAX_ESCAPED_DOMAIN_LABEL (254) bytes long
-// to guarantee there will be no buffer overrun. It is only safe to use a buffer shorter than this in rare cases
-// where the label is known to be constrained somehow (for example, if the label is known to be either "_tcp" or "_udp").
-// Similarly, when using ConvertDomainNameToCString, the target buffer must be MAX_ESCAPED_DOMAIN_NAME (1005) bytes long.
-// See definitions of MAX_ESCAPED_DOMAIN_LABEL and MAX_ESCAPED_DOMAIN_NAME for more detailed explanation.
-	extern char    *ConvertDomainLabelToCString_withescape(const domainlabel *const name, char *cstr, char esc);
-#define         ConvertDomainLabelToCString_unescaped(D,C) ConvertDomainLabelToCString_withescape((D), (C), 0)
-#define         ConvertDomainLabelToCString(D,C)           ConvertDomainLabelToCString_withescape((D), (C), '\\')
-	extern char    *ConvertDomainNameToCString_withescape(const domainname *const name, char *cstr, char esc);
-#define         ConvertDomainNameToCString_unescaped(D,C) ConvertDomainNameToCString_withescape((D), (C), 0)
-#define         ConvertDomainNameToCString(D,C)           ConvertDomainNameToCString_withescape((D), (C), '\\')
-
-	extern void     ConvertUTF8PstringToRFC1034HostLabel(const mDNSu8 UTF8Name[], domainlabel *const hostlabel);
-
-	extern mDNSu8  *ConstructServiceName(domainname *const fqdn, const domainlabel *name, const domainname *type, const domainname *const domain);
-	extern mDNSBool DeconstructServiceName(const domainname *const fqdn, domainlabel *const name, domainname *const type, domainname *const domain);
-
-// Note: Some old functions have been replaced by more sensibly-named versions.
-// You can uncomment the hash-defines below if you don't want to have to change your source code right away.
-// When updating your code, note that (unlike the old versions) *all* the new routines take the target object
-// as their first parameter.
-//#define ConvertCStringToDomainName(SRC,DST)  MakeDomainNameFromDNSNameString((DST),(SRC))
-//#define ConvertCStringToDomainLabel(SRC,DST) MakeDomainLabelFromLiteralString((DST),(SRC))
-//#define AppendStringLabelToName(DST,SRC)     AppendLiteralLabelString((DST),(SRC))
-//#define AppendStringNameToName(DST,SRC)      AppendDNSNameString((DST),(SRC))
-//#define AppendDomainLabelToName(DST,SRC)     AppendDomainLabel((DST),(SRC))
-//#define AppendDomainNameToName(DST,SRC)      AppendDomainName((DST),(SRC))
-
-// ***************************************************************************
-#if 0
-#pragma mark - Other utility functions
-#endif
-
-	extern mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, va_list arg);
-	extern mDNSu32 mDNS_snprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, ...) IS_A_PRINTF_STYLE_FUNCTION(3,4);
-	extern char *DNSTypeName(mDNSu16 rrtype);
-	extern char *GetRRDisplayString_rdb(mDNS *const m, const ResourceRecord *rr, RDataBody *rd);
-#define GetRRDisplayString(m, rr) GetRRDisplayString_rdb((m), &(rr)->resrec, &(rr)->resrec.rdata->u)
-	extern mDNSBool mDNSSameAddress(const mDNSAddr *ip1, const mDNSAddr *ip2);
-	extern void IncrementLabelSuffix(domainlabel *name, mDNSBool RichText);
-
-// ***************************************************************************
-#if 0
-#pragma mark - PlatformSupport interface
-#endif
-
-// This section defines the interface to the Platform Support layer.
-// Normal client code should not use any of types defined here, or directly call any of the functions defined here.
-// The definitions are placed here because sometimes clients do use these calls indirectly, via other supported client operations.
-// For example, AssignDomainName is a macro defined using mDNSPlatformMemCopy()
-
-	typedef packedstruct
-	{
-		mDNSOpaque16 id;
-		mDNSOpaque16 flags;
-		mDNSu16 numQuestions;
-		mDNSu16 numAnswers;
-		mDNSu16 numAuthorities;
-		mDNSu16 numAdditionals;
-	} DNSMessageHeader;
-
-// We can send and receive packets up to 9000 bytes (Ethernet Jumbo Frame size, if that ever becomes widely used)
-// However, in the normal case we try to limit packets to 1500 bytes so that we don't get IP fragmentation on standard Ethernet
-// 40 (IPv6 header) + 8 (UDP header) + 12 (DNS message header) + 1440 (DNS message body) = 1500 total
-#define AbsoluteMaxDNSMessageData 1500//8940
-#define NormalMaxDNSMessageData 1440
-	typedef packedstruct
-	{
-		DNSMessageHeader h;						// Note: Size 12 bytes
-		mDNSu8 data[AbsoluteMaxDNSMessageData];	// 40 (IPv6) + 8 (UDP) + 12 (DNS header) + 8940 (data) = 9000
-	} DNSMessage;
-
-// Every platform support module must provide the following functions.
-// mDNSPlatformInit() typically opens a communication endpoint, and starts listening for mDNS packets.
-// When Setup is complete, the platform support layer calls mDNSCoreInitComplete().
-// mDNSPlatformSendUDP() sends one UDP packet
-// When a packet is received, the PlatformSupport code calls mDNSCoreReceive()
-// mDNSPlatformClose() tidies up on exit
-// Note: mDNSPlatformMemAllocate/mDNSPlatformMemFree are only required for handling oversized resource records.
-// If your target platform has a well-defined specialized application, and you know that all the records it uses
-// are InlineCacheRDSize or less, then you can just make a simple mDNSPlatformMemAllocate() stub that always returns
-// NULL. InlineCacheRDSize is a compile-time constant, which is set by default to 64. If you need to handle records
-// a little larger than this and you don't want to have to implement run-time allocation and freeing, then you
-// can raise the value of this constant to a suitable value (at the expense of increased memory usage).
-	extern mStatus  mDNSPlatformInit        (mDNS *const m);
-	extern void     mDNSPlatformClose       (mDNS *const m);
-	extern mStatus  mDNSPlatformSendUDP(const mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end,
-					    mDNSInterfaceID InterfaceID, mDNSIPPort srcport, const mDNSAddr *dst, mDNSIPPort dstport);
-
-	extern void     mDNSPlatformLock        (const mDNS *const m);
-	extern void     mDNSPlatformUnlock      (const mDNS *const m);
-
-	extern void     mDNSPlatformStrCopy     (const void *src,       void *dst);
-	extern mDNSu32  mDNSPlatformStrLen      (const void *src);
-	extern void     mDNSPlatformMemCopy     (const void *src,       void *dst, mDNSu32 len);
-	extern mDNSBool mDNSPlatformMemSame     (const void *src, const void *dst, mDNSu32 len);
-	extern void     mDNSPlatformMemZero     (                       void *dst, mDNSu32 len);
-	extern void *   mDNSPlatformMemAllocate (mDNSu32 len);
-	extern void     mDNSPlatformMemFree     (void *mem);
-	extern mStatus  mDNSPlatformTimeInit    (mDNSs32 *timenow);
-
-// The core mDNS code provides these functions, for the platform support code to call at appropriate times
-//
-// mDNS_GenerateFQDN() is called once on startup (typically from mDNSPlatformInit())
-// and then again on each subsequent change of the dot-local host name.
-//
-// mDNS_RegisterInterface() is used by the platform support layer to inform mDNSCore of what
-// physical and/or logical interfaces are available for sending and receiving packets.
-// Typically it is called on startup for each available interface, but register/deregister may be
-// called again later, on multiple occasions, to inform the core of interface configuration changes.
-// If set->Advertise is set non-zero, then mDNS_RegisterInterface() also registers the standard
-// resource records that should be associated with every publicised IP address/interface:
-// -- Name-to-address records (A/AAAA)
-// -- Address-to-name records (PTR)
-// -- Host information (HINFO)
-//
-// mDNSCoreInitComplete() is called when the platform support layer is finished.
-// Typically this is at the end of mDNSPlatformInit(), but may be later
-// (on platforms like OT that allow asynchronous initialization of the networking stack).
-//
-// mDNSCoreReceive() is called when a UDP packet is received
-//
-// mDNSCoreMachineSleep() is called when the machine sleeps or wakes
-// (This refers to heavyweight laptop-style sleep/wake that disables network access,
-// not lightweight second-by-second CPU power management modes.)
-
-	extern void     mDNS_GenerateFQDN(mDNS *const m);
-	extern mStatus  mDNS_RegisterInterface  (mDNS *const m, NetworkInterfaceInfo *set);
-	extern void     mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set);
-	extern void     mDNSCoreInitComplete(mDNS *const m, mStatus result);
-	extern void     mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end,
-					const mDNSAddr *const srcaddr, const mDNSIPPort srcport,
-					const mDNSAddr *const dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, mDNSu8 ttl);
-	extern void     mDNSCoreMachineSleep(mDNS *const m, mDNSBool wake);
-#define mDNSinline static inline
-mDNSinline mDNSOpaque16 mDNSOpaque16fromIntVal(mDNSu16 v)
-	{
-	mDNSOpaque16 x;
-	x.b[0] = (mDNSu8)(v >> 8);
-	x.b[1] = (mDNSu8)(v & 0xFF);
-	return(x);
-	}
-
-// ***************************************************************************
-#if 0
-#pragma mark - Compile-Time assertion checks
-#endif
-
-// Some C compiler cleverness. We can make the compiler check certain things for
-// us, and report compile-time errors if anything is wrong. The usual way to do
-// this would be to use a run-time "if" statement, but then you don't find out
-// what's wrong until you run the software. This way, if the assertion condition
-// is false, the array size is negative, and the complier complains immediately.
-
-	struct mDNS_CompileTimeAssertionChecks
-	{
-		// Check that the compiler generated our on-the-wire packet format structure definitions
-		// properly packed, without adding padding bytes to align fields on 32-bit or 64-bit boundaries.
-		char assert0[(sizeof(rdataSRV)         == 262                          ) ? 1 : -1];
-		char assert1[(sizeof(DNSMessageHeader) ==  12                          ) ? 1 : -1];
-		char assert2[(sizeof(DNSMessage)       ==  12+AbsoluteMaxDNSMessageData) ? 1 : -1];
-		char assert3[(sizeof(mDNSs8)           ==   1                          ) ? 1 : -1];
-		char assert4[(sizeof(mDNSu8)           ==   1                          ) ? 1 : -1];
-		char assert5[(sizeof(mDNSs16)          ==   2                          ) ? 1 : -1];
-		char assert6[(sizeof(mDNSu16)          ==   2                          ) ? 1 : -1];
-		char assert7[(sizeof(mDNSs32)          ==   4                          ) ? 1 : -1];
-		char assert8[(sizeof(mDNSu32)          ==   4                          ) ? 1 : -1];
-		char assert9[(sizeof(mDNSOpaque16)     ==   2                          ) ? 1 : -1];
-		char assertA[(sizeof(mDNSOpaque32)     ==   4                          ) ? 1 : -1];
-		char assertB[(sizeof(mDNSOpaque128)    ==  16                          ) ? 1 : -1];
-	};
-
-// ***************************************************************************
-
-#ifdef	__cplusplus
-}
-#endif
-
-#endif

+ 0 - 128
src/app/mDNS/mDNSCore/mDNSDebug.h

@@ -1,128 +0,0 @@
-/*
- * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
-
-    Change History (most recent first):
-
-$Log: mDNSDebug.h,v $
-Revision 1.1.1.1  2005/07/23 13:57:05  shiro
-raop_play project
-
-Revision 1.1.2.1  2004/09/18 03:29:20  shiro
-*** empty log message ***
-
-Revision 1.14  2003/08/12 19:56:24  cheshire
-Update to APSL 2.0
-
-Revision 1.13  2003/07/02 21:19:46  cheshire
-<rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
-Revision 1.12  2003/05/26 03:01:27  cheshire
-<rdar://problem/3268904> sprintf/vsprintf-style functions are unsafe; use snprintf/vsnprintf instead
-
-Revision 1.11  2003/05/21 17:48:10  cheshire
-Add macro to enable GCC's printf format string checking
-
-Revision 1.10  2003/04/26 02:32:57  cheshire
-Add extern void LogMsg(const char *format, ...);
-
-Revision 1.9  2002/09/21 20:44:49  zarzycki
-Added APSL info
-
-Revision 1.8  2002/09/19 04:20:43  cheshire
-Remove high-ascii characters that confuse some systems
-
-Revision 1.7  2002/09/16 18:41:42  cheshire
-Merge in license terms from Quinn's copy, in preparation for Darwin release
-
-*/
-
-#ifndef __mDNSDebug_h
-#define __mDNSDebug_h
-
-// Set MDNS_DEBUGMSGS to 0 to optimize debugf() calls out of the compiled code
-// Set MDNS_DEBUGMSGS to 1 to generate normal debugging messages
-// Set MDNS_DEBUGMSGS to 2 to generate verbose debugging messages
-// MDNS_DEBUGMSGS is normally set in the project options (or makefile) but can also be set here if desired
-
-#define MDNS_DEBUGMSGS 0
-
-// Set MDNS_CHECK_PRINTF_STYLE_FUNCTIONS to 1 to enable extra GCC compiler warnings
-// Note: You don't normally want to do this, because it generates a bunch of
-// spurious warnings for the following custom extensions implemented by mDNS_vsnprintf:
-//    warning: `#' flag used with `%s' printf format    (for %#s              -- pascal string format)
-//    warning: repeated `#' flag in format              (for %##s             -- DNS name string format)
-//    warning: double format, pointer arg (arg 2)       (for %.4a, %.16a, %#a -- IP address formats)
-#define MDNS_CHECK_PRINTF_STYLE_FUNCTIONS 0
-#if MDNS_CHECK_PRINTF_STYLE_FUNCTIONS
-#define IS_A_PRINTF_STYLE_FUNCTION(F,A) __attribute__ ((format(printf,F,A)))
-#else
-#define IS_A_PRINTF_STYLE_FUNCTION(F,A)
-#endif
-
-#ifdef	__cplusplus
-	extern "C" {
-#endif
-
-#if MDNS_DEBUGMSGS
-#define debugf debugf_
-extern void debugf_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
-#else // If debug breaks are off, use a preprocessor trick to optimize those calls out of the code
-	#if( defined( __GNUC__ ) )
-		#define	debugf( ARGS... ) ((void)0)
-	#elif( defined( __MWERKS__ ) )
-		#define	debugf( ... )
-	#else
-		#define debugf 1 ? ((void)0) : (void)
-	#endif
-#endif
-
-#if MDNS_DEBUGMSGS > 1
-#define verbosedebugf verbosedebugf_
-extern void verbosedebugf_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
-#else
-	#if( defined( __GNUC__ ) )
-		#define	verbosedebugf( ARGS... ) ((void)0)
-	#elif( defined( __MWERKS__ ) )
-		#define	verbosedebugf( ... )
-	#else
-		#define verbosedebugf 1 ? ((void)0) : (void)
-	#endif
-#endif
-
-#if MDNS_DEBUGMSGS > 2
-// LogMsg is used even in shipping code, to write truly serious error messages to syslog (or equivalent)
-#define LogMsg LogMsg_
-extern void LogMsg_(const char *format, ...) IS_A_PRINTF_STYLE_FUNCTION(1,2);
-#else
-	#if( defined( __GNUC__ ) )
-		#define	LogMsg( ARGS... ) ((void)0)
-	#elif( defined( __MWERKS__ ) )
-		#define	LogMsg( ... )
-	#else
-		#define LogMsg 1 ? ((void)0) : (void)
-	#endif
-#endif
-#ifdef	__cplusplus
-	}
-#endif
-
-#endif

+ 0 - 2966
src/app/mDNS/mDNSCore/mDNSEmbeddedAPI.h

@@ -1,2966 +0,0 @@
-/* -*- Mode: C; tab-width: 4 -*-
- *
- * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
-
-   NOTE:
-   If you're building an application that uses DNS Service Discovery
-   this is probably NOT the header file you're looking for.
-   In most cases you will want to use /usr/include/dns_sd.h instead.
-
-   This header file defines the lowest level raw interface to mDNSCore,
-   which is appropriate *only* on tiny embedded systems where everything
-   runs in a single address space and memory is extremely constrained.
-   All the APIs here are malloc-free, which means that the caller is
-   responsible for passing in a pointer to the relevant storage that
-   will be used in the execution of that call, and (when called with
-   correct parameters) all the calls are guaranteed to succeed. There
-   is never a case where a call can suffer intermittent failures because
-   the implementation calls malloc() and sometimes malloc() returns NULL
-   because memory is so limited that no more is available.
-   This is primarily for devices that need to have precisely known fixed
-   memory requirements, with absolutely no uncertainty or run-time variation,
-   but that certainty comes at a cost of more difficult programming.
-   
-   For applications running on general-purpose desktop operating systems
-   (Mac OS, Linux, Solaris, Windows, etc.) the API you should use is
-   /usr/include/dns_sd.h, which defines the API by which multiple
-   independent client processes communicate their DNS Service Discovery
-   requests to a single "mdnsd" daemon running in the background.
-   
-   Even on platforms that don't run multiple independent processes in
-   multiple independent address spaces, you can still use the preferred
-   dns_sd.h APIs by linking in "dnssd_clientshim.c", which implements
-   the standard "dns_sd.h" API calls, allocates any required storage
-   using malloc(), and then calls through to the low-level malloc-free
-   mDNSCore routines defined here. This has the benefit that even though
-   you're running on a small embedded system with a single address space,
-   you can still use the exact same client C code as you'd use on a
-   general-purpose desktop system.
-
- */
-
-#ifndef __mDNSClientAPI_h
-#define __mDNSClientAPI_h
-
-#if defined(EFI32) || defined(EFI64) || defined(EFIX64)
-// EFI doesn't have stdarg.h unless it's building with GCC.
-#include "Tiano.h"
-#if !defined(__GNUC__)
-#define va_list         VA_LIST
-#define va_start(a, b)  VA_START(a, b)
-#define va_end(a)       VA_END(a)
-#define va_arg(a, b)    VA_ARG(a, b)
-#endif
-#else
-#include <stdarg.h>		// stdarg.h is required for for va_list support for the mDNS_vsnprintf declaration
-#endif
-
-#include "mDNSDebug.h"
-#if APPLE_OSX_mDNSResponder
-#include <uuid/uuid.h>
-#endif
-
-#ifdef __cplusplus
-	extern "C" {
-#endif
-
-// ***************************************************************************
-// Function scope indicators
-
-// If you see "mDNSlocal" before a function name in a C file, it means the function is not callable outside this file
-#ifndef mDNSlocal
-#define mDNSlocal static
-#endif
-// If you see "mDNSexport" before a symbol in a C file, it means the symbol is exported for use by clients
-// For every "mDNSexport" in a C file, there needs to be a corresponding "extern" declaration in some header file
-// (When a C file #includes a header file, the "extern" declarations tell the compiler:
-// "This symbol exists -- but not necessarily in this C file.")
-#ifndef mDNSexport
-#define mDNSexport
-#endif
-
-// Explanation: These local/export markers are a little habit of mine for signaling the programmers' intentions.
-// When "mDNSlocal" is just a synonym for "static", and "mDNSexport" is a complete no-op, you could be
-// forgiven for asking what purpose they serve. The idea is that if you see "mDNSexport" in front of a
-// function definition it means the programmer intended it to be exported and callable from other files
-// in the project. If you see "mDNSlocal" in front of a function definition it means the programmer
-// intended it to be private to that file. If you see neither in front of a function definition it
-// means the programmer forgot (so you should work out which it is supposed to be, and fix it).
-// Using "mDNSlocal" instead of "static" makes it easier to do a textual searches for one or the other.
-// For example you can do a search for "static" to find if any functions declare any local variables as "static"
-// (generally a bad idea unless it's also "const", because static storage usually risks being non-thread-safe)
-// without the results being cluttered with hundreds of matches for functions declared static.
-// - Stuart Cheshire
-
-// ***************************************************************************
-// Structure packing macro
-
-// If we're not using GNUC, it's not fatal.
-// Most compilers naturally pack the on-the-wire structures correctly anyway, so a plain "struct" is usually fine.
-// In the event that structures are not packed correctly, mDNS_Init() will detect this and report an error, so the
-// developer will know what's wrong, and can investigate what needs to be done on that compiler to provide proper packing.
-#ifndef packedstruct
- #if ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9)))
-  #define packedstruct struct __attribute__((__packed__))
-  #define packedunion  union  __attribute__((__packed__))
- #else
-  #define packedstruct struct
-  #define packedunion  union
- #endif
-#endif
-
-// ***************************************************************************
-#if 0
-#pragma mark - DNS Resource Record class and type constants
-#endif
-
-typedef enum							// From RFC 1035
-	{
-	kDNSClass_IN               = 1,		// Internet
-	kDNSClass_CS               = 2,		// CSNET
-	kDNSClass_CH               = 3,		// CHAOS
-	kDNSClass_HS               = 4,		// Hesiod
-	kDNSClass_NONE             = 254,	// Used in DNS UPDATE [RFC 2136]
-
-	kDNSClass_Mask             = 0x7FFF,// Multicast DNS uses the bottom 15 bits to identify the record class...
-	kDNSClass_UniqueRRSet      = 0x8000,// ... and the top bit indicates that all other cached records are now invalid
-
-	kDNSQClass_ANY             = 255,	// Not a DNS class, but a DNS query class, meaning "all classes"
-	kDNSQClass_UnicastResponse = 0x8000	// Top bit set in a question means "unicast response acceptable"
-	} DNS_ClassValues;
-
-typedef enum				// From RFC 1035
-	{
-	kDNSType_A = 1,			//  1 Address
-	kDNSType_NS,			//  2 Name Server
-	kDNSType_MD,			//  3 Mail Destination
-	kDNSType_MF,			//  4 Mail Forwarder
-	kDNSType_CNAME,			//  5 Canonical Name
-	kDNSType_SOA,			//  6 Start of Authority
-	kDNSType_MB,			//  7 Mailbox
-	kDNSType_MG,			//  8 Mail Group
-	kDNSType_MR,			//  9 Mail Rename
-	kDNSType_NULL,			// 10 NULL RR
-	kDNSType_WKS,			// 11 Well-known-service
-	kDNSType_PTR,			// 12 Domain name pointer
-	kDNSType_HINFO,			// 13 Host information
-	kDNSType_MINFO,			// 14 Mailbox information
-	kDNSType_MX,			// 15 Mail Exchanger
-	kDNSType_TXT,			// 16 Arbitrary text string
-	kDNSType_RP,			// 17 Responsible person
-	kDNSType_AFSDB,			// 18 AFS cell database
-	kDNSType_X25,			// 19 X_25 calling address
-	kDNSType_ISDN,			// 20 ISDN calling address
-	kDNSType_RT,			// 21 Router
-	kDNSType_NSAP,			// 22 NSAP address
-	kDNSType_NSAP_PTR,		// 23 Reverse NSAP lookup (deprecated)
-	kDNSType_SIG,			// 24 Security signature
-	kDNSType_KEY,			// 25 Security key
-	kDNSType_PX,			// 26 X.400 mail mapping
-	kDNSType_GPOS,			// 27 Geographical position (withdrawn)
-	kDNSType_AAAA,			// 28 IPv6 Address
-	kDNSType_LOC,			// 29 Location Information
-	kDNSType_NXT,			// 30 Next domain (security)
-	kDNSType_EID,			// 31 Endpoint identifier
-	kDNSType_NIMLOC,		// 32 Nimrod Locator
-	kDNSType_SRV,			// 33 Service record
-	kDNSType_ATMA,			// 34 ATM Address
-	kDNSType_NAPTR,			// 35 Naming Authority PoinTeR
-	kDNSType_KX,			// 36 Key Exchange
-	kDNSType_CERT,			// 37 Certification record
-	kDNSType_A6,			// 38 IPv6 Address (deprecated)
-	kDNSType_DNAME,			// 39 Non-terminal DNAME (for IPv6)
-	kDNSType_SINK,			// 40 Kitchen sink (experimental)
-	kDNSType_OPT,			// 41 EDNS0 option (meta-RR)
-	kDNSType_APL,			// 42 Address Prefix List
-	kDNSType_DS,			// 43 Delegation Signer
-	kDNSType_SSHFP,			// 44 SSH Key Fingerprint
-	kDNSType_IPSECKEY,		// 45 IPSECKEY
-	kDNSType_RRSIG,			// 46 RRSIG
-	kDNSType_NSEC,			// 47 Denial of Existence
-	kDNSType_DNSKEY,		// 48 DNSKEY
-	kDNSType_DHCID,			// 49 DHCP Client Identifier
-	kDNSType_NSEC3,			// 50 Hashed Authenticated Denial of Existence
-	kDNSType_NSEC3PARAM,	// 51 Hashed Authenticated Denial of Existence
-
-	kDNSType_HIP = 55,		// 55 Host Identity Protocol
-
-	kDNSType_SPF = 99,		// 99 Sender Policy Framework for E-Mail
-	kDNSType_UINFO,			// 100 IANA-Reserved
-	kDNSType_UID,			// 101 IANA-Reserved
-	kDNSType_GID,			// 102 IANA-Reserved
-	kDNSType_UNSPEC,		// 103 IANA-Reserved
-
-	kDNSType_TKEY = 249,	// 249 Transaction key
-	kDNSType_TSIG,			// 250 Transaction signature
-	kDNSType_IXFR,			// 251 Incremental zone transfer
-	kDNSType_AXFR,			// 252 Transfer zone of authority
-	kDNSType_MAILB,			// 253 Transfer mailbox records
-	kDNSType_MAILA,			// 254 Transfer mail agent records
-	kDNSQType_ANY			// Not a DNS type, but a DNS query type, meaning "all types"
-	} DNS_TypeValues;
-
-// ***************************************************************************
-#if 0
-#pragma mark -
-#pragma mark - Simple types
-#endif
-
-// mDNS defines its own names for these common types to simplify portability across
-// multiple platforms that may each have their own (different) names for these types.
-typedef          int   mDNSBool;
-typedef   signed char  mDNSs8;
-typedef unsigned char  mDNSu8;
-typedef   signed short mDNSs16;
-typedef unsigned short mDNSu16;
-
-// <http://gcc.gnu.org/onlinedocs/gcc-3.3.3/cpp/Common-Predefined-Macros.html> says
-//   __LP64__ _LP64
-//   These macros are defined, with value 1, if (and only if) the compilation is
-//   for a target where long int and pointer both use 64-bits and int uses 32-bit.
-// <http://www.intel.com/software/products/compilers/clin/docs/ug/lin1077.htm> says
-//   Macro Name __LP64__ Value 1
-// A quick Google search for "defined(__LP64__)" OR "#ifdef __LP64__" gives 2590 hits and
-// a search for "#if __LP64__" gives only 12, so I think we'll go with the majority and use defined()
-#if defined(_ILP64) || defined(__ILP64__)
-typedef   signed int32 mDNSs32;
-typedef unsigned int32 mDNSu32;
-#elif defined(_LP64) || defined(__LP64__)
-typedef   signed int   mDNSs32;
-typedef unsigned int   mDNSu32;
-#else
-typedef   signed long  mDNSs32;
-typedef unsigned long  mDNSu32;
-//typedef   signed int mDNSs32;
-//typedef unsigned int mDNSu32;
-#endif
-
-// To enforce useful type checking, we make mDNSInterfaceID be a pointer to a dummy struct
-// This way, mDNSInterfaceIDs can be assigned, and compared with each other, but not with other types
-// Declaring the type to be the typical generic "void *" would lack this type checking
-typedef struct mDNSInterfaceID_dummystruct { void *dummy; } *mDNSInterfaceID;
-
-// These types are for opaque two- and four-byte identifiers.
-// The "NotAnInteger" fields of the unions allow the value to be conveniently passed around in a
-// register for the sake of efficiency, and compared for equality or inequality, but don't forget --
-// just because it is in a register doesn't mean it is an integer. Operations like greater than,
-// less than, add, multiply, increment, decrement, etc., are undefined for opaque identifiers,
-// and if you make the mistake of trying to do those using the NotAnInteger field, then you'll
-// find you get code that doesn't work consistently on big-endian and little-endian machines.
-#if defined(_WIN32)
- #pragma pack(push,2)
-#endif
-typedef       union { mDNSu8 b[ 2]; mDNSu16 NotAnInteger; } mDNSOpaque16;
-typedef       union { mDNSu8 b[ 4]; mDNSu32 NotAnInteger; } mDNSOpaque32;
-typedef packedunion { mDNSu8 b[ 6]; mDNSu16 w[3]; mDNSu32 l[1]; } mDNSOpaque48;
-typedef       union { mDNSu8 b[ 8]; mDNSu16 w[4]; mDNSu32 l[2]; } mDNSOpaque64;
-typedef       union { mDNSu8 b[16]; mDNSu16 w[8]; mDNSu32 l[4]; } mDNSOpaque128;
-#if defined(_WIN32)
- #pragma pack(pop)
-#endif
-
-typedef mDNSOpaque16  mDNSIPPort;		// An IP port is a two-byte opaque identifier (not an integer)
-typedef mDNSOpaque32  mDNSv4Addr;		// An IP address is a four-byte opaque identifier (not an integer)
-typedef mDNSOpaque128 mDNSv6Addr;		// An IPv6 address is a 16-byte opaque identifier (not an integer)
-typedef mDNSOpaque48  mDNSEthAddr;		// An Ethernet address is a six-byte opaque identifier (not an integer)
-
-// Bit operations for opaque 64 bit quantity. Uses the 32 bit quantity(l[2]) to set and clear bits
-#define mDNSNBBY 8
-#define bit_set_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] |= (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
-#define bit_clr_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] &= ~(1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
-#define bit_get_opaque64(op64, index) (op64.l[((index))/(sizeof(mDNSu32) * mDNSNBBY)] & (1 << ((index) % (sizeof(mDNSu32) * mDNSNBBY))))
-
-enum
-	{
-	mDNSAddrType_None    = 0,
-	mDNSAddrType_IPv4    = 4,
-	mDNSAddrType_IPv6    = 6,
-	mDNSAddrType_Unknown = ~0	// Special marker value used in known answer list recording
-	};
-
-enum
-	{
-	mDNSTransport_None = 0,
-	mDNSTransport_UDP  = 1,
-	mDNSTransport_TCP  = 2
-	};
-
-typedef struct
-	{
-	mDNSs32 type;
-	union { mDNSv6Addr v6; mDNSv4Addr v4; } ip;
-	} mDNSAddr;
-
-enum { mDNSfalse = 0, mDNStrue = 1 };
-
-#define mDNSNULL 0L
-
-enum
-	{
-	mStatus_Waiting           = 1,
-	mStatus_NoError           = 0,
-
-	// mDNS return values are in the range FFFE FF00 (-65792) to FFFE FFFF (-65537)
-	// The top end of the range (FFFE FFFF) is used for error codes;
-	// the bottom end of the range (FFFE FF00) is used for non-error values;
-
-	// Error codes:
-	mStatus_UnknownErr                = -65537,		// First value: 0xFFFE FFFF
-	mStatus_NoSuchNameErr             = -65538,
-	mStatus_NoMemoryErr               = -65539,
-	mStatus_BadParamErr               = -65540,
-	mStatus_BadReferenceErr           = -65541,
-	mStatus_BadStateErr               = -65542,
-	mStatus_BadFlagsErr               = -65543,
-	mStatus_UnsupportedErr            = -65544,
-	mStatus_NotInitializedErr         = -65545,
-	mStatus_NoCache                   = -65546,
-	mStatus_AlreadyRegistered         = -65547,
-	mStatus_NameConflict              = -65548,
-	mStatus_Invalid                   = -65549,
-	mStatus_Firewall                  = -65550,
-	mStatus_Incompatible              = -65551,
-	mStatus_BadInterfaceErr           = -65552,
-	mStatus_Refused                   = -65553,
-	mStatus_NoSuchRecord              = -65554,
-	mStatus_NoAuth                    = -65555,
-	mStatus_NoSuchKey                 = -65556,
-	mStatus_NATTraversal              = -65557,
-	mStatus_DoubleNAT                 = -65558,
-	mStatus_BadTime                   = -65559,
-	mStatus_BadSig                    = -65560,     // while we define this per RFC 2845, BIND 9 returns Refused for bad/missing signatures
-	mStatus_BadKey                    = -65561,
-	mStatus_TransientErr              = -65562,     // transient failures, e.g. sending packets shortly after a network transition or wake from sleep
-	mStatus_ServiceNotRunning         = -65563,     // Background daemon not running
-	mStatus_NATPortMappingUnsupported = -65564,     // NAT doesn't support NAT-PMP or UPnP
-	mStatus_NATPortMappingDisabled    = -65565,     // NAT supports NAT-PMP or UPnP but it's disabled by the administrator
-	mStatus_NoRouter                  = -65566,
-	mStatus_PollingMode               = -65567,
-	mStatus_Timeout                   = -65568,
-	// -65568 to -65786 currently unused; available for allocation
-
-	// tcp connection status
-	mStatus_ConnPending       = -65787,
-	mStatus_ConnFailed        = -65788,
-	mStatus_ConnEstablished   = -65789,
-
-	// Non-error values:
-	mStatus_GrowCache         = -65790,
-	mStatus_ConfigChanged     = -65791,
-	mStatus_MemFree           = -65792		// Last value: 0xFFFE FF00
-	// mStatus_MemFree is the last legal mDNS error code, at the end of the range allocated for mDNS
-	};
-
-typedef mDNSs32 mStatus;
-
-// RFC 1034/1035 specify that a domain label consists of a length byte plus up to 63 characters
-#define MAX_DOMAIN_LABEL 63
-typedef struct { mDNSu8 c[ 64]; } domainlabel;		// One label: length byte and up to 63 characters
-
-// RFC 1034/1035/2181 specify that a domain name (length bytes and data bytes) may be up to 255 bytes long,
-// plus the terminating zero at the end makes 256 bytes total in the on-the-wire format.
-#define MAX_DOMAIN_NAME 256
-typedef struct { mDNSu8 c[256]; } domainname;		// Up to 256 bytes of length-prefixed domainlabels
-
-typedef struct { mDNSu8 c[256]; } UTF8str255;		// Null-terminated C string
-
-// The longest legal textual form of a DNS name is 1009 bytes, including the C-string terminating NULL at the end.
-// Explanation:
-// When a native domainname object is converted to printable textual form using ConvertDomainNameToCString(),
-// non-printing characters are represented in the conventional DNS way, as '\ddd', where ddd is a three-digit decimal number.
-// The longest legal domain name is 256 bytes, in the form of four labels as shown below:
-// Length byte, 63 data bytes, length byte, 63 data bytes, length byte, 63 data bytes, length byte, 62 data bytes, zero byte.
-// Each label is encoded textually as characters followed by a trailing dot.
-// If every character has to be represented as a four-byte escape sequence, then this makes the maximum textual form four labels
-// plus the C-string terminating NULL as shown below:
-// 63*4+1 + 63*4+1 + 63*4+1 + 62*4+1 + 1 = 1009.
-// Note that MAX_ESCAPED_DOMAIN_LABEL is not normally used: If you're only decoding a single label, escaping is usually not required.
-// It is for domain names, where dots are used as label separators, that proper escaping is vital.
-#define MAX_ESCAPED_DOMAIN_LABEL 254
-#define MAX_ESCAPED_DOMAIN_NAME 1009
-
-// MAX_REVERSE_MAPPING_NAME
-// For IPv4: "123.123.123.123.in-addr.arpa."  30 bytes including terminating NUL
-// 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
-
-#define MAX_REVERSE_MAPPING_NAME_V4 30
-#define MAX_REVERSE_MAPPING_NAME_V6 74
-#define MAX_REVERSE_MAPPING_NAME    74
-
-// Most records have a TTL of 75 minutes, so that their 80% cache-renewal query occurs once per hour.
-// For records containing a hostname (in the name on the left, or in the rdata on the right),
-// like A, AAAA, reverse-mapping PTR, and SRV, we use a two-minute TTL by default, because we don't want
-// them to hang around for too long in the cache if the host in question crashes or otherwise goes away.
-
-#define kStandardTTL (3600UL * 100 / 80)
-#define kHostNameTTL 120UL
-
-// Some applications want to register their SRV records with a lower ttl so that in case the server
-// using a dynamic port number restarts, the clients will not have stale information for more than
-// 10 seconds
-
-#define kHostNameSmallTTL 10UL
-
-
-// Multicast DNS uses announcements (gratuitous responses) to update peer caches.
-// This means it is feasible to use relatively larger TTL values than we might otherwise
-// use, because we have a cache coherency protocol to keep the peer caches up to date.
-// With Unicast DNS, once an authoritative server gives a record with a certain TTL value to a client
-// or caching server, that client or caching server is entitled to hold onto the record until its TTL
-// expires, and has no obligation to contact the authoritative server again until that time arrives.
-// This means that whereas Multicast DNS can use announcements to pre-emptively update stale data
-// before it would otherwise have expired, standard Unicast DNS (not using LLQs) has no equivalent
-// mechanism, and TTL expiry is the *only* mechanism by which stale data gets deleted. Because of this,
-// we currently limit the TTL to ten seconds in such cases where no dynamic cache updating is possible.
-#define kStaticCacheTTL 10
-
-#define DefaultTTLforRRType(X) (((X) == kDNSType_A || (X) == kDNSType_AAAA || (X) == kDNSType_SRV) ? kHostNameTTL : kStandardTTL)
-
-typedef struct AuthRecord_struct AuthRecord;
-typedef struct ServiceRecordSet_struct ServiceRecordSet;
-typedef struct CacheRecord_struct CacheRecord;
-typedef struct CacheGroup_struct CacheGroup;
-typedef struct AuthGroup_struct AuthGroup;
-typedef struct DNSQuestion_struct DNSQuestion;
-typedef struct ZoneData_struct ZoneData;
-typedef struct mDNS_struct mDNS;
-typedef struct mDNS_PlatformSupport_struct mDNS_PlatformSupport;
-typedef struct NATTraversalInfo_struct NATTraversalInfo;
-
-// Structure to abstract away the differences between TCP/SSL sockets, and one for UDP sockets
-// The actual definition of these structures appear in the appropriate platform support code
-typedef struct TCPSocket_struct TCPSocket;
-typedef struct UDPSocket_struct UDPSocket;
-
-// ***************************************************************************
-#if 0
-#pragma mark -
-#pragma mark - DNS Message structures
-#endif
-
-#define mDNS_numZones   numQuestions
-#define mDNS_numPrereqs numAnswers
-#define mDNS_numUpdates numAuthorities
-
-typedef struct
-	{
-	mDNSOpaque16 id;
-	mDNSOpaque16 flags;
-	mDNSu16 numQuestions;
-	mDNSu16 numAnswers;
-	mDNSu16 numAuthorities;
-	mDNSu16 numAdditionals;
-	} DNSMessageHeader;
-
-// We can send and receive packets up to 9000 bytes (Ethernet Jumbo Frame size, if that ever becomes widely used)
-// However, in the normal case we try to limit packets to 1500 bytes so that we don't get IP fragmentation on standard Ethernet
-// 40 (IPv6 header) + 8 (UDP header) + 12 (DNS message header) + 1440 (DNS message body) = 1500 total
-#define AbsoluteMaxDNSMessageData 1500//8940
-#define NormalMaxDNSMessageData 1440
-typedef packedstruct
-	{
-	DNSMessageHeader h;						// Note: Size 12 bytes
-	mDNSu8 data[AbsoluteMaxDNSMessageData];	// 40 (IPv6) + 8 (UDP) + 12 (DNS header) + 8940 (data) = 9000
-	} DNSMessage;
-
-typedef struct tcpInfo_t
-	{
-	mDNS             *m;
-	TCPSocket        *sock;
-	DNSMessage        request;
-	int               requestLen;
-	DNSQuestion      *question;   // For queries
-	AuthRecord       *rr;         // For record updates
-	mDNSAddr          Addr;
-	mDNSIPPort        Port;
-	mDNSIPPort        SrcPort;
-	DNSMessage       *reply;
-	mDNSu16           replylen;
-	unsigned long     nread;
-	int               numReplies;
-	} tcpInfo_t;
-
-// ***************************************************************************
-#if 0
-#pragma mark -
-#pragma mark - Other Packet Format Structures
-#endif
-
-typedef packedstruct
-	{
-	mDNSEthAddr  dst;
-	mDNSEthAddr  src;
-	mDNSOpaque16 ethertype;
-	} EthernetHeader;		// 14 bytes
-
-typedef packedstruct
-	{
-	mDNSOpaque16 hrd;
-	mDNSOpaque16 pro;
-	mDNSu8       hln;
-	mDNSu8       pln;
-	mDNSOpaque16 op;
-	mDNSEthAddr  sha;
-	mDNSv4Addr   spa;
-	mDNSEthAddr  tha;
-	mDNSv4Addr   tpa;
-	} ARP_EthIP;			// 28 bytes
-
-typedef packedstruct
-	{
-	mDNSu8       vlen;
-	mDNSu8       tos;
-	mDNSu16      totlen;
-	mDNSOpaque16 id;
-	mDNSOpaque16 flagsfrags;
-	mDNSu8       ttl;
-	mDNSu8       protocol;	// Payload type: 0x06 = TCP, 0x11 = UDP
-	mDNSu16      checksum;
-	mDNSv4Addr   src;
-	mDNSv4Addr   dst;
-	} IPv4Header;			// 20 bytes
-
-typedef packedstruct
-	{
-	mDNSu32      vcf;		// Version, Traffic Class, Flow Label
-	mDNSu16      len;		// Payload Length
-	mDNSu8       pro;		// Type of next header: 0x06 = TCP, 0x11 = UDP, 0x3A = ICMPv6
-	mDNSu8       ttl;		// Hop Limit
-	mDNSv6Addr   src;
-	mDNSv6Addr   dst;
-	} IPv6Header;			// 40 bytes
-
-typedef packedstruct
-	{
-	mDNSv6Addr   src;
-	mDNSv6Addr   dst;
-	mDNSOpaque32 len;
-	mDNSOpaque32 pro;
-	} IPv6PseudoHeader;		// 40 bytes
-
-typedef union
-	{
-	mDNSu8       bytes[20];
-	ARP_EthIP    arp;
-	IPv4Header   v4;
-	IPv6Header   v6;
-	} NetworkLayerPacket;
-
-typedef packedstruct
-	{
-	mDNSIPPort   src;
-	mDNSIPPort   dst;
-	mDNSu32      seq;
-	mDNSu32      ack;
-	mDNSu8       offset;
-	mDNSu8       flags;
-	mDNSu16      window;
-	mDNSu16      checksum;
-	mDNSu16      urgent;
-	} TCPHeader;			// 20 bytes; IP protocol type 0x06
-
-typedef packedstruct
-	{
-	mDNSIPPort   src;
-	mDNSIPPort   dst;
-	mDNSu16      len;		// Length including UDP header (i.e. minimum value is 8 bytes)
-	mDNSu16      checksum;
-	} UDPHeader;			// 8 bytes; IP protocol type 0x11
-
-typedef packedstruct
-	{
-	mDNSu8       type;		// 0x87 == Neighbor Solicitation, 0x88 == Neighbor Advertisement
-	mDNSu8       code;
-	mDNSu16      checksum;
-	mDNSu32      flags_res;	// R/S/O flags and reserved bits
-	mDNSv6Addr   target;
-	// Typically 8 bytes of options are also present
-	} IPv6NDP;				// 24 bytes or more; IP protocol type 0x3A
-
-#define NDP_Sol 0x87
-#define NDP_Adv 0x88
-
-#define NDP_Router    0x80
-#define NDP_Solicited 0x40
-#define NDP_Override  0x20
-
-#define NDP_SrcLL 1
-#define NDP_TgtLL 2
-
-typedef union
-	{
-	mDNSu8       bytes[20];
-	TCPHeader    tcp;
-	UDPHeader    udp;
-	IPv6NDP      ndp;
-	} TransportLayerPacket;
-
-typedef packedstruct
-	{
-	mDNSOpaque64 InitiatorCookie;
-	mDNSOpaque64 ResponderCookie;
-	mDNSu8       NextPayload;
-	mDNSu8       Version;
-	mDNSu8       ExchangeType;
-	mDNSu8       Flags;
-	mDNSOpaque32 MessageID;
-	mDNSu32      Length;
-	} IKEHeader;			// 28 bytes
-
-// ***************************************************************************
-#if 0
-#pragma mark -
-#pragma mark - Resource Record structures
-#endif
-
-// Authoritative Resource Records:
-// There are four basic types: Shared, Advisory, Unique, Known Unique
-
-// * Shared Resource Records do not have to be unique
-// -- Shared Resource Records are used for DNS-SD service PTRs
-// -- It is okay for several hosts to have RRs with the same name but different RDATA
-// -- We use a random delay on responses to reduce collisions when all the hosts respond to the same query
-// -- These RRs typically have moderately high TTLs (e.g. one hour)
-// -- These records are announced on startup and topology changes for the benefit of passive listeners
-// -- These records send a goodbye packet when deregistering
-//
-// * Advisory Resource Records are like Shared Resource Records, except they don't send a goodbye packet
-//
-// * Unique Resource Records should be unique among hosts within any given mDNS scope
-// -- The majority of Resource Records are of this type
-// -- If two entities on the network have RRs with the same name but different RDATA, this is a conflict
-// -- Responses may be sent immediately, because only one host should be responding to any particular query
-// -- These RRs typically have low TTLs (e.g. a few minutes)
-// -- On startup and after topology changes, a host issues queries to verify uniqueness
-
-// * Known Unique Resource Records are treated like Unique Resource Records, except that mDNS does
-// not have to verify their uniqueness because this is already known by other means (e.g. the RR name
-// is derived from the host's IP or Ethernet address, which is already known to be a unique identifier).
-
-// Summary of properties of different record types:
-// Probe?    Does this record type send probes before announcing?
-// Conflict? Does this record type react if we observe an apparent conflict?
-// Goodbye?  Does this record type send a goodbye packet on departure?
-//
-//               Probe? Conflict? Goodbye? Notes
-// Unregistered                            Should not appear in any list (sanity check value)
-// Shared         No      No       Yes     e.g. Service PTR record
-// Deregistering  No      No       Yes     Shared record about to announce its departure and leave the list
-// Advisory       No      No       No
-// Unique         Yes     Yes      No      Record intended to be unique -- will probe to verify
-// Verified       Yes     Yes      No      Record has completed probing, and is verified unique
-// KnownUnique    No      Yes      No      Record is assumed by other means to be unique
-
-// Valid lifecycle of a record:
-// Unregistered ->                   Shared      -> Deregistering -(goodbye)-> Unregistered
-// Unregistered ->                   Advisory                               -> Unregistered
-// Unregistered -> Unique -(probe)-> Verified                               -> Unregistered
-// Unregistered ->                   KnownUnique                            -> Unregistered
-
-// Each Authoritative kDNSRecordType has only one bit set. This makes it easy to quickly see if a record
-// is one of a particular set of types simply by performing the appropriate bitwise masking operation.
-
-// Cache Resource Records (received from the network):
-// There are four basic types: Answer, Unique Answer, Additional, Unique Additional
-// Bit 7 (the top bit) of kDNSRecordType is always set for Cache Resource Records; always clear for Authoritative Resource Records
-// Bit 6 (value 0x40) is set for answer records; clear for authority/additional records
-// Bit 5 (value 0x20) is set for records received with the kDNSClass_UniqueRRSet
-
-enum
-	{
-	kDNSRecordTypeUnregistered     = 0x00,	// Not currently in any list
-	kDNSRecordTypeDeregistering    = 0x01,	// Shared record about to announce its departure and leave the list
-
-	kDNSRecordTypeUnique           = 0x02,	// Will become a kDNSRecordTypeVerified when probing is complete
-
-	kDNSRecordTypeAdvisory         = 0x04,	// Like Shared, but no goodbye packet
-	kDNSRecordTypeShared           = 0x08,	// Shared means record name does not have to be unique -- use random delay on responses
-
-	kDNSRecordTypeVerified         = 0x10,	// Unique means mDNS should check that name is unique (and then send immediate responses)
-	kDNSRecordTypeKnownUnique      = 0x20,	// Known Unique means mDNS can assume name is unique without checking
-	                                        // For Dynamic Update records, Known Unique means the record must already exist on the server.
-	kDNSRecordTypeUniqueMask       = (kDNSRecordTypeUnique | kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique),
-	kDNSRecordTypeActiveSharedMask = (kDNSRecordTypeAdvisory         | kDNSRecordTypeShared),
-	kDNSRecordTypeActiveUniqueMask = (kDNSRecordTypeVerified         | kDNSRecordTypeKnownUnique),
-	kDNSRecordTypeActiveMask       = (kDNSRecordTypeActiveSharedMask | kDNSRecordTypeActiveUniqueMask),
-
-	kDNSRecordTypePacketAdd        = 0x80,	// Received in the Additional  Section of a DNS Response
-	kDNSRecordTypePacketAddUnique  = 0x90,	// Received in the Additional  Section of a DNS Response with kDNSClass_UniqueRRSet set
-	kDNSRecordTypePacketAuth       = 0xA0,	// Received in the Authorities Section of a DNS Response
-	kDNSRecordTypePacketAuthUnique = 0xB0,	// Received in the Authorities Section of a DNS Response with kDNSClass_UniqueRRSet set
-	kDNSRecordTypePacketAns        = 0xC0,	// Received in the Answer      Section of a DNS Response
-	kDNSRecordTypePacketAnsUnique  = 0xD0,	// Received in the Answer      Section of a DNS Response with kDNSClass_UniqueRRSet set
-
-	kDNSRecordTypePacketNegative   = 0xF0,	// Pseudo-RR generated to cache non-existence results like NXDomain
-
-	kDNSRecordTypePacketUniqueMask = 0x10	// True for PacketAddUnique, PacketAnsUnique, PacketAuthUnique, kDNSRecordTypePacketNegative
-	};
-
-typedef packedstruct { mDNSu16 priority; mDNSu16 weight; mDNSIPPort port; domainname target;   } rdataSRV;
-typedef packedstruct { mDNSu16 preference;                                domainname exchange; } rdataMX;
-typedef packedstruct { domainname mbox; domainname txt;                                        } rdataRP;
-typedef packedstruct { mDNSu16 preference; domainname map822; domainname mapx400;              } rdataPX;
-
-typedef packedstruct
-	{
-	domainname mname;
-	domainname rname;
-	mDNSs32 serial;		// Modular counter; increases when zone changes
-	mDNSu32 refresh;	// Time in seconds that a slave waits after successful replication of the database before it attempts replication again
-	mDNSu32 retry;		// Time in seconds that a slave waits after an unsuccessful replication attempt before it attempts replication again
-	mDNSu32 expire;		// Time in seconds that a slave holds on to old data while replication attempts remain unsuccessful
-	mDNSu32 min;		// Nominally the minimum record TTL for this zone, in seconds; also used for negative caching.
-	} rdataSOA;
-
-// EDNS Option Code registrations are recorded in the "DNS EDNS0 Options" section of
-// <http://www.iana.org/assignments/dns-parameters>
-
-#define kDNSOpt_LLQ   1
-#define kDNSOpt_Lease 2
-#define kDNSOpt_NSID  3
-#define kDNSOpt_Owner 4
-
-typedef struct
-	{
-	mDNSu16      vers;
-	mDNSu16      llqOp;
-	mDNSu16      err;	// Or UDP reply port, in setup request
-	// Note: In the in-memory form, there's typically a two-byte space here, so that the following 64-bit id is word-aligned
-	mDNSOpaque64 id;
-	mDNSu32      llqlease;
-	} LLQOptData;
-
-typedef struct
-	{
-	mDNSu8       vers;		// Version number of this Owner OPT record
-	mDNSs8       seq;		// Sleep/wake epoch
-	mDNSEthAddr  HMAC;		// Host's primary identifier (e.g. MAC of on-board Ethernet)
-	mDNSEthAddr  IMAC;		// Interface's MAC address (if different to primary MAC)
-	mDNSOpaque48 password;	// Optional password
-	} OwnerOptData;
-
-// Note: rdataOPT format may be repeated an arbitrary number of times in a single resource record
-typedef packedstruct
-	{
-	mDNSu16 opt;
-	mDNSu16 optlen;
-	union { LLQOptData llq; mDNSu32 updatelease; OwnerOptData owner; } u;
-	} rdataOPT;
-
-// Space needed to put OPT records into a packet:
-// Header      11 bytes (name 1, type 2, class 2, TTL 4, length 2)
-// LLQ rdata   18 bytes (opt 2, len 2, vers 2, op 2, err 2, id 8, lease 4)
-// Lease rdata  8 bytes (opt 2, len 2, lease 4)
-// Owner rdata 12-24    (opt 2, len 2, owner 8-20)
-
-#define DNSOpt_Header_Space                 11
-#define DNSOpt_LLQData_Space               (4 + 2 + 2 + 2 + 8 + 4)
-#define DNSOpt_LeaseData_Space             (4 + 4)
-#define DNSOpt_OwnerData_ID_Space          (4 + 2 + 6)
-#define DNSOpt_OwnerData_ID_Wake_Space     (4 + 2 + 6 + 6)
-#define DNSOpt_OwnerData_ID_Wake_PW4_Space (4 + 2 + 6 + 6 + 4)
-#define DNSOpt_OwnerData_ID_Wake_PW6_Space (4 + 2 + 6 + 6 + 6)
-
-#define ValidOwnerLength(X) (	(X) == DNSOpt_OwnerData_ID_Space          - 4 || \
-								(X) == DNSOpt_OwnerData_ID_Wake_Space     - 4 || \
-								(X) == DNSOpt_OwnerData_ID_Wake_PW4_Space - 4 || \
-								(X) == DNSOpt_OwnerData_ID_Wake_PW6_Space - 4    )
-
-#define DNSOpt_Owner_Space(A,B) (mDNSSameEthAddress((A),(B)) ? DNSOpt_OwnerData_ID_Space : DNSOpt_OwnerData_ID_Wake_Space)
-
-#define DNSOpt_Data_Space(O) (                                  \
-	(O)->opt == kDNSOpt_LLQ   ? DNSOpt_LLQData_Space   :        \
-	(O)->opt == kDNSOpt_Lease ? DNSOpt_LeaseData_Space :        \
-	(O)->opt == kDNSOpt_Owner ? DNSOpt_Owner_Space(&(O)->u.owner.HMAC, &(O)->u.owner.IMAC) : 0x10000)
-
-// A maximal NSEC record is:
-//   256 bytes domainname 'nextname'
-// + 256 * 34 = 8704 bytes of bitmap data
-// = 8960 bytes total
-// For now we only support NSEC records encoding DNS types 0-255 and ignore the nextname (we always set it to be the same as the rrname),
-// which gives us a fixed in-memory size of 32 bytes (256 bits)
-typedef struct
-	{
-	mDNSu8 bitmap[32];
-	} rdataNSEC;
-
-// StandardAuthRDSize is 264 (256+8), which is large enough to hold a maximum-sized SRV record (6 + 256 bytes)
-// MaximumRDSize is 8K the absolute maximum we support (at least for now)
-#define StandardAuthRDSize 264
-#define MaximumRDSize 8192
-
-// InlineCacheRDSize is 68
-// Records received from the network with rdata this size or less have their rdata stored right in the CacheRecord object
-// Records received from the network with rdata larger than this have additional storage allocated for the rdata
-// A quick unscientific sample from a busy network at Apple with lots of machines revealed this:
-// 1461 records in cache
-// 292 were one-byte TXT records
-// 136 were four-byte A records
-// 184 were sixteen-byte AAAA records
-// 780 were various PTR, TXT and SRV records from 12-64 bytes
-// Only 69 records had rdata bigger than 64 bytes
-// Note that since CacheRecord object and a CacheGroup object are allocated out of the same pool, it's sensible to
-// have them both be the same size. Making one smaller without making the other smaller won't actually save any memory.
-#define InlineCacheRDSize 68
-
-// On 64-bit, the pointers in a CacheRecord are bigger, and that creates 8 bytes more space for the name in a CacheGroup
-#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
-	#if defined(_ILP64) || defined(__ILP64__) || defined(_LP64) || defined(__LP64__) || defined(_WIN64)
-	#define InlineCacheGroupNameSize 160
-	#else
-	#define InlineCacheGroupNameSize 148
-	#endif
-#else
-	#if defined(_ILP64) || defined(__ILP64__) || defined(_LP64) || defined(__LP64__) || defined(_WIN64)
-	#define InlineCacheGroupNameSize 144
-	#else
-	#define InlineCacheGroupNameSize 132
-	#endif
-#endif
-
-// The RDataBody union defines the common rdata types that fit into our 264-byte limit
-typedef union
-	{
-	mDNSu8      data[StandardAuthRDSize];
-	mDNSv4Addr  ipv4;		// For 'A' record
-	domainname  name;		// For PTR, NS, CNAME, DNAME
-	UTF8str255  txt;
-	rdataMX     mx;
-	mDNSv6Addr  ipv6;		// For 'AAAA' record
-	rdataSRV    srv;
-	rdataOPT    opt[2];		// For EDNS0 OPT record; RDataBody may contain multiple variable-length rdataOPT objects packed together
-	rdataNSEC   nsec;
-	} RDataBody;
-
-// The RDataBody2 union is the same as above, except it includes fields for the larger types like soa, rp, px
-typedef union
-	{
-	mDNSu8      data[StandardAuthRDSize];
-	mDNSv4Addr  ipv4;		// For 'A' record
-	domainname  name;		// For PTR, NS, CNAME, DNAME
-	rdataSOA    soa;		// This is large; not included in the normal RDataBody definition
-	UTF8str255  txt;
-	rdataMX     mx;
-	rdataRP     rp;			// This is large; not included in the normal RDataBody definition
-	rdataPX     px;			// This is large; not included in the normal RDataBody definition
-	mDNSv6Addr  ipv6;		// For 'AAAA' record
-	rdataSRV    srv;
-	rdataOPT    opt[2];		// For EDNS0 OPT record; RDataBody may contain multiple variable-length rdataOPT objects packed together
-	rdataNSEC   nsec;
-	} RDataBody2;
-
-typedef struct
-	{
-	mDNSu16    MaxRDLength;	// Amount of storage allocated for rdata (usually sizeof(RDataBody))
-	mDNSu16    padding;		// So that RDataBody is aligned on 32-bit boundary
-	RDataBody  u;
-	} RData;
-
-// sizeofRDataHeader should be 4 bytes
-#define sizeofRDataHeader (sizeof(RData) - sizeof(RDataBody))
-
-// RData_small is a smaller version of the RData object, used for inline data storage embedded in a CacheRecord_struct
-typedef struct
-	{
-	mDNSu16    MaxRDLength;	// Storage allocated for data (may be greater than InlineCacheRDSize if additional storage follows this object)
-	mDNSu16    padding;		// So that data is aligned on 32-bit boundary
-	mDNSu8     data[InlineCacheRDSize];
-	} RData_small;
-
-// Note: Within an mDNSRecordCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
-typedef void mDNSRecordCallback(mDNS *const m, AuthRecord *const rr, mStatus result);
-
-// Note:
-// Restrictions: An mDNSRecordUpdateCallback may not make any mDNS API calls.
-// The intent of this callback is to allow the client to free memory, if necessary.
-// The internal data structures of the mDNS code may not be in a state where mDNS API calls may be made safely.
-typedef void mDNSRecordUpdateCallback(mDNS *const m, AuthRecord *const rr, RData *OldRData, mDNSu16 OldRDLen);
-
-// ***************************************************************************
-#if 0
-#pragma mark -
-#pragma mark - NAT Traversal structures and constants
-#endif
-
-#define NATMAP_MAX_RETRY_INTERVAL    ((mDNSPlatformOneSecond * 60) * 15)    // Max retry interval is 15 minutes
-#define NATMAP_MIN_RETRY_INTERVAL     (mDNSPlatformOneSecond * 2)           // Min retry interval is 2 seconds
-#define NATMAP_INIT_RETRY             (mDNSPlatformOneSecond / 4)           // start at 250ms w/ exponential decay
-#define NATMAP_DEFAULT_LEASE          (60 * 60 * 2)                         // 2 hour lease life in seconds
-#define NATMAP_VERS 0
-
-typedef enum
-	{
-	NATOp_AddrRequest    = 0,
-	NATOp_MapUDP         = 1,
-	NATOp_MapTCP         = 2,
-	
-	NATOp_AddrResponse   = 0x80 | 0,
-	NATOp_MapUDPResponse = 0x80 | 1,
-	NATOp_MapTCPResponse = 0x80 | 2,
-	} NATOp_t;
-
-enum
-	{
-	NATErr_None    = 0,
-	NATErr_Vers    = 1,
-	NATErr_Refused = 2,
-	NATErr_NetFail = 3,
-	NATErr_Res     = 4,
-	NATErr_Opcode  = 5
-	};
-
-typedef mDNSu16 NATErr_t;
-
-typedef packedstruct
-	{
-	mDNSu8 vers;
-	mDNSu8 opcode;
-	} NATAddrRequest;
-
-typedef packedstruct
-	{
-	mDNSu8     vers;
-	mDNSu8     opcode;
-	mDNSu16    err;
-	mDNSu32    upseconds;		// Time since last NAT engine reboot, in seconds
-	mDNSv4Addr ExtAddr;
-	} NATAddrReply;
-
-typedef packedstruct
-	{
-	mDNSu8 vers;
-	mDNSu8 opcode;
-	mDNSOpaque16 unused;
-	mDNSIPPort intport;
-	mDNSIPPort extport;
-	mDNSu32    NATReq_lease;
-	} NATPortMapRequest;
-
-typedef packedstruct
-	{
-	mDNSu8     vers;
-	mDNSu8     opcode;
-	mDNSu16    err;
-	mDNSu32    upseconds;		// Time since last NAT engine reboot, in seconds
-	mDNSIPPort intport;
-	mDNSIPPort extport;
-	mDNSu32    NATRep_lease;
-	} NATPortMapReply;
-
-typedef enum
-	{
-	LNTDiscoveryOp      = 1,
-	LNTExternalAddrOp   = 2,
-	LNTPortMapOp        = 3,
-	LNTPortMapDeleteOp  = 4
-	} LNTOp_t;
-
-#define LNT_MAXBUFSIZE 8192
-typedef struct tcpLNTInfo_struct tcpLNTInfo;
-struct tcpLNTInfo_struct
-	{
-	tcpLNTInfo       *next;
-	mDNS             *m;
-	NATTraversalInfo *parentNATInfo;	// pointer back to the parent NATTraversalInfo
-	TCPSocket        *sock;
-	LNTOp_t           op;				// operation performed using this connection
-	mDNSAddr          Address;			// router address
-	mDNSIPPort        Port;				// router port
-	mDNSu8           *Request;			// xml request to router
-	int               requestLen;
-	mDNSu8           *Reply;			// xml reply from router
-	int               replyLen;
-	unsigned long     nread;			// number of bytes read so far
-	int               retries;			// number of times we've tried to do this port mapping
-	};
-
-typedef void (*NATTraversalClientCallback)(mDNS *m, NATTraversalInfo *n);
-
-// if m->timenow <  ExpiryTime then we have an active mapping, and we'll renew halfway to expiry
-// if m->timenow >= ExpiryTime then our mapping has expired, and we're trying to create one
-
-struct NATTraversalInfo_struct
-	{
-	// Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
-	NATTraversalInfo           *next;
-
-	mDNSs32                     ExpiryTime;			// Time this mapping expires, or zero if no mapping
-	mDNSs32                     retryInterval;		// Current interval, between last packet we sent and the next one
-	mDNSs32                     retryPortMap;		// If Protocol is nonzero, time to send our next mapping packet
-	mStatus                     NewResult;			// New error code; will be copied to Result just prior to invoking callback
-
-#ifdef _LEGACY_NAT_TRAVERSAL_
-	tcpLNTInfo                  tcpInfo;			// Legacy NAT traversal (UPnP) TCP connection
-#endif
-
-	// Result fields: When the callback is invoked these fields contain the answers the client is looking for
-	// When the callback is invoked ExternalPort is *usually* set to be the same the same as RequestedPort, except:
-	// (a) When we're behind a NAT gateway with port mapping disabled, ExternalPort is reported as zero to
-	//     indicate that we don't currently have a working mapping (but RequestedPort retains the external port
-	//     we'd like to get, the next time we meet an accomodating NAT gateway willing to give us one).
-	// (b) When we have a routable non-RFC1918 address, we don't *need* a port mapping, so ExternalPort
-	//     is reported as the same as our InternalPort, since that is effectively our externally-visible port too.
-	//     Again, RequestedPort retains the external port we'd like to get the next time we find ourself behind a NAT gateway.
-	// To improve stability of port mappings, RequestedPort is updated any time we get a successful
-	// mapping response from the NAT-PMP or UPnP gateway. For example, if we ask for port 80, and
-	// get assigned port 81, then thereafter we'll contine asking for port 81.
-	mDNSInterfaceID             InterfaceID;
-	mDNSv4Addr                  ExternalAddress;	// Initially set to onesIPv4Addr, until first callback
-	mDNSIPPort                  ExternalPort;
-	mDNSu32                     Lifetime;
-	mStatus                     Result;
-
-	// Client API fields: The client must set up these fields *before* making any NAT traversal API calls
-	mDNSu8                      Protocol;			// NATOp_MapUDP or NATOp_MapTCP, or zero if just requesting the external IP address
-	mDNSIPPort                  IntPort;			// Client's internal port number (doesn't change)
-	mDNSIPPort                  RequestedPort;		// Requested external port; may be updated with actual value assigned by gateway
-	mDNSu32                     NATLease;			// Requested lifetime in seconds (doesn't change)
-	NATTraversalClientCallback  clientCallback;
-	void                       *clientContext;
-	};
-
-enum
-	{
-	DNSServer_Untested = 0,
-	DNSServer_Passed   = 1,
-	DNSServer_Failed   = 2,
-	DNSServer_Disabled = 3
-	};
-
-enum
-	{
-	DNSServer_FlagDelete = 1,
-	DNSServer_FlagNew    = 2
-	};
-
-enum
-	{
-	McastResolver_FlagDelete = 1,
-	McastResolver_FlagNew    = 2
-	};
-
-typedef struct McastResolver
-	{
-	struct McastResolver *next;
-	mDNSInterfaceID interface;
-	mDNSu32         flags;		// Set when we're planning to delete this from the list
-	domainname      domain;
-	mDNSu32         timeout;	// timeout value for questions
-	} McastResolver;
-
-typedef struct DNSServer
-	{
-	struct DNSServer *next;
-	mDNSInterfaceID interface;	// For specialized uses; we can have DNS servers reachable over specific interfaces
-	mDNSAddr        addr;
-	mDNSIPPort      port;
-	mDNSOpaque16    testid;
-	mDNSu32         flags;		// Set when we're planning to delete this from the list
-	mDNSu32         teststate;	// Have we sent bug-detection query to this server?
-	mDNSs32         lasttest;	// Time we sent last bug-detection query to this server
-	domainname      domain;		// name->server matching for "split dns"
-	mDNSs32			penaltyTime; // amount of time this server is penalized
-	mDNSBool		scoped;		// interface should be matched against question only
-								// if scoped is set
-	mDNSu32			timeout;	// timeout value for questions
-	} DNSServer;
-
-typedef struct							// Size is 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit
-	{
-	mDNSu8           RecordType;		// See enum above
-	mDNSu16          rrtype;
-	mDNSu16          rrclass;
-	mDNSu32          rroriginalttl;		// In seconds
-	mDNSu16          rdlength;			// Size of the raw rdata, in bytes, in the on-the-wire format
-										// (In-memory storage may be larger, for structures containing 'holes', like SOA,
-										// or smaller, for NSEC where we don't bother storing the nextname field)
-	mDNSu16          rdestimate;		// Upper bound on on-the-wire size of rdata after name compression
-	mDNSu32          namehash;			// Name-based (i.e. case-insensitive) hash of name
-	mDNSu32          rdatahash;			// For rdata containing domain name (e.g. PTR, SRV, CNAME etc.), case-insensitive name hash
-										// else, for all other rdata, 32-bit hash of the raw rdata
-										// Note: This requirement is important. Various routines like AddAdditionalsToResponseList(),
-										// ReconfirmAntecedents(), etc., use rdatahash as a pre-flight check to see
-										// whether it's worth doing a full SameDomainName() call. If the rdatahash
-										// is not a correct case-insensitive name hash, they'll get false negatives.
-
-	// Grouping pointers together at the end of the structure improves the memory layout efficiency
-	mDNSInterfaceID  InterfaceID;		// Set if this RR is specific to one interface
-										// For records received off the wire, InterfaceID is *always* set to the receiving interface
-										// For our authoritative records, InterfaceID is usually zero, except for those few records
-										// that are interface-specific (e.g. address records, especially linklocal addresses)
-	const domainname *name;
-	RData           *rdata;				// Pointer to storage for this rdata
-	DNSServer       *rDNSServer;		// Unicast DNS server authoritative for this entry;null for multicast
-	} ResourceRecord;
-
-// Unless otherwise noted, states may apply to either independent record registrations or service registrations
-typedef enum
-	{
-	regState_Zero              = 0,
-	regState_Pending           = 1,     // update sent, reply not received
-	regState_Registered        = 2,     // update sent, reply received
-	regState_DeregPending      = 3,     // dereg sent, reply not received
-	regState_Unregistered      = 4,     // not in any list
-	regState_Refresh           = 5,     // outstanding refresh (or target change) message
-	regState_NATMap            = 6,     // establishing NAT port mapping 
-	regState_UpdatePending     = 7,     // update in flight as result of mDNS_Update call
-	regState_NoTarget          = 8,     // SRV Record registration pending registration of hostname 
-	regState_NATError          = 9     // unable to complete NAT traversal
-	} regState_t;
-
-enum
-	{
-	Target_Manual = 0,
-	Target_AutoHost = 1,
-	Target_AutoHostAndNATMAP = 2
-	};
-
-typedef enum
-	{
-	mergeState_Zero = 0,
-	mergeState_DontMerge = 1  // Set on fatal error conditions to disable merging
-	} mergeState_t;
-
-struct AuthGroup_struct				// Header object for a list of AuthRecords with the same name
-	{
-	AuthGroup      *next;				// Next AuthGroup object in this hash table bucket
-	mDNSu32         namehash;			// Name-based (i.e. case insensitive) hash of name
-	AuthRecord     *members;			// List of CacheRecords with this same name
-	AuthRecord    **rrauth_tail;		// Tail end of that list
-	domainname     *name;				// Common name for all AuthRecords in this list
-	AuthRecord     *NewLocalOnlyRecords;
-	// Size to here is 20 bytes when compiling 32-bit; 40 bytes when compiling 64-bit
-	mDNSu8          namestorage[InlineCacheGroupNameSize];
-	};
-
-#define AUTH_HASH_SLOTS 499
-#define FORALL_AUTHRECORDS(SLOT,AG,AR)                           	\
-	for ((SLOT) = 0; (SLOT) < AUTH_HASH_SLOTS; (SLOT)++)         	\
-		for ((AG)=m->rrauth.rrauth_hash[(SLOT)]; (AG); (AG)=(AG)->next) \
-			for ((AR) = (AG)->members; (AR); (AR)=(AR)->next)
-
-typedef union AuthEntity_union AuthEntity;
-union AuthEntity_union { AuthEntity *next; AuthGroup ag; };
-typedef struct {
-	mDNSu32 rrauth_size;				// Total number of available auth entries
-	mDNSu32 rrauth_totalused;			// Number of auth entries currently occupied
-	mDNSu32 rrauth_report;
-	mDNSu8  rrauth_lock;				// For debugging: Set at times when these lists may not be modified
-	AuthEntity *rrauth_free;
-	AuthGroup *rrauth_hash[AUTH_HASH_SLOTS];
-}AuthHash;
-
-// AuthRecordAny includes mDNSInterface_Any and interface specific auth records (anything
-// other than P2P or LocalOnly)
-typedef enum 
-	{
-	AuthRecordAny, 				// registered for *Any, NOT including P2P interfaces
-	AuthRecordAnyIncludeP2P, 	// registered for *Any, including P2P interfaces
-	AuthRecordLocalOnly, 
-	AuthRecordP2P				// discovered over D2D/P2P framework
-	} AuthRecType;
-
-struct AuthRecord_struct
-	{
-	// For examples of how to set up this structure for use in mDNS_Register(),
-	// see mDNS_AdvertiseInterface() or mDNS_RegisterService().
-	// Basically, resrec and persistent metadata need to be set up before calling mDNS_Register().
-	// mDNS_SetupResourceRecord() is avaliable as a helper routine to set up most fields to sensible default values for you
-
-	AuthRecord     *next;				// Next in list; first element of structure for efficiency reasons
-	// Field Group 1: Common ResourceRecord fields
-	ResourceRecord  resrec;				// 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit
-
-	// Field Group 2: Persistent metadata for Authoritative Records
-	AuthRecord     *Additional1;		// Recommended additional record to include in response (e.g. SRV for PTR record)
-	AuthRecord     *Additional2;		// Another additional (e.g. TXT for PTR record)
-	AuthRecord     *DependentOn;		// This record depends on another for its uniqueness checking
-	AuthRecord     *RRSet;				// This unique record is part of an RRSet
-	mDNSRecordCallback *RecordCallback;	// Callback function to call for state changes, and to free memory asynchronously on deregistration
-	void           *RecordContext;		// Context parameter for the callback function
-	mDNSu8          AutoTarget;			// Set if the target of this record (PTR, CNAME, SRV, etc.) is our host name
-	mDNSu8          AllowRemoteQuery;	// Set if we allow hosts not on the local link to query this record
-	mDNSu8          ForceMCast;			// Set by client to advertise solely via multicast, even for apparently unicast names
-
-	OwnerOptData    WakeUp;				// WakeUp.HMAC.l[0] nonzero indicates that this is a Sleep Proxy record
-	mDNSAddr        AddressProxy;		// For reverse-mapping Sleep Proxy PTR records, address in question
-	mDNSs32         TimeRcvd;			// In platform time units
-	mDNSs32         TimeExpire;			// In platform time units
-	AuthRecType     ARType;             // LocalOnly, P2P or Normal ?
-
-	// Field Group 3: Transient state for Authoritative Records
-	mDNSu8          Acknowledged;		// Set if we've given the success callback to the client
-	mDNSu8          ProbeCount;			// Number of probes remaining before this record is valid (kDNSRecordTypeUnique)
-	mDNSu8          AnnounceCount;		// Number of announcements remaining (kDNSRecordTypeShared)
-	mDNSu8          RequireGoodbye;		// Set if this RR has been announced on the wire and will require a goodbye packet
-	mDNSu8          AnsweredLocalQ;		// Set if this AuthRecord has been delivered to any local question (LocalOnly or mDNSInterface_Any)
-	mDNSu8          IncludeInProbe;		// Set if this RR is being put into a probe right now
-	mDNSu8          ImmedUnicast;		// Set if we may send our response directly via unicast to the requester
-	mDNSInterfaceID SendNSECNow;		// Set if we need to generate associated NSEC data for this rrname
-	mDNSInterfaceID ImmedAnswer;		// Someone on this interface issued a query we need to answer (all-ones for all interfaces)
-#if MDNS_LOG_ANSWER_SUPPRESSION_TIMES
-	mDNSs32         ImmedAnswerMarkTime;
-#endif
-	mDNSInterfaceID ImmedAdditional;	// Hint that we might want to also send this record, just to be helpful
-	mDNSInterfaceID SendRNow;			// The interface this query is being sent on right now
-	mDNSv4Addr      v4Requester;		// Recent v4 query for this record, or all-ones if more than one recent query
-	mDNSv6Addr      v6Requester;		// Recent v6 query for this record, or all-ones if more than one recent query
-	AuthRecord     *NextResponse;		// Link to the next element in the chain of responses to generate
-	const mDNSu8   *NR_AnswerTo;		// Set if this record was selected by virtue of being a direct answer to a question
-	AuthRecord     *NR_AdditionalTo;	// Set if this record was selected by virtue of being additional to another
-	mDNSs32         ThisAPInterval;		// In platform time units: Current interval for announce/probe
-	mDNSs32         LastAPTime;			// In platform time units: Last time we sent announcement/probe
-	mDNSs32         LastMCTime;			// Last time we multicast this record (used to guard against packet-storm attacks)
-	mDNSInterfaceID LastMCInterface;	// Interface this record was multicast on at the time LastMCTime was recorded
-	RData          *NewRData;			// Set if we are updating this record with new rdata
-	mDNSu16         newrdlength;		// ... and the length of the new RData
-	mDNSRecordUpdateCallback *UpdateCallback;
-	mDNSu32         UpdateCredits;		// Token-bucket rate limiting of excessive updates
-	mDNSs32         NextUpdateCredit;	// Time next token is added to bucket
-	mDNSs32         UpdateBlocked;		// Set if update delaying is in effect
-
-	// Field Group 4: Transient uDNS state for Authoritative Records
-	regState_t   state;			// Maybe combine this with resrec.RecordType state? Right now it's ambiguous and confusing.
-								// e.g. rr->resrec.RecordType can be kDNSRecordTypeUnregistered,
-								// and rr->state can be regState_Unregistered
-								// What if we find one of those statements is true and the other false? What does that mean?
-	mDNSBool     uselease;		// dynamic update contains (should contain) lease option
-	mDNSs32      expire;		// In platform time units: expiration of lease (-1 for static)
-	mDNSBool     Private;		// If zone is private, DNS updates may have to be encrypted to prevent eavesdropping
-	mDNSOpaque16 updateid;		// Identifier to match update request and response -- also used when transferring records to Sleep Proxy
-	const domainname *zone;		// the zone that is updated
-	ZoneData  *nta;
-	struct tcpInfo_t *tcp;
-	NATTraversalInfo  NATinfo;
-	mDNSBool SRVChanged;       // temporarily deregistered service because its SRV target or port changed
-	mergeState_t  mState;      // Unicast Record Registrations merge state
-	mDNSu8		  refreshCount; // Number of refreshes to the server
-	mStatus		  updateError;  // Record update resulted in Error ?
-
-	// uDNS_UpdateRecord support fields
-	// Do we really need all these in *addition* to NewRData and newrdlength above?
-	void *UpdateContext;	// Context parameter for the update callback function
-	mDNSu16 OrigRDLen;		// previously registered, being deleted
-	mDNSu16 InFlightRDLen;	// currently being registered
-	mDNSu16 QueuedRDLen;	// pending operation (re-transmitting if necessary) THEN register the queued update
-	RData *OrigRData;
-	RData *InFlightRData;
-	RData *QueuedRData;
-
-	// Field Group 5: Large data objects go at the end
-	domainname      namestorage;
-	RData           rdatastorage;		// Normally the storage is right here, except for oversized records
-	// rdatastorage MUST be the last thing in the structure -- when using oversized AuthRecords, extra bytes
-	// are appended after the end of the AuthRecord, logically augmenting the size of the rdatastorage
-	// DO NOT ADD ANY MORE FIELDS HERE
-	};
-
-// IsLocalDomain alone is not sufficient to determine that a record is mDNS or uDNS. By default domain names within
-// the "local" pseudo-TLD (and within the IPv4 and IPv6 link-local reverse mapping domains) are automatically treated
-// as mDNS records, but it is also possible to force any record (even those not within one of the inherently local
-// domains) to be handled as an mDNS record by setting the ForceMCast flag, or by setting a non-zero InterfaceID.
-// For example, the reverse-mapping PTR record created in AdvertiseInterface sets the ForceMCast flag, since it points to
-// a dot-local hostname, and therefore it would make no sense to register this record with a wide-area Unicast DNS server.
-// The same applies to Sleep Proxy records, which we will answer for when queried via mDNS, but we never want to try
-// to register them with a wide-area Unicast DNS server -- and we probably don't have the required credentials anyway.
-// Currently we have no concept of a wide-area uDNS record scoped to a particular interface, so if the InterfaceID is
-// nonzero we treat this the same as ForceMCast.
-// Note: Question_uDNS(Q) is used in *only* one place -- on entry to mDNS_StartQuery_internal, to decide whether to set TargetQID.
-// Everywhere else in the code, the determination of whether a question is unicast is made by checking to see if TargetQID is nonzero.
-#define AuthRecord_uDNS(R) ((R)->resrec.InterfaceID == mDNSInterface_Any && !(R)->ForceMCast && !IsLocalDomain((R)->resrec.name))
-#define Question_uDNS(Q)   ((Q)->InterfaceID == mDNSInterface_Unicast || \
-	((Q)->InterfaceID != mDNSInterface_LocalOnly && (Q)->InterfaceID != mDNSInterface_P2P && !(Q)->ForceMCast && !IsLocalDomain(&(Q)->qname)))
-
-#define RRLocalOnly(rr) ((rr)->ARType == AuthRecordLocalOnly || (rr)->ARType == AuthRecordP2P)
-
-#define RRAny(rr) ((rr)->ARType == AuthRecordAny || (rr)->ARType == AuthRecordAnyIncludeP2P)
-
-// Question (A or AAAA) that is suppressed currently because IPv4 or IPv6 address
-// is not available locally for A or AAAA question respectively
-#define QuerySuppressed(Q) ((Q)->SuppressUnusable && (Q)->SuppressQuery)
-
-#define PrivateQuery(Q) ((Q)->AuthInfo && (Q)->AuthInfo->AutoTunnel)
-
-// Normally we always lookup the cache and /etc/hosts before sending the query on the wire. For single label
-// queries (A and AAAA) that are unqualified (indicated by AppendSearchDomains), we want to append search
-// domains before we try them as such
-#define ApplySearchDomainsFirst(q) ((q)->AppendSearchDomains && (CountLabels(&((q)->qname))) == 1)
-
-// Wrapper struct for Auth Records for higher-level code that cannot use the AuthRecord's ->next pointer field
-typedef struct ARListElem
-	{
-	struct ARListElem *next;
-	AuthRecord ar;          // Note: Must be last element of structure, to accomodate oversized AuthRecords
-	} ARListElem;
-
-struct CacheGroup_struct				// Header object for a list of CacheRecords with the same name
-	{
-	CacheGroup     *next;				// Next CacheGroup object in this hash table bucket
-	mDNSu32         namehash;			// Name-based (i.e. case insensitive) hash of name
-	CacheRecord    *members;			// List of CacheRecords with this same name
-	CacheRecord   **rrcache_tail;		// Tail end of that list
-	domainname     *name;				// Common name for all CacheRecords in this list
-	// Size to here is 20 bytes when compiling 32-bit; 40 bytes when compiling 64-bit
-	mDNSu8          namestorage[InlineCacheGroupNameSize];
-	};
-
-
-struct CacheRecord_struct
-	{
-	CacheRecord    *next;				// Next in list; first element of structure for efficiency reasons
-	ResourceRecord  resrec;				// 36 bytes when compiling for 32-bit; 48 when compiling for 64-bit
-
-	// Transient state for Cache Records
-	CacheRecord    *NextInKAList;		// Link to the next element in the chain of known answers to send
-	mDNSs32         TimeRcvd;			// In platform time units
-	mDNSs32         DelayDelivery;		// Set if we want to defer delivery of this answer to local clients
-	mDNSs32         NextRequiredQuery;	// In platform time units
-	mDNSs32         LastUsed;			// In platform time units
-	DNSQuestion    *CRActiveQuestion;	// Points to an active question referencing this answer. Can never point to a NewQuestion.
-	mDNSu32         UnansweredQueries;	// Number of times we've issued a query for this record without getting an answer
-	mDNSs32         LastUnansweredTime;	// In platform time units; last time we incremented UnansweredQueries
-#if ENABLE_MULTI_PACKET_QUERY_SNOOPING
-	mDNSu32         MPUnansweredQ;		// Multi-packet query handling: Number of times we've seen a query for this record
-	mDNSs32         MPLastUnansweredQT;	// Multi-packet query handling: Last time we incremented MPUnansweredQ
-	mDNSu32         MPUnansweredKA;		// Multi-packet query handling: Number of times we've seen this record in a KA list
-	mDNSBool        MPExpectingKA;		// Multi-packet query handling: Set when we increment MPUnansweredQ; allows one KA
-#endif
-	CacheRecord    *NextInCFList;		// Set if this is in the list of records we just received with the cache flush bit set
-	// Size to here is 76 bytes when compiling 32-bit; 104 bytes when compiling 64-bit
-	RData_small     smallrdatastorage;	// Storage for small records is right here (4 bytes header + 68 bytes data = 72 bytes)
-	};
-
-// Storage sufficient to hold either a CacheGroup header or a CacheRecord
-// -- for best efficiency (to avoid wasted unused storage) they should be the same size
-typedef union CacheEntity_union CacheEntity;
-union CacheEntity_union { CacheEntity *next; CacheGroup cg; CacheRecord cr; };
-
-typedef struct
-	{
-	CacheRecord r;
-	mDNSu8 _extradata[MaximumRDSize-InlineCacheRDSize];		// Glue on the necessary number of extra bytes
-	domainname namestorage;									// Needs to go *after* the extra rdata bytes
-	} LargeCacheRecord;
-
-typedef struct HostnameInfo
-	{
-	struct HostnameInfo *next;
-	NATTraversalInfo natinfo;
-	domainname fqdn;
-	AuthRecord arv4;                          // registered IPv4 address record
-	AuthRecord arv6;                          // registered IPv6 address record
-	mDNSRecordCallback *StatusCallback;       // callback to deliver success or error code to client layer
-	const void *StatusContext;                // Client Context
-	} HostnameInfo;
-
-typedef struct ExtraResourceRecord_struct ExtraResourceRecord;
-struct ExtraResourceRecord_struct
-	{
-	ExtraResourceRecord *next;
-	mDNSu32 ClientID;  // Opaque ID field to be used by client to map an AddRecord call to a set of Extra records
-	AuthRecord r;
-	// Note: Add any additional fields *before* the AuthRecord in this structure, not at the end.
-	// In some cases clients can allocate larger chunks of memory and set r->rdata->MaxRDLength to indicate
-	// that this extra memory is available, which would result in any fields after the AuthRecord getting smashed
-	};
-
-// Note: Within an mDNSServiceCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
-typedef void mDNSServiceCallback(mDNS *const m, ServiceRecordSet *const sr, mStatus result);
-
-// A ServiceRecordSet has no special meaning to the core code of the Multicast DNS protocol engine;
-// it is just a convenience structure to group together the records that make up a standard service
-// registration so that they can be allocted and deallocted together as a single memory object.
-// It contains its own ServiceCallback+ServiceContext to report aggregate results up to the next layer of software above.
-// It also contains:
-//  * the basic PTR/SRV/TXT triplet used to represent any DNS-SD service
-//  * the "_services" PTR record for service enumeration
-//  * the optional list of SubType PTR records
-//  * the optional list of additional records attached to the service set (e.g. iChat pictures)
-
-struct ServiceRecordSet_struct
-	{
-	// These internal state fields are used internally by mDNSCore; the client layer needn't be concerned with them.
-	// No fields need to be set up by the client prior to calling mDNS_RegisterService();
-	// all required data is passed as parameters to that function.
-	mDNSServiceCallback *ServiceCallback;
-	void                *ServiceContext;
-	mDNSBool             Conflict;	// Set if this record set was forcibly deregistered because of a conflict
-
-	ExtraResourceRecord *Extras;	// Optional list of extra AuthRecords attached to this service registration
-	mDNSu32              NumSubTypes;
-	AuthRecord          *SubTypes;
-	AuthRecord           RR_ADV;	// e.g. _services._dns-sd._udp.local. PTR _printer._tcp.local.
-	AuthRecord           RR_PTR;	// e.g. _printer._tcp.local.        PTR Name._printer._tcp.local.
-	AuthRecord           RR_SRV;	// e.g. Name._printer._tcp.local.   SRV 0 0 port target
-	AuthRecord           RR_TXT;	// e.g. Name._printer._tcp.local.   TXT PrintQueueName
-	// Don't add any fields after AuthRecord RR_TXT.
-	// This is where the implicit extra space goes if we allocate a ServiceRecordSet containing an oversized RR_TXT record
-	};
-
-// ***************************************************************************
-#if 0
-#pragma mark -
-#pragma mark - Question structures
-#endif
-
-// We record the last eight instances of each duplicate query
-// This gives us v4/v6 on each of Ethernet, AirPort and Firewire, and two free slots "for future expansion"
-// If the host has more active interfaces that this it is not fatal -- duplicate question suppression will degrade gracefully.
-// Since we will still remember the last eight, the busiest interfaces will still get the effective duplicate question suppression.
-#define DupSuppressInfoSize 8
-
-typedef struct
-	{
-	mDNSs32               Time;
-	mDNSInterfaceID       InterfaceID;
-	mDNSs32               Type;				// v4 or v6?
-	} DupSuppressInfo;
-
-typedef enum
-	{
-	LLQ_InitialRequest    = 1,
-	LLQ_SecondaryRequest  = 2,
-	LLQ_Established       = 3,
-	LLQ_Poll              = 4
-	} LLQ_State;
-
-// LLQ constants
-#define kLLQ_Vers      1
-#define kLLQ_DefLease  7200 // 2 hours
-#define kLLQ_MAX_TRIES 3    // retry an operation 3 times max
-#define kLLQ_INIT_RESEND 2 // resend an un-ack'd packet after 2 seconds, then double for each additional
-// LLQ Operation Codes
-#define kLLQOp_Setup     1
-#define kLLQOp_Refresh   2
-#define kLLQOp_Event     3
-
-// LLQ Errror Codes
-enum
-	{
-	LLQErr_NoError    = 0,
-	LLQErr_ServFull   = 1,
-	LLQErr_Static     = 2,
-	LLQErr_FormErr    = 3,
-	LLQErr_NoSuchLLQ  = 4,
-	LLQErr_BadVers    = 5,
-	LLQErr_UnknownErr = 6
-	};
-
-enum { NoAnswer_Normal = 0, NoAnswer_Suspended = 1, NoAnswer_Fail = 2 };
-
-#define HMAC_LEN    64
-#define HMAC_IPAD   0x36
-#define HMAC_OPAD   0x5c
-#define MD5_LEN     16
-
-#define AutoTunnelUnregistered(X) (                                              \
-	(X)->AutoTunnelHostRecord.resrec.RecordType == kDNSRecordTypeUnregistered && \
-	(X)->AutoTunnelDeviceInfo.resrec.RecordType == kDNSRecordTypeUnregistered && \
-	(X)->AutoTunnelService.   resrec.RecordType == kDNSRecordTypeUnregistered && \
-	(X)->AutoTunnel6Record.   resrec.RecordType == kDNSRecordTypeUnregistered    )
-
-// Internal data structure to maintain authentication information
-typedef struct DomainAuthInfo
-	{
-	struct DomainAuthInfo *next;
-	mDNSs32          deltime;				// If we're planning to delete this DomainAuthInfo, the time we want it deleted
-	const char*      AutoTunnel;            // If NULL, this is not an AutoTunnel DAI. Otherwise, this is prepended to the IPSec identifier
-	AuthRecord       AutoTunnelHostRecord;	// User-visible hostname; used as SRV target for AutoTunnel services
-	AuthRecord       AutoTunnelTarget;		// Opaque hostname of tunnel endpoint; used as SRV target for AutoTunnelService record
-	AuthRecord       AutoTunnelDeviceInfo;	// Device info of tunnel endpoint
-	AuthRecord       AutoTunnelService;		// Service record (possibly NAT-Mapped) of IKE daemon implementing tunnel endpoint
-	AuthRecord       AutoTunnel6Record;     // AutoTunnel AAAA Record obtained from Connectivityd
-	NATTraversalInfo AutoTunnelNAT;
-	domainname       domain;
-	domainname       keyname;
-	domainname       hostname;
-	mDNSIPPort       port;
-	char             b64keydata[32];
-	mDNSu8           keydata_ipad[HMAC_LEN];	// padded key for inner hash rounds
-	mDNSu8           keydata_opad[HMAC_LEN];	// padded key for outer hash rounds
-	} DomainAuthInfo;
-
-// Note: Within an mDNSQuestionCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
-typedef enum { QC_rmv = 0, QC_add = 1, QC_addnocache = 2 } QC_result;
-typedef void mDNSQuestionCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord);
-
-#define NextQSendTime(Q)  ((Q)->LastQTime + (Q)->ThisQInterval)
-#define ActiveQuestion(Q) ((Q)->ThisQInterval > 0 && !(Q)->DuplicateOf)
-#define TimeToSendThisQuestion(Q,time) (ActiveQuestion(Q) && (time) - NextQSendTime(Q) >= 0)
-
-struct DNSQuestion_struct
-	{
-	// Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
-	DNSQuestion          *next;
-	mDNSu32               qnamehash;
-	mDNSs32               DelayAnswering;	// Set if we want to defer answering this question until the cache settles
-	mDNSs32               LastQTime;		// Last scheduled transmission of this Q on *all* applicable interfaces
-	mDNSs32               ThisQInterval;	// LastQTime + ThisQInterval is the next scheduled transmission of this Q
-											// ThisQInterval > 0 for an active question;
-											// ThisQInterval = 0 for a suspended question that's still in the list
-											// ThisQInterval = -1 for a cancelled question (should not still be in list)
-	mDNSs32               ExpectUnicastResp;// Set when we send a query with the kDNSQClass_UnicastResponse bit set
-	mDNSs32               LastAnswerPktNum;	// The sequence number of the last response packet containing an answer to this Q
-	mDNSu32               RecentAnswerPkts;	// Number of answers since the last time we sent this query
-	mDNSu32               CurrentAnswers;	// Number of records currently in the cache that answer this question
-	mDNSu32               LargeAnswers;		// Number of answers with rdata > 1024 bytes
-	mDNSu32               UniqueAnswers;	// Number of answers received with kDNSClass_UniqueRRSet bit set
-	mDNSInterfaceID       FlappingInterface1;// Set when an interface goes away, to flag if remove events are delivered for this Q
-	mDNSInterfaceID       FlappingInterface2;// Set when an interface goes away, to flag if remove events are delivered for this Q
-	DomainAuthInfo       *AuthInfo;			// Non-NULL if query is currently being done using Private DNS
-	DNSQuestion          *DuplicateOf;
-	DNSQuestion          *NextInDQList;
-	DupSuppressInfo       DupSuppress[DupSuppressInfoSize];
-	mDNSInterfaceID       SendQNow;			// The interface this query is being sent on right now
-	mDNSBool              SendOnAll;		// Set if we're sending this question on all active interfaces
-	mDNSu32               RequestUnicast;	// Non-zero if we want to send query with kDNSQClass_UnicastResponse bit set
-	mDNSs32               LastQTxTime;		// Last time this Q was sent on one (but not necessarily all) interfaces
-	mDNSu32               CNAMEReferrals;	// Count of how many CNAME redirections we've done
-	mDNSBool              SuppressQuery;    // This query should be suppressed and not sent on the wire 
-	mDNSu8                LOAddressAnswers; // Number of answers from the local only auth records that are
-		                                    // answering A, AAAA and CNAME (/etc/hosts)
-	mDNSu8                WakeOnResolveCount; // Number of wakes that should be sent on resolve
-	mDNSs32               StopTime;			// Time this question should be stopped by giving them a negative answer
-
-	// Wide Area fields. These are used internally by the uDNS core
-	UDPSocket            *LocalSocket;
-	mDNSBool             deliverAddEvents;  // Change in DNSSserver requiring to deliver ADD events
-	DNSServer            *qDNSServer;		// Caching server for this query (in the absence of an SRV saying otherwise)
-	mDNSOpaque64          validDNSServers;  // Valid DNSServers for this question
-	mDNSu16              noServerResponse;  // At least one server did not respond.
-	mDNSu16              triedAllServersOnce; // Tried all DNS servers once
-	mDNSu8               unansweredQueries;// The number of unanswered queries to this server
-
-	ZoneData             *nta;				// Used for getting zone data for private or LLQ query
-	mDNSAddr              servAddr;			// Address and port learned from _dns-llq, _dns-llq-tls or _dns-query-tls SRV query
-	mDNSIPPort            servPort;
-	struct tcpInfo_t *tcp;
-	mDNSIPPort            tcpSrcPort;		// Local Port TCP packet received on;need this as tcp struct is disposed
-											// by tcpCallback before calling into mDNSCoreReceive
-	mDNSu8                NoAnswer;			// Set if we want to suppress answers until tunnel setup has completed
-
-	// LLQ-specific fields. These fields are only meaningful when LongLived flag is set
-	LLQ_State             state;
-	mDNSu32               ReqLease;			// seconds (relative)
-	mDNSs32               expire;			// ticks (absolute)
-	mDNSs16               ntries;           // for UDP: the number of packets sent for this LLQ state
-	                                       // for TCP: there is some ambiguity in the use of this variable, but in general, it is
-	                                       //          the number of TCP/TLS connection attempts for this LLQ state, or
-	                                       //          the number of packets sent for this TCP/TLS connection
-	mDNSOpaque64          id;
-
-	// Client API fields: The client must set up these fields *before* calling mDNS_StartQuery()
-	mDNSInterfaceID       InterfaceID;		// Non-zero if you want to issue queries only on a single specific IP interface
-	mDNSAddr              Target;			// Non-zero if you want to direct queries to a specific unicast target address
-	mDNSIPPort            TargetPort;		// Must be set if Target is set
-	mDNSOpaque16          TargetQID;		// Must be set if Target is set
-	domainname            qname;
-	mDNSu16               qtype;
-	mDNSu16               qclass;
-	mDNSBool              LongLived;        // Set by client for calls to mDNS_StartQuery to indicate LLQs to unicast layer.
-	mDNSBool              ExpectUnique;		// Set by client if it's expecting unique RR(s) for this question, not shared RRs
-	mDNSBool              ForceMCast;		// Set by client to force mDNS query, even for apparently uDNS names
-	mDNSBool              ReturnIntermed;	// Set by client to request callbacks for intermediate CNAME/NXDOMAIN results
-	mDNSBool              SuppressUnusable; // Set by client to suppress unusable queries to be sent on the wire
-	mDNSBool              RetryWithSearchDomains;	// Retry with search domains if there is no entry in the cache or AuthRecords
-	mDNSu8                TimeoutQuestion; // Timeout this question if there is no reply in configured time
-	mDNSu8                WakeOnResolve; // Send wakeup on resolve
-	mDNSs8                SearchListIndex;  // Index into SearchList; Used by the client layer but not touched by core
-	mDNSs8                AppendSearchDomains; // Search domains can be appended for this query
-	mDNSs8                AppendLocalSearchDomains; // Search domains ending in .local can be appended for this query
-	domainname           *qnameOrig;       // Copy of the original question name if it is not fully qualified
-	mDNSQuestionCallback *QuestionCallback;
-	void                 *QuestionContext;
-	};
-
-typedef struct
-	{
-	// Client API fields: The client must set up name and InterfaceID *before* calling mDNS_StartResolveService()
-	// When the callback is invoked, ip, port, TXTlen and TXTinfo will have been filled in with the results learned from the network.
-	domainname      name;
-	mDNSInterfaceID InterfaceID;		// ID of the interface the response was received on
-	mDNSAddr        ip;					// Remote (destination) IP address where this service can be accessed
-	mDNSIPPort      port;				// Port where this service can be accessed
-	mDNSu16         TXTlen;
-	mDNSu8          TXTinfo[2048];		// Additional demultiplexing information (e.g. LPR queue name)
-	} ServiceInfo;
-
-// Note: Within an mDNSServiceInfoQueryCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Exit(), mDNS_Execute()
-typedef struct ServiceInfoQuery_struct ServiceInfoQuery;
-typedef void mDNSServiceInfoQueryCallback(mDNS *const m, ServiceInfoQuery *query);
-struct ServiceInfoQuery_struct
-	{
-	// Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
-	// No fields need to be set up by the client prior to calling mDNS_StartResolveService();
-	// all required data is passed as parameters to that function.
-	// The ServiceInfoQuery structure memory is working storage for mDNSCore to discover the requested information
-	// and place it in the ServiceInfo structure. After the client has called mDNS_StopResolveService(), it may
-	// dispose of the ServiceInfoQuery structure while retaining the results in the ServiceInfo structure.
-	DNSQuestion                   qSRV;
-	DNSQuestion                   qTXT;
-	DNSQuestion                   qAv4;
-	DNSQuestion                   qAv6;
-	mDNSu8                        GotSRV;
-	mDNSu8                        GotTXT;
-	mDNSu8                        GotADD;
-	mDNSu32                       Answers;
-	ServiceInfo                  *info;
-	mDNSServiceInfoQueryCallback *ServiceInfoQueryCallback;
-	void                         *ServiceInfoQueryContext;
-	};
-
-typedef enum { ZoneServiceUpdate, ZoneServiceQuery, ZoneServiceLLQ } ZoneService;
-
-typedef void ZoneDataCallback(mDNS *const m, mStatus err, const ZoneData *result);
-
-struct ZoneData_struct
-	{
-	domainname       ChildName;			// Name for which we're trying to find the responsible server
-	ZoneService      ZoneService;		// Which service we're seeking for this zone (update, query, or LLQ)
-	domainname       *CurrentSOA;		// Points to somewhere within ChildName
-	domainname       ZoneName;			// Discovered result: Left-hand-side of SOA record
-	mDNSu16          ZoneClass;			// Discovered result: DNS Class from SOA record
-	domainname       Host;				// Discovered result: Target host from SRV record
-	mDNSIPPort       Port;				// Discovered result: Update port, query port, or LLQ port from SRV record
-	mDNSAddr         Addr;				// Discovered result: Address of Target host from SRV record
-	mDNSBool         ZonePrivate;		// Discovered result: Does zone require encrypted queries?
-	ZoneDataCallback *ZoneDataCallback;	// Caller-specified function to be called upon completion
-	void             *ZoneDataContext;
-	DNSQuestion      question;			// Storage for any active question
-	};
-
-extern ZoneData *StartGetZoneData(mDNS *const m, const domainname *const name, const ZoneService target, ZoneDataCallback callback, void *callbackInfo);
-extern void CancelGetZoneData(mDNS *const m, ZoneData *nta);
-extern mDNSBool IsGetZoneDataQuestion(DNSQuestion *q);
-
-typedef struct DNameListElem
-	{
-	struct DNameListElem *next;
-	mDNSu32 uid;
-	domainname name;
-	} DNameListElem;
-
-#if APPLE_OSX_mDNSResponder
-// Different states that we go through locating the peer
-#define TC_STATE_AAAA_PEER			0x000000001		/* Peer's BTMM IPv6 address */
-#define TC_STATE_AAAA_PEER_RELAY	0x000000002		/* Peer's IPv6 Relay address */
-#define TC_STATE_SRV_PEER			0x000000003		/* Peer's SRV Record corresponding to IPv4 address */
-#define TC_STATE_ADDR_PEER			0x000000004		/* Peer's IPv4 address */
-
-typedef struct ClientTunnel
-	{
-	struct ClientTunnel *next;
-	const char *prefix;
-	domainname dstname;
-	mDNSBool   MarkedForDeletion;
-	mDNSv6Addr loc_inner;
-	mDNSv4Addr loc_outer;
-	mDNSv6Addr loc_outer6;
-	mDNSv6Addr rmt_inner;
-	mDNSv4Addr rmt_outer;
-	mDNSv6Addr rmt_outer6;
-	mDNSIPPort rmt_outer_port;
-	mDNSu16	tc_state;
-	DNSQuestion q;
-	} ClientTunnel;
-#endif
-
-// ***************************************************************************
-#if 0
-#pragma mark -
-#pragma mark - NetworkInterfaceInfo_struct
-#endif
-
-typedef struct NetworkInterfaceInfo_struct NetworkInterfaceInfo;
-
-// A NetworkInterfaceInfo_struct serves two purposes:
-// 1. It holds the address, PTR and HINFO records to advertise a given IP address on a given physical interface
-// 2. It tells mDNSCore which physical interfaces are available; each physical interface has its own unique InterfaceID.
-//    Since there may be multiple IP addresses on a single physical interface,
-//    there may be multiple NetworkInterfaceInfo_structs with the same InterfaceID.
-//    In this case, to avoid sending the same packet n times, when there's more than one
-//    struct with the same InterfaceID, mDNSCore picks one member of the set to be the
-//    active representative of the set; all others have the 'InterfaceActive' flag unset.
-
-struct NetworkInterfaceInfo_struct
-	{
-	// Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them.
-	NetworkInterfaceInfo *next;
-
-	mDNSu8          InterfaceActive;	// Set if interface is sending & receiving packets (see comment above)
-	mDNSu8          IPv4Available;		// If InterfaceActive, set if v4 available on this InterfaceID
-	mDNSu8          IPv6Available;		// If InterfaceActive, set if v6 available on this InterfaceID
-
-	DNSQuestion     NetWakeBrowse;
-	DNSQuestion     NetWakeResolve[3];	// For fault-tolerance, we try up to three Sleep Proxies
-	mDNSAddr        SPSAddr[3];
-	mDNSIPPort      SPSPort[3];
-	mDNSs32         NextSPSAttempt;		// -1 if we're not currently attempting to register with any Sleep Proxy
-	mDNSs32         NextSPSAttemptTime;
-
-	// Standard AuthRecords that every Responder host should have (one per active IP address)
-	AuthRecord RR_A;					// 'A' or 'AAAA' (address) record for our ".local" name
-	AuthRecord RR_PTR;					// PTR (reverse lookup) record
-	AuthRecord RR_HINFO;
-
-	// Client API fields: The client must set up these fields *before* calling mDNS_RegisterInterface()
-	mDNSInterfaceID InterfaceID;		// Identifies physical interface; MUST NOT be 0, -1, or -2
-	mDNSAddr        ip;					// The IPv4 or IPv6 address to advertise
-	mDNSAddr        mask;
-	mDNSEthAddr     MAC;
-	char            ifname[64];			// Windows uses a GUID string for the interface name, which doesn't fit in 16 bytes
-	mDNSu8          Advertise;			// False if you are only searching on this interface
-	mDNSu8          McastTxRx;			// Send/Receive multicast on this { InterfaceID, address family } ?
-	mDNSu8          NetWake;			// Set if Wake-On-Magic-Packet is enabled on this interface
-	mDNSu8          Loopback;			// Set if this is the loopback interface
-	};
-
-#define SLE_DELETE              0x00000001
-#define SLE_WAB_QUERY_STARTED   0x00000002
-
-typedef struct SearchListElem
-	{
-	struct SearchListElem *next;
-	domainname domain;
-	int flag;
-	mDNSInterfaceID InterfaceID;
-	DNSQuestion BrowseQ;
-	DNSQuestion DefBrowseQ;
-	DNSQuestion AutomaticBrowseQ;
-	DNSQuestion RegisterQ;
-	DNSQuestion DefRegisterQ;
-	int	numCfAnswers;
-	ARListElem *AuthRecs;
-	} SearchListElem;
-
-// For domain enumeration and automatic browsing
-// This is the user's DNS search list.
-// In each of these domains we search for our special pointer records (lb._dns-sd._udp.<domain>, etc.)
-// to discover recommended domains for domain enumeration (browse, default browse, registration,
-// default registration) and possibly one or more recommended automatic browsing domains.
-extern SearchListElem *SearchList;		// This really ought to be part of mDNS_struct -- SC
-
-// ***************************************************************************
-#if 0
-#pragma mark -
-#pragma mark - Main mDNS object, used to hold all the mDNS state
-#endif
-
-typedef void mDNSCallback(mDNS *const m, mStatus result);
-
-#define CACHE_HASH_SLOTS 499
-
-enum		// Bit flags -- i.e. values should be 1, 2, 4, 8, etc.
-	{
-	mDNS_KnownBug_LimitedIPv6       = 1,
-	mDNS_KnownBug_LossySyslog       = 2		// <rdar://problem/6561888>
-	};
-
-enum
-	{
-	SleepState_Awake = 0,
-	SleepState_Transferring = 1,
-	SleepState_Sleeping = 2
-	};
-
-struct mDNS_struct
-	{
-	// Internal state fields. These hold the main internal state of mDNSCore;
-	// the client layer needn't be concerned with them.
-	// No fields need to be set up by the client prior to calling mDNS_Init();
-	// all required data is passed as parameters to that function.
-
-	mDNS_PlatformSupport *p;			// Pointer to platform-specific data of indeterminite size
-	mDNSu32  KnownBugs;
-	mDNSBool CanReceiveUnicastOn5353;
-	mDNSBool AdvertiseLocalAddresses;
-	mDNSBool DivertMulticastAdvertisements; // from interfaces that do not advertise local addresses to local-only
-	mStatus mDNSPlatformStatus;
-	mDNSIPPort UnicastPort4;
-	mDNSIPPort UnicastPort6;
-	mDNSEthAddr PrimaryMAC;				// Used as unique host ID
-	mDNSCallback *MainCallback;
-	void         *MainContext;
-
-	// For debugging: To catch and report locking failures
-	mDNSu32 mDNS_busy;					// Incremented between mDNS_Lock/mDNS_Unlock section
-	mDNSu32 mDNS_reentrancy;			// Incremented when calling a client callback
-	mDNSu8  lock_rrcache;				// For debugging: Set at times when these lists may not be modified
-	mDNSu8  lock_Questions;
-	mDNSu8  lock_Records;
-#ifndef MaxMsg
-	#define MaxMsg 160
-#endif
-	char MsgBuffer[MaxMsg];				// Temp storage used while building error log messages
-
-	// Task Scheduling variables
-	mDNSs32  timenow_adjust;			// Correction applied if we ever discover time went backwards
-	mDNSs32  timenow;					// The time that this particular activation of the mDNS code started
-	mDNSs32  timenow_last;				// The time the last time we ran
-	mDNSs32  NextScheduledEvent;		// Derived from values below
-	mDNSs32  ShutdownTime;				// Set when we're shutting down; allows us to skip some unnecessary steps
-	mDNSs32  SuppressSending;			// Don't send local-link mDNS packets during this time
-	mDNSs32  NextCacheCheck;			// Next time to refresh cache record before it expires
-	mDNSs32  NextScheduledQuery;		// Next time to send query in its exponential backoff sequence
-	mDNSs32  NextScheduledProbe;		// Next time to probe for new authoritative record
-	mDNSs32  NextScheduledResponse;		// Next time to send authoritative record(s) in responses
-	mDNSs32  NextScheduledNATOp;		// Next time to send NAT-traversal packets
-	mDNSs32  NextScheduledSPS;			// Next time to purge expiring Sleep Proxy records
-	mDNSs32  RandomQueryDelay;			// For de-synchronization of query packets on the wire
-	mDNSu32  RandomReconfirmDelay;		// For de-synchronization of reconfirmation queries on the wire
-	mDNSs32  PktNum;					// Unique sequence number assigned to each received packet
-	mDNSu8   LocalRemoveEvents;			// Set if we may need to deliver remove events for local-only questions and/or local-only records
-	mDNSu8   SleepState;				// Set if we're sleeping
-	mDNSu8   SleepSeqNum;				// "Epoch number" of our current period of wakefulness
-	mDNSu8   SystemWakeOnLANEnabled;	// Set if we want to register with a Sleep Proxy before going to sleep
-	mDNSu8   SentSleepProxyRegistration;// Set if we registered (or tried to register) with a Sleep Proxy
-	mDNSu8   SystemSleepOnlyIfWakeOnLAN;// Set if we may only sleep if we managed to register with a Sleep Proxy
-	mDNSs32  AnnounceOwner;				// After waking from sleep, include OWNER option in packets until this time
-	mDNSs32  DelaySleep;				// To inhibit re-sleeping too quickly right after wake
-	mDNSs32  SleepLimit;				// Time window to allow deregistrations, etc.,
-										// during which underying platform layer should inhibit system sleep
-	mDNSs32  NextScheduledSPRetry;		// Time next sleep proxy registration action is required.
-										// Only valid if SleepLimit is nonzero and DelaySleep is zero.
-
-	mDNSs32 NextScheduledStopTime;      // Next time to stop a question
-
-	// These fields only required for mDNS Searcher...
-	DNSQuestion *Questions;				// List of all registered questions, active and inactive
-	DNSQuestion *NewQuestions;			// Fresh questions not yet answered from cache
-	DNSQuestion *CurrentQuestion;		// Next question about to be examined in AnswerLocalQuestions()
-	DNSQuestion *LocalOnlyQuestions;	// Questions with InterfaceID set to mDNSInterface_LocalOnly or mDNSInterface_P2P
-	DNSQuestion *NewLocalOnlyQuestions;	// Fresh local-only or P2P questions not yet answered
-	DNSQuestion *RestartQuestion;		// Questions that are being restarted (stop followed by start)
-	mDNSu32 rrcache_size;				// Total number of available cache entries
-	mDNSu32 rrcache_totalused;			// Number of cache entries currently occupied
-	mDNSu32 rrcache_active;				// Number of cache entries currently occupied by records that answer active questions
-	mDNSu32 rrcache_report;
-	CacheEntity *rrcache_free;
-	CacheGroup *rrcache_hash[CACHE_HASH_SLOTS];
-	mDNSs32  rrcache_nextcheck[CACHE_HASH_SLOTS];
-
-	AuthHash rrauth;
-
-	// Fields below only required for mDNS Responder...
-	domainlabel nicelabel;				// Rich text label encoded using canonically precomposed UTF-8
-	domainlabel hostlabel;				// Conforms to RFC 1034 "letter-digit-hyphen" ARPANET host name rules
-	domainname  MulticastHostname;		// Fully Qualified "dot-local" Host Name, e.g. "Foo.local."
-	UTF8str255  HIHardware;
-	UTF8str255  HISoftware;
-	AuthRecord  DeviceInfo;
-	AuthRecord *ResourceRecords;
-	AuthRecord *DuplicateRecords;		// Records currently 'on hold' because they are duplicates of existing records
-	AuthRecord *NewLocalRecords;		// Fresh AuthRecords (public) not yet delivered to our local-only questions
-	AuthRecord *CurrentRecord;			// Next AuthRecord about to be examined
-	mDNSBool    NewLocalOnlyRecords;	// Fresh AuthRecords (local only) not yet delivered to our local questions
-	NetworkInterfaceInfo *HostInterfaces;
-	mDNSs32 ProbeFailTime;
-	mDNSu32 NumFailedProbes;
-	mDNSs32 SuppressProbes;
-
-	// Unicast-specific data
-	mDNSs32           NextuDNSEvent;		// uDNS next event
-	mDNSs32           NextSRVUpdate;        // Time to perform delayed update
-
-	DNSServer        *DNSServers;           // list of DNS servers
-	McastResolver    *McastResolvers;       // list of Mcast Resolvers
-
-	mDNSAddr          Router;
-	mDNSAddr          AdvertisedV4;         // IPv4 address pointed to by hostname
-	mDNSAddr          AdvertisedV6;         // IPv6 address pointed to by hostname
-
-	DomainAuthInfo   *AuthInfoList;         // list of domains requiring authentication for updates
-
-	DNSQuestion       ReverseMap;           // Reverse-map query to find static hostname for service target
-	DNSQuestion       AutomaticBrowseDomainQ;
-	domainname        StaticHostname;       // Current answer to reverse-map query
-	domainname        FQDN;
-	HostnameInfo     *Hostnames;            // List of registered hostnames + hostname metadata
-	mDNSv6Addr        AutoTunnelHostAddr;	// IPv6 address advertised for AutoTunnel services on this machine
-	mDNSBool          AutoTunnelHostAddrActive;
-	// AutoTunnel Relay address has two distinct uses
-	// AutoTunnelRelayAddrIn: If non-zero, it means that this host can be reached (inbound connection) through the relay
-	// AutoTunnelRelayAddrOut: If non-zero, it means that this host can use the relay to reach (outbound connection) the
-	// other hosts through the relay
-	mDNSv6Addr        AutoTunnelRelayAddrIn;
-	mDNSv6Addr        AutoTunnelRelayAddrOut;
-	domainlabel       AutoTunnelLabel;		// Used to construct hostname for *IPv4* address of tunnel endpoints
-
-	mDNSBool          StartWABQueries;		// Start WAB queries for the purpose of domain enumeration
-	mDNSBool          RegisterAutoTunnel6;
-
-	// NAT-Traversal fields
-	NATTraversalInfo  LLQNAT;					// Single shared NAT Traversal to receive inbound LLQ notifications
-	NATTraversalInfo *NATTraversals;
-	NATTraversalInfo *CurrentNATTraversal;
-	mDNSs32           retryIntervalGetAddr;		// delta between time sent and retry
-	mDNSs32           retryGetAddr;				// absolute time when we retry
-	mDNSv4Addr        ExternalAddress;
-
-	UDPSocket        *NATMcastRecvskt;			// For receiving NAT-PMP AddrReply multicasts from router on port 5350
-	mDNSu32           LastNATupseconds;			// NAT engine uptime in seconds, from most recent NAT packet
-	mDNSs32           LastNATReplyLocalTime;	// Local time in ticks when most recent NAT packet was received
-	mDNSu16           LastNATMapResultCode;		// Most recent error code for mappings
-
-	tcpLNTInfo        tcpAddrInfo;				// legacy NAT traversal TCP connection info for external address
-	tcpLNTInfo        tcpDeviceInfo;			// legacy NAT traversal TCP connection info for device info
-	tcpLNTInfo       *tcpInfoUnmapList;			// list of pending unmap requests
-	mDNSInterfaceID   UPnPInterfaceID;
-	UDPSocket        *SSDPSocket;               // For SSDP request/response
-	mDNSBool          SSDPWANPPPConnection;     // whether we should send the SSDP query for WANIPConnection or WANPPPConnection
-	mDNSIPPort        UPnPRouterPort;			// port we send discovery messages to
-	mDNSIPPort        UPnPSOAPPort;				// port we send SOAP messages to
-	mDNSu8           *UPnPRouterURL;			// router's URL string
-	mDNSBool          UPnPWANPPPConnection;     // whether we're using WANIPConnection or WANPPPConnection
-	mDNSu8           *UPnPSOAPURL;				// router's SOAP control URL string
-	mDNSu8           *UPnPRouterAddressString;	// holds both the router's address and port
-	mDNSu8           *UPnPSOAPAddressString;	// holds both address and port for SOAP messages
-
-	// Sleep Proxy Server fields
-	mDNSu8            SPSType;					// 0 = off, 10-99 encodes desirability metric
-	mDNSu8            SPSPortability;			// 10-99
-	mDNSu8            SPSMarginalPower;			// 10-99
-	mDNSu8            SPSTotalPower;			// 10-99
-	mDNSu8            SPSState;					// 0 = off, 1 = running, 2 = shutting down, 3 = suspended during sleep
-	mDNSInterfaceID   SPSProxyListChanged;
-	UDPSocket        *SPSSocket;
-	ServiceRecordSet  SPSRecords;
-	mDNSQuestionCallback *SPSBrowseCallback;    // So the platform layer can do something useful with SPS browse results
-	int               ProxyRecords;				// Total number of records we're holding as proxy
-	#define           MAX_PROXY_RECORDS 10000	/* DOS protection: 400 machines at 25 records each */
-
-#if APPLE_OSX_mDNSResponder
-	ClientTunnel     *TunnelClients;
-	uuid_t           asl_uuid;					// uuid for ASL logging
-	void		    *WCF;
-#endif
-
-	// Fixed storage, to avoid creating large objects on the stack
-	// The imsg is declared as a union with a pointer type to enforce CPU-appropriate alignment
-	union { DNSMessage m; void *p; } imsg;  // Incoming message received from wire
-	DNSMessage        omsg;                 // Outgoing message we're building
-	LargeCacheRecord  rec;                  // Resource Record extracted from received message
-	};
-
-#define FORALL_CACHERECORDS(SLOT,CG,CR)                           \
-	for ((SLOT) = 0; (SLOT) < CACHE_HASH_SLOTS; (SLOT)++)         \
-		for ((CG)=m->rrcache_hash[(SLOT)]; (CG); (CG)=(CG)->next) \
-			for ((CR) = (CG)->members; (CR); (CR)=(CR)->next)
-
-// ***************************************************************************
-#if 0
-#pragma mark -
-#pragma mark - Useful Static Constants
-#endif
-
-extern const mDNSInterfaceID mDNSInterface_Any;				// Zero
-extern const mDNSInterfaceID mDNSInterface_LocalOnly;		// Special value
-extern const mDNSInterfaceID mDNSInterface_Unicast;			// Special value
-extern const mDNSInterfaceID mDNSInterfaceMark;				// Special value
-extern const mDNSInterfaceID mDNSInterface_P2P;				// Special value
-
-extern const mDNSIPPort   DiscardPort;
-extern const mDNSIPPort   SSHPort;
-extern const mDNSIPPort   UnicastDNSPort;
-extern const mDNSIPPort   SSDPPort;
-extern const mDNSIPPort   IPSECPort;
-extern const mDNSIPPort   NSIPCPort;
-extern const mDNSIPPort   NATPMPAnnouncementPort;
-extern const mDNSIPPort   NATPMPPort;
-extern const mDNSIPPort   DNSEXTPort;
-extern const mDNSIPPort   MulticastDNSPort;
-extern const mDNSIPPort   LoopbackIPCPort;
-extern const mDNSIPPort   PrivateDNSPort;
-
-extern const OwnerOptData    zeroOwner;
-
-extern const mDNSIPPort      zeroIPPort;
-extern const mDNSv4Addr      zerov4Addr;
-extern const mDNSv6Addr      zerov6Addr;
-extern const mDNSEthAddr     zeroEthAddr;
-extern const mDNSv4Addr      onesIPv4Addr;
-extern const mDNSv6Addr      onesIPv6Addr;
-extern const mDNSEthAddr     onesEthAddr;
-//extern const mDNSAddr        zeroAddr;
-
-extern const mDNSv4Addr   AllDNSAdminGroup;
-extern const mDNSv4Addr   AllHosts_v4;
-extern const mDNSv6Addr   AllHosts_v6;
-extern const mDNSv6Addr   NDP_prefix;
-extern const mDNSEthAddr  AllHosts_v6_Eth;
-extern const mDNSAddr     AllDNSLinkGroup_v4;
-extern const mDNSAddr     AllDNSLinkGroup_v6;
-
-extern const mDNSOpaque16 zeroID;
-extern const mDNSOpaque16 onesID;
-extern const mDNSOpaque16 QueryFlags;
-extern const mDNSOpaque16 uQueryFlags;
-extern const mDNSOpaque16 ResponseFlags;
-extern const mDNSOpaque16 UpdateReqFlags;
-extern const mDNSOpaque16 UpdateRespFlags;
-
-extern const mDNSOpaque64 zeroOpaque64;
-
-extern mDNSBool StrictUnicastOrdering;
-extern mDNSu8 NumUnicastDNSServers;
-
-#define localdomain           (*(const domainname *)"\x5" "local")
-#define DeviceInfoName        (*(const domainname *)"\xC" "_device-info" "\x4" "_tcp")
-#define SleepProxyServiceType (*(const domainname *)"\xC" "_sleep-proxy" "\x4" "_udp")
-
-// ***************************************************************************
-#if 0
-#pragma mark -
-#pragma mark - Inline functions
-#endif
-
-#if (defined(_MSC_VER))
-	#define mDNSinline static __inline
-#elif ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9)))
-	#define mDNSinline static inline
-#endif
-
-// If we're not doing inline functions, then this header needs to have the extern declarations
-#if !defined(mDNSinline)
-extern mDNSs32      NonZeroTime(mDNSs32 t);
-extern mDNSu16      mDNSVal16(mDNSOpaque16 x);
-extern mDNSOpaque16 mDNSOpaque16fromIntVal(mDNSu16 v);
-#endif
-
-// If we're compiling the particular C file that instantiates our inlines, then we
-// define "mDNSinline" (to empty string) so that we generate code in the following section
-#if (!defined(mDNSinline) && mDNS_InstantiateInlines)
-#define mDNSinline
-#endif
-
-#ifdef mDNSinline
-
-mDNSinline mDNSs32 NonZeroTime(mDNSs32 t) { if (t) return(t); else return(1); }
-
-mDNSinline mDNSu16 mDNSVal16(mDNSOpaque16 x) { return((mDNSu16)((mDNSu16)x.b[0] <<  8 | (mDNSu16)x.b[1])); }
-
-mDNSinline mDNSOpaque16 mDNSOpaque16fromIntVal(mDNSu16 v)
-	{
-	mDNSOpaque16 x;
-	x.b[0] = (mDNSu8)(v >> 8);
-	x.b[1] = (mDNSu8)(v & 0xFF);
-	return(x);
-	}
-
-#endif
-
-// ***************************************************************************
-#if 0
-#pragma mark -
-#pragma mark - Main Client Functions
-#endif
-
-// Every client should call mDNS_Init, passing in storage for the mDNS object and the mDNS_PlatformSupport object.
-//
-// Clients that are only advertising services should use mDNS_Init_NoCache and mDNS_Init_ZeroCacheSize.
-// Clients that plan to perform queries (mDNS_StartQuery, mDNS_StartBrowse, mDNS_StartResolveService, etc.)
-// need to provide storage for the resource record cache, or the query calls will return 'mStatus_NoCache'.
-// The rrcachestorage parameter is the address of memory for the resource record cache, and
-// the rrcachesize parameter is the number of entries in the CacheRecord array passed in.
-// (i.e. the size of the cache memory needs to be sizeof(CacheRecord) * rrcachesize).
-// OS X 10.3 Panther uses an initial cache size of 64 entries, and then mDNSCore sends an
-// mStatus_GrowCache message if it needs more.
-//
-// Most clients should use mDNS_Init_AdvertiseLocalAddresses. This causes mDNSCore to automatically
-// create the correct address records for all the hosts interfaces. If you plan to advertise
-// services being offered by the local machine, this is almost always what you want.
-// There are two cases where you might use mDNS_Init_DontAdvertiseLocalAddresses:
-// 1. A client-only device, that browses for services but doesn't advertise any of its own.
-// 2. A proxy-registration service, that advertises services being offered by other machines, and takes
-//    the appropriate steps to manually create the correct address records for those other machines.
-// In principle, a proxy-like registration service could manually create address records for its own machine too,
-// but this would be pointless extra effort when using mDNS_Init_AdvertiseLocalAddresses does that for you.
-//
-// Note that a client-only device that wishes to prohibit multicast advertisements (e.g. from
-// higher-layer API calls) must also set DivertMulticastAdvertisements in the mDNS structure and
-// advertise local address(es) on a loopback interface.
-//
-// When mDNS has finished setting up the client's callback is called
-// A client can also spin and poll the mDNSPlatformStatus field to see when it changes from mStatus_Waiting to mStatus_NoError
-//
-// Call mDNS_StartExit to tidy up before exiting
-// Because exiting may be an asynchronous process (e.g. if unicast records need to be deregistered)
-// client layer may choose to wait until mDNS_ExitNow() returns true before calling mDNS_FinalExit().
-//
-// Call mDNS_Register with a completed AuthRecord object to register a resource record
-// If the resource record type is kDNSRecordTypeUnique (or kDNSknownunique) then if a conflicting resource record is discovered,
-// the resource record's mDNSRecordCallback will be called with error code mStatus_NameConflict. The callback should deregister
-// the record, and may then try registering the record again after picking a new name (e.g. by automatically appending a number).
-// Following deregistration, the RecordCallback will be called with result mStatus_MemFree to signal that it is safe to deallocate
-// the record's storage (memory must be freed asynchronously to allow for goodbye packets and dynamic update deregistration).
-//
-// Call mDNS_StartQuery to initiate a query. mDNS will proceed to issue Multicast DNS query packets, and any time a response
-// is received containing a record which matches the question, the DNSQuestion's mDNSAnswerCallback function will be called
-// Call mDNS_StopQuery when no more answers are required
-//
-// Care should be taken on multi-threaded or interrupt-driven environments.
-// The main mDNS routines call mDNSPlatformLock() on entry and mDNSPlatformUnlock() on exit;
-// each platform layer needs to implement these appropriately for its respective platform.
-// For example, if the support code on a particular platform implements timer callbacks at interrupt time, then
-// mDNSPlatformLock/Unlock need to disable interrupts or do similar concurrency control to ensure that the mDNS
-// code is not entered by an interrupt-time timer callback while in the middle of processing a client call.
-
-extern mStatus mDNS_Init      (mDNS *const m, mDNS_PlatformSupport *const p,
-								CacheEntity *rrcachestorage, mDNSu32 rrcachesize,
-								mDNSBool AdvertiseLocalAddresses,
-								mDNSCallback *Callback, void *Context);
-// See notes above on use of NoCache/ZeroCacheSize
-#define mDNS_Init_NoCache                     mDNSNULL
-#define mDNS_Init_ZeroCacheSize               0
-// See notes above on use of Advertise/DontAdvertiseLocalAddresses
-#define mDNS_Init_AdvertiseLocalAddresses     mDNStrue
-#define mDNS_Init_DontAdvertiseLocalAddresses mDNSfalse
-#define mDNS_Init_NoInitCallback              mDNSNULL
-#define mDNS_Init_NoInitCallbackContext       mDNSNULL
-
-extern void    mDNS_ConfigChanged(mDNS *const m);
-extern void    mDNS_GrowCache (mDNS *const m, CacheEntity *storage, mDNSu32 numrecords);
-extern void    mDNS_GrowAuth (mDNS *const m, AuthEntity *storage, mDNSu32 numrecords);
-//extern void    mDNS_StartExit (mDNS *const m);
-//extern void    mDNS_FinalExit (mDNS *const m);
-//#define mDNS_Close(m) do { mDNS_StartExit(m); mDNS_FinalExit(m); } while(0)
-extern void mDNS_Close(mDNS *const m);
-#define mDNS_ExitNow(m, now) ((now) - (m)->ShutdownTime >= 0 || (!(m)->ResourceRecords))
-
-extern mDNSs32 mDNS_Execute   (mDNS *const m);
-
-extern mStatus mDNS_Register  (mDNS *const m, AuthRecord *const rr);
-extern mStatus mDNS_Update    (mDNS *const m, AuthRecord *const rr, mDNSu32 newttl,
-								const mDNSu16 newrdlength, RData *const newrdata, mDNSRecordUpdateCallback *Callback);
-extern mStatus mDNS_Deregister(mDNS *const m, AuthRecord *const rr);
-
-extern mStatus mDNS_StartQuery(mDNS *const m, DNSQuestion *const question);
-extern mStatus mDNS_StopQuery (mDNS *const m, DNSQuestion *const question);
-extern mStatus mDNS_StopQueryWithRemoves(mDNS *const m, DNSQuestion *const question);
-extern mStatus mDNS_Reconfirm (mDNS *const m, CacheRecord *const cacherr);
-extern mStatus mDNS_ReconfirmByValue(mDNS *const m, ResourceRecord *const rr);
-extern void    mDNS_PurgeCacheResourceRecord(mDNS *const m, CacheRecord *rr);
-extern mDNSs32 mDNS_TimeNow(const mDNS *const m);
-
-extern mStatus mDNS_StartNATOperation(mDNS *const m, NATTraversalInfo *traversal);
-extern mStatus mDNS_StopNATOperation(mDNS *const m, NATTraversalInfo *traversal);
-extern mStatus mDNS_StopNATOperation_internal(mDNS *m, NATTraversalInfo *traversal);
-
-extern DomainAuthInfo *GetAuthInfoForName(mDNS *m, const domainname *const name);
-
-extern void    mDNS_UpdateAllowSleep(mDNS *const m);
-
-// ***************************************************************************
-#if 0
-#pragma mark -
-#pragma mark - Platform support functions that are accessible to the client layer too
-#endif
-
-extern mDNSs32  mDNSPlatformOneSecond;
-
-// ***************************************************************************
-#if 0
-#pragma mark -
-#pragma mark - General utility and helper functions
-#endif
-
-// mDNS_Dereg_normal is used for most calls to mDNS_Deregister_internal
-// mDNS_Dereg_rapid is used to send one goodbye instead of three, when we want the memory available for reuse sooner
-// mDNS_Dereg_conflict is used to indicate that this record is being forcibly deregistered because of a conflict
-// mDNS_Dereg_repeat is used when cleaning up, for records that may have already been forcibly deregistered
-typedef enum { mDNS_Dereg_normal, mDNS_Dereg_rapid, mDNS_Dereg_conflict, mDNS_Dereg_repeat } mDNS_Dereg_type;
-
-// mDNS_RegisterService is a single call to register the set of resource records associated with a given named service.
-//
-// mDNS_StartResolveService is single call which is equivalent to multiple calls to mDNS_StartQuery,
-// to find the IP address, port number, and demultiplexing information for a given named service.
-// As with mDNS_StartQuery, it executes asynchronously, and calls the ServiceInfoQueryCallback when the answer is
-// found. After the service is resolved, the client should call mDNS_StopResolveService to complete the transaction.
-// The client can also call mDNS_StopResolveService at any time to abort the transaction.
-//
-// mDNS_AddRecordToService adds an additional record to a Service Record Set.  This record may be deregistered
-// via mDNS_RemoveRecordFromService, or by deregistering the service.  mDNS_RemoveRecordFromService is passed a
-// callback to free the memory associated with the extra RR when it is safe to do so.  The ExtraResourceRecord
-// object can be found in the record's context pointer.
-
-// mDNS_GetBrowseDomains is a special case of the mDNS_StartQuery call, where the resulting answers
-// are a list of PTR records indicating (in the rdata) domains that are recommended for browsing.
-// After getting the list of domains to browse, call mDNS_StopQuery to end the search.
-// mDNS_GetDefaultBrowseDomain returns the name of the domain that should be highlighted by default.
-//
-// mDNS_GetRegistrationDomains and mDNS_GetDefaultRegistrationDomain are the equivalent calls to get the list
-// of one or more domains that should be offered to the user as choices for where they may register their service,
-// and the default domain in which to register in the case where the user has made no selection.
-
-extern void    mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mDNSInterfaceID InterfaceID,
-               mDNSu16 rrtype, mDNSu32 ttl, mDNSu8 RecordType, AuthRecType artype, mDNSRecordCallback Callback, void *Context);
-
-// mDNS_RegisterService() flags parameter bit definitions
-enum
-	{
-		regFlagIncludeP2P	= 0x1,	// include P2P interfaces when using mDNSInterface_Any
-		regFlagKnownUnique	= 0x2	// client guarantees that SRV and TXT record names are unique
-	};
-
-extern mStatus mDNS_RegisterService  (mDNS *const m, ServiceRecordSet *sr,
-               const domainlabel *const name, const domainname *const type, const domainname *const domain,
-               const domainname *const host, mDNSIPPort port, const mDNSu8 txtinfo[], mDNSu16 txtlen,
-               AuthRecord *SubTypes, mDNSu32 NumSubTypes,
-               mDNSInterfaceID InterfaceID, mDNSServiceCallback Callback, void *Context, mDNSu32 flags);
-extern mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra, RData *rdata, mDNSu32 ttl,  mDNSu32 includeP2P);
-extern mStatus mDNS_RemoveRecordFromService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra, mDNSRecordCallback MemFreeCallback, void *Context);
-extern mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordSet *const sr, const domainlabel *newname);
-//extern mStatus mDNS_DeregisterService_drt(mDNS *const m, ServiceRecordSet *sr, mDNS_Dereg_type drt);
-//#define mDNS_DeregisterService(M,S) mDNS_DeregisterService_drt((M), (S), mDNS_Dereg_normal)
-extern mStatus mDNS_DeregisterService(mDNS *const m, ServiceRecordSet *sr);
-extern mStatus mDNS_RegisterNoSuchService(mDNS *const m, AuthRecord *const rr,
-               const domainlabel *const name, const domainname *const type, const domainname *const domain,
-               const domainname *const host,
-               const mDNSInterfaceID InterfaceID, mDNSRecordCallback Callback, void *Context, mDNSBool includeP2P);
-#define        mDNS_DeregisterNoSuchService mDNS_Deregister
-
-extern void mDNS_SetupQuestion(DNSQuestion *const q, const mDNSInterfaceID InterfaceID, const domainname *const name,
-               const mDNSu16 qtype, mDNSQuestionCallback *const callback, void *const context);
-
-extern mStatus mDNS_StartBrowse(mDNS *const m, DNSQuestion *const question,
-               const domainname *const srv, const domainname *const domain,
-               const mDNSInterfaceID InterfaceID, mDNSBool ForceMCast, mDNSQuestionCallback *Callback, void *Context);
-#define        mDNS_StopBrowse mDNS_StopQuery
-
-extern mStatus mDNS_StartResolveService(mDNS *const m, ServiceInfoQuery *query, ServiceInfo *info, mDNSServiceInfoQueryCallback *Callback, void *Context);
-extern void    mDNS_StopResolveService (mDNS *const m, ServiceInfoQuery *query);
-
-typedef enum
-	{
-	mDNS_DomainTypeBrowse              = 0,
-	mDNS_DomainTypeBrowseDefault       = 1,
-	mDNS_DomainTypeBrowseAutomatic     = 2,
-	mDNS_DomainTypeRegistration        = 3,
-	mDNS_DomainTypeRegistrationDefault = 4,
-
-	mDNS_DomainTypeMax = 4
-	} mDNS_DomainType;
-
-//extern const char *const mDNS_DomainTypeNames[];
-
-extern mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, mDNS_DomainType DomainType, const domainname *dom,
-								const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *Callback, void *Context);
-#define        mDNS_StopGetDomains mDNS_StopQuery
-extern mStatus mDNS_AdvertiseDomains(mDNS *const m, AuthRecord *rr, mDNS_DomainType DomainType, const mDNSInterfaceID InterfaceID, char *domname);
-#define        mDNS_StopAdvertiseDomains mDNS_Deregister
-
-extern mDNSOpaque16 mDNS_NewMessageID(mDNS *const m);
-extern mDNSBool mDNS_AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr);
-
-extern DNSServer *GetServerForName(mDNS *m, const domainname *name, mDNSInterfaceID InterfaceID);
-extern DNSServer *GetServerForQuestion(mDNS *m, DNSQuestion *question);
-extern mDNSu32 SetValidDNSServers(mDNS *m, DNSQuestion *question);
-
-// ***************************************************************************
-#if 0
-#pragma mark -
-#pragma mark - DNS name utility functions
-#endif
-
-// In order to expose the full capabilities of the DNS protocol (which allows any arbitrary eight-bit values
-// in domain name labels, including unlikely characters like ascii nulls and even dots) all the mDNS APIs
-// work with DNS's native length-prefixed strings. For convenience in C, the following utility functions
-// are provided for converting between C's null-terminated strings and DNS's length-prefixed strings.
-
-// Assignment
-// A simple C structure assignment of a domainname can cause a protection fault by accessing unmapped memory,
-// because that object is defined to be 256 bytes long, but not all domainname objects are truly the full size.
-// This macro uses mDNSPlatformMemCopy() to make sure it only touches the actual bytes that are valid.
-#define AssignDomainName(DST, SRC) do { mDNSu16 len__ = DomainNameLength((SRC)); \
-	if (len__ <= MAX_DOMAIN_NAME) mDNSPlatformMemCopy((DST)->c, (SRC)->c, len__); else (DST)->c[0] = 0; } while(0)
-
-// Comparison functions
-#define SameDomainLabelCS(A,B) ((A)[0] == (B)[0] && mDNSPlatformMemSame((A)+1, (B)+1, (A)[0]))
-extern mDNSBool SameDomainLabel(const mDNSu8 *a, const mDNSu8 *b);
-extern mDNSBool SameDomainName(const domainname *const d1, const domainname *const d2);
-extern mDNSBool SameDomainNameCS(const domainname *const d1, const domainname *const d2);
-typedef mDNSBool DomainNameComparisonFn(const domainname *const d1, const domainname *const d2);
-extern mDNSBool IsLocalDomain(const domainname *d);     // returns true for domains that by default should be looked up using link-local multicast
-
-#define StripFirstLabel(X) ((const domainname *)&(X)->c[(X)->c[0] ? 1 + (X)->c[0] : 0])
-
-#define FirstLabel(X)  ((const domainlabel *)(X))
-#define SecondLabel(X) ((const domainlabel *)StripFirstLabel(X))
-#define ThirdLabel(X)  ((const domainlabel *)StripFirstLabel(StripFirstLabel(X)))
-
-extern const mDNSu8 *LastLabel(const domainname *d);
-
-// Get total length of domain name, in native DNS format, including terminal root label
-//   (e.g. length of "com." is 5 (length byte, three data bytes, final zero)
-extern mDNSu16  DomainNameLengthLimit(const domainname *const name, const mDNSu8 *limit);
-#define DomainNameLength(name) DomainNameLengthLimit((name), (name)->c + MAX_DOMAIN_NAME)
-
-// Append functions to append one or more labels to an existing native format domain name:
-//   AppendLiteralLabelString adds a single label from a literal C string, with no escape character interpretation.
-//   AppendDNSNameString      adds zero or more labels from a C string using conventional DNS dots-and-escaping interpretation
-//   AppendDomainLabel        adds a single label from a native format domainlabel
-//   AppendDomainName         adds zero or more labels from a native format domainname
-extern mDNSu8  *AppendLiteralLabelString(domainname *const name, const char *cstr);
-extern mDNSu8  *AppendDNSNameString     (domainname *const name, const char *cstr);
-extern mDNSu8  *AppendDomainLabel       (domainname *const name, const domainlabel *const label);
-extern mDNSu8  *AppendDomainName        (domainname *const name, const domainname *const append);
-
-// Convert from null-terminated string to native DNS format:
-//   The DomainLabel form makes a single label from a literal C string, with no escape character interpretation.
-//   The DomainName form makes native format domain name from a C string using conventional DNS interpretation:
-//     dots separate labels, and within each label, '\.' represents a literal dot, '\\' represents a literal
-//     backslash and backslash with three decimal digits (e.g. \000) represents an arbitrary byte value.
-extern mDNSBool MakeDomainLabelFromLiteralString(domainlabel *const label, const char *cstr);
-extern mDNSu8  *MakeDomainNameFromDNSNameString (domainname  *const name,  const char *cstr);
-
-// Convert native format domainlabel or domainname back to C string format
-// IMPORTANT:
-// When using ConvertDomainLabelToCString, the target buffer must be MAX_ESCAPED_DOMAIN_LABEL (254) bytes long
-// to guarantee there will be no buffer overrun. It is only safe to use a buffer shorter than this in rare cases
-// where the label is known to be constrained somehow (for example, if the label is known to be either "_tcp" or "_udp").
-// Similarly, when using ConvertDomainNameToCString, the target buffer must be MAX_ESCAPED_DOMAIN_NAME (1009) bytes long.
-// See definitions of MAX_ESCAPED_DOMAIN_LABEL and MAX_ESCAPED_DOMAIN_NAME for more detailed explanation.
-extern char    *ConvertDomainLabelToCString_withescape(const domainlabel *const name, char *cstr, char esc);
-#define         ConvertDomainLabelToCString_unescaped(D,C) ConvertDomainLabelToCString_withescape((D), (C), 0)
-#define         ConvertDomainLabelToCString(D,C)           ConvertDomainLabelToCString_withescape((D), (C), '\\')
-extern char    *ConvertDomainNameToCString_withescape(const domainname *const name, char *cstr, char esc);
-#define         ConvertDomainNameToCString_unescaped(D,C) ConvertDomainNameToCString_withescape((D), (C), 0)
-#define         ConvertDomainNameToCString(D,C)           ConvertDomainNameToCString_withescape((D), (C), '\\')
-
-extern void     ConvertUTF8PstringToRFC1034HostLabel(const mDNSu8 UTF8Name[], domainlabel *const hostlabel);
-
-extern mDNSu8  *ConstructServiceName(domainname *const fqdn, const domainlabel *name, const domainname *type, const domainname *const domain);
-extern mDNSBool DeconstructServiceName(const domainname *const fqdn, domainlabel *const name, domainname *const type, domainname *const domain);
-
-// Note: Some old functions have been replaced by more sensibly-named versions.
-// You can uncomment the hash-defines below if you don't want to have to change your source code right away.
-// When updating your code, note that (unlike the old versions) *all* the new routines take the target object
-// as their first parameter.
-//#define ConvertCStringToDomainName(SRC,DST)  MakeDomainNameFromDNSNameString((DST),(SRC))
-//#define ConvertCStringToDomainLabel(SRC,DST) MakeDomainLabelFromLiteralString((DST),(SRC))
-//#define AppendStringLabelToName(DST,SRC)     AppendLiteralLabelString((DST),(SRC))
-//#define AppendStringNameToName(DST,SRC)      AppendDNSNameString((DST),(SRC))
-//#define AppendDomainLabelToName(DST,SRC)     AppendDomainLabel((DST),(SRC))
-//#define AppendDomainNameToName(DST,SRC)      AppendDomainName((DST),(SRC))
-
-// ***************************************************************************
-#if 0
-#pragma mark -
-#pragma mark - Other utility functions and macros
-#endif
-
-// mDNS_vsnprintf/snprintf return the number of characters written, excluding the final terminating null.
-// The output is always null-terminated: for example, if the output turns out to be exactly buflen long,
-// then the output will be truncated by one character to allow space for the terminating null.
-// Unlike standard C vsnprintf/snprintf, they return the number of characters *actually* written,
-// not the number of characters that *would* have been printed were buflen unlimited.
-extern mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, va_list arg);
-extern mDNSu32 mDNS_snprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, ...) IS_A_PRINTF_STYLE_FUNCTION(3,4);
-extern mDNSu32 NumCacheRecordsForInterfaceID(const mDNS *const m, mDNSInterfaceID id);
-extern char *DNSTypeName(mDNSu16 rrtype);
-extern char *GetRRDisplayString_rdb(const ResourceRecord *const rr, const RDataBody *const rd1, char *const buffer);
-#define RRDisplayString(m, rr) GetRRDisplayString_rdb(rr, &(rr)->rdata->u, (m)->MsgBuffer)
-#define ARDisplayString(m, rr) GetRRDisplayString_rdb(&(rr)->resrec, &(rr)->resrec.rdata->u, (m)->MsgBuffer)
-#define CRDisplayString(m, rr) GetRRDisplayString_rdb(&(rr)->resrec, &(rr)->resrec.rdata->u, (m)->MsgBuffer)
-extern mDNSBool mDNSSameAddress(const mDNSAddr *ip1, const mDNSAddr *ip2);
-extern void IncrementLabelSuffix(domainlabel *name, mDNSBool RichText);
-extern mDNSBool mDNSv4AddrIsRFC1918(mDNSv4Addr *addr);  // returns true for RFC1918 private addresses
-#define mDNSAddrIsRFC1918(X) ((X)->type == mDNSAddrType_IPv4 && mDNSv4AddrIsRFC1918(&(X)->ip.v4))
-
-#define mDNSSameIPPort(A,B)      ((A).NotAnInteger == (B).NotAnInteger)
-#define mDNSSameOpaque16(A,B)    ((A).NotAnInteger == (B).NotAnInteger)
-#define mDNSSameOpaque32(A,B)    ((A).NotAnInteger == (B).NotAnInteger)
-#define mDNSSameOpaque64(A,B)    ((A)->l[0] == (B)->l[0] && (A)->l[1] == (B)->l[1])
-
-#define mDNSSameIPv4Address(A,B) ((A).NotAnInteger == (B).NotAnInteger)
-#define mDNSSameIPv6Address(A,B) ((A).l[0] == (B).l[0] && (A).l[1] == (B).l[1] && (A).l[2] == (B).l[2] && (A).l[3] == (B).l[3])
-#define mDNSSameEthAddress(A,B)  ((A)->w[0] == (B)->w[0] && (A)->w[1] == (B)->w[1] && (A)->w[2] == (B)->w[2])
-
-#define mDNSIPPortIsZero(A)      ((A).NotAnInteger                            == 0)
-#define mDNSOpaque16IsZero(A)    ((A).NotAnInteger                            == 0)
-#define mDNSOpaque64IsZero(A)    (((A)->l[0] | (A)->l[1]                    ) == 0)
-#define mDNSIPv4AddressIsZero(A) ((A).NotAnInteger                            == 0)
-#define mDNSIPv6AddressIsZero(A) (((A).l[0] | (A).l[1] | (A).l[2] | (A).l[3]) == 0)
-#define mDNSEthAddressIsZero(A)  (((A).w[0] | (A).w[1] | (A).w[2]           ) == 0)
-
-#define mDNSIPv4AddressIsOnes(A) ((A).NotAnInteger == 0xFFFFFFFF)
-#define mDNSIPv6AddressIsOnes(A) (((A).l[0] & (A).l[1] & (A).l[2] & (A).l[3]) == 0xFFFFFFFF)
-#if HAVE_IPV6
-#define mDNSAddressIsAllDNSLinkGroup(X) (                                                            \
-	((X)->type == mDNSAddrType_IPv4 && mDNSSameIPv4Address((X)->ip.v4, AllDNSLinkGroup_v4.ip.v4)) || \
-	((X)->type == mDNSAddrType_IPv6 && mDNSSameIPv6Address((X)->ip.v6, AllDNSLinkGroup_v6.ip.v6))    )
-#else
-#define mDNSAddressIsAllDNSLinkGroup(X) (                                                            \
-	((X)->type == mDNSAddrType_IPv4 && mDNSSameIPv4Address((X)->ip.v4, AllDNSLinkGroup_v4.ip.v4))  )
-#endif
-#define mDNSAddressIsZero(X) (                                                \
-	((X)->type == mDNSAddrType_IPv4 && mDNSIPv4AddressIsZero((X)->ip.v4))  || \
-	((X)->type == mDNSAddrType_IPv6 && mDNSIPv6AddressIsZero((X)->ip.v6))     )
-
-#define mDNSAddressIsValidNonZero(X) (                                        \
-	((X)->type == mDNSAddrType_IPv4 && !mDNSIPv4AddressIsZero((X)->ip.v4)) || \
-	((X)->type == mDNSAddrType_IPv6 && !mDNSIPv6AddressIsZero((X)->ip.v6))    )
-
-#define mDNSAddressIsOnes(X) (                                                \
-	((X)->type == mDNSAddrType_IPv4 && mDNSIPv4AddressIsOnes((X)->ip.v4))  || \
-	((X)->type == mDNSAddrType_IPv6 && mDNSIPv6AddressIsOnes((X)->ip.v6))     )
-
-#define mDNSAddressIsValid(X) (                                                                                             \
-	((X)->type == mDNSAddrType_IPv4) ? !(mDNSIPv4AddressIsZero((X)->ip.v4) || mDNSIPv4AddressIsOnes((X)->ip.v4)) :          \
-	((X)->type == mDNSAddrType_IPv6) ? !(mDNSIPv6AddressIsZero((X)->ip.v6) || mDNSIPv6AddressIsOnes((X)->ip.v6)) : mDNSfalse)
-
-#define mDNSv4AddressIsLinkLocal(X) ((X)->b[0] ==  169 &&  (X)->b[1]         ==  254)
-#define mDNSv6AddressIsLinkLocal(X) ((X)->b[0] == 0xFE && ((X)->b[1] & 0xC0) == 0x80)
-
-#define mDNSAddressIsLinkLocal(X)  (                                                    \
-	((X)->type == mDNSAddrType_IPv4) ? mDNSv4AddressIsLinkLocal(&(X)->ip.v4) :          \
-	((X)->type == mDNSAddrType_IPv6) ? mDNSv6AddressIsLinkLocal(&(X)->ip.v6) : mDNSfalse)
-
-#define mDNSv4AddressIsLoopback(X) ((X)->b[0] == 127 && (X)->b[1] == 0 && (X)->b[2] == 0 && (X)->b[3] == 1)
-#define mDNSv6AddressIsLoopback(X) ((((X)->l[0] | (X)->l[1] | (X)->l[2]) == 0) && ((X)->b[12] == 0 && (X)->b[13] == 0 && (X)->b[14] == 0 && (X)->b[15] == 1))
-
-// ***************************************************************************
-#if 0
-#pragma mark -
-#pragma mark - Authentication Support
-#endif
-
-// Unicast DNS and Dynamic Update specific Client Calls
-//
-// mDNS_SetSecretForDomain tells the core to authenticate (via TSIG with an HMAC_MD5 hash of the shared secret)
-// when dynamically updating a given zone (and its subdomains).  The key used in authentication must be in
-// domain name format.  The shared secret must be a null-terminated base64 encoded string.  A minimum size of
-// 16 bytes (128 bits) is recommended for an MD5 hash as per RFC 2485.
-// Calling this routine multiple times for a zone replaces previously entered values.  Call with a NULL key
-// to disable authentication for the zone.  A non-NULL autoTunnelPrefix means this is an AutoTunnel domain,
-// and the value is prepended to the IPSec identifier (used for key lookup)
-
-extern mStatus mDNS_SetSecretForDomain(mDNS *m, DomainAuthInfo *info,
-	const domainname *domain, const domainname *keyname, const char *b64keydata, const domainname *hostname, mDNSIPPort *port, const char *autoTunnelPrefix);
-
-extern void RecreateNATMappings(mDNS *const m);
-
-// Hostname/Unicast Interface Configuration
-
-// All hostnames advertised point to one IPv4 address and/or one IPv6 address, set via SetPrimaryInterfaceInfo.  Invoking this routine
-// updates all existing hostnames to point to the new address.
-
-// A hostname is added via AddDynDNSHostName, which points to the primary interface's v4 and/or v6 addresss
-
-// The status callback is invoked to convey success or failure codes - the callback should not modify the AuthRecord or free memory.
-// Added hostnames may be removed (deregistered) via mDNS_RemoveDynDNSHostName.
-
-// Host domains added prior to specification of the primary interface address and computer name will be deferred until
-// these values are initialized.
-
-// DNS servers used to resolve unicast queries are specified by mDNS_AddDNSServer.
-// For "split" DNS configurations, in which queries for different domains are sent to different servers (e.g. VPN and external),
-// a domain may be associated with a DNS server.  For standard configurations, specify the root label (".") or NULL.
-
-extern void mDNS_AddDynDNSHostName(mDNS *m, const domainname *fqdn, mDNSRecordCallback *StatusCallback, const void *StatusContext);
-extern void mDNS_RemoveDynDNSHostName(mDNS *m, const domainname *fqdn);
-extern void mDNS_SetPrimaryInterfaceInfo(mDNS *m, const mDNSAddr *v4addr,  const mDNSAddr *v6addr, const mDNSAddr *router);
-extern DNSServer *mDNS_AddDNSServer(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, const mDNSAddr *addr, const mDNSIPPort port, mDNSBool scoped, mDNSu32 timeout);
-extern void PenalizeDNSServer(mDNS *const m, DNSQuestion *q);
-extern void mDNS_AddSearchDomain(const domainname *const domain, mDNSInterfaceID InterfaceID);
-
-extern McastResolver *mDNS_AddMcastResolver(mDNS *const m, const domainname *d, const mDNSInterfaceID interface, mDNSu32 timeout);
-
-// We use ((void *)0) here instead of mDNSNULL to avoid compile warnings on gcc 4.2
-#define mDNS_AddSearchDomain_CString(X, I) \
-	do { domainname d__; if (((X) != (void*)0) && MakeDomainNameFromDNSNameString(&d__, (X)) && d__.c[0]) mDNS_AddSearchDomain(&d__, I); } while(0)
-
-// Routines called by the core, exported by DNSDigest.c
-
-// Convert an arbitrary base64 encoded key key into an HMAC key (stored in AuthInfo struct)
-extern mDNSs32 DNSDigest_ConstructHMACKeyfromBase64(DomainAuthInfo *info, const char *b64key);
-
-// sign a DNS message.  The message must be complete, with all values in network byte order.  end points to the end
-// of the message, and is modified by this routine.  numAdditionals is a pointer to the number of additional
-// records in HOST byte order, which is incremented upon successful completion of this routine.  The function returns
-// the new end pointer on success, and NULL on failure.
-extern void DNSDigest_SignMessage(DNSMessage *msg, mDNSu8 **end, DomainAuthInfo *info, mDNSu16 tcode);
-
-#define SwapDNSHeaderBytes(M) do { \
-    (M)->h.numQuestions   = (mDNSu16)((mDNSu8 *)&(M)->h.numQuestions  )[0] << 8 | ((mDNSu8 *)&(M)->h.numQuestions  )[1]; \
-    (M)->h.numAnswers     = (mDNSu16)((mDNSu8 *)&(M)->h.numAnswers    )[0] << 8 | ((mDNSu8 *)&(M)->h.numAnswers    )[1]; \
-    (M)->h.numAuthorities = (mDNSu16)((mDNSu8 *)&(M)->h.numAuthorities)[0] << 8 | ((mDNSu8 *)&(M)->h.numAuthorities)[1]; \
-    (M)->h.numAdditionals = (mDNSu16)((mDNSu8 *)&(M)->h.numAdditionals)[0] << 8 | ((mDNSu8 *)&(M)->h.numAdditionals)[1]; \
-    } while (0)
-
-#define DNSDigest_SignMessageHostByteOrder(M,E,INFO) \
-	do { SwapDNSHeaderBytes(M); DNSDigest_SignMessage((M), (E), (INFO), 0); SwapDNSHeaderBytes(M); } while (0)
-
-// verify a DNS message.  The message must be complete, with all values in network byte order.  end points to the
-// end of the record.  tsig is a pointer to the resource record that contains the TSIG OPT record.  info is
-// the matching key to use for verifying the message.  This function expects that the additionals member
-// of the DNS message header has already had one subtracted from it.
-extern mDNSBool DNSDigest_VerifyMessage(DNSMessage *msg, mDNSu8 *end, LargeCacheRecord *tsig, DomainAuthInfo *info, mDNSu16 *rcode, mDNSu16 *tcode);
-
-// ***************************************************************************
-#if 0
-#pragma mark -
-#pragma mark - PlatformSupport interface
-#endif
-
-// This section defines the interface to the Platform Support layer.
-// Normal client code should not use any of types defined here, or directly call any of the functions defined here.
-// The definitions are placed here because sometimes clients do use these calls indirectly, via other supported client operations.
-// For example, AssignDomainName is a macro defined using mDNSPlatformMemCopy()
-
-// Every platform support module must provide the following functions.
-// mDNSPlatformInit() typically opens a communication endpoint, and starts listening for mDNS packets.
-// When Setup is complete, the platform support layer calls mDNSCoreInitComplete().
-// mDNSPlatformSendUDP() sends one UDP packet
-// When a packet is received, the PlatformSupport code calls mDNSCoreReceive()
-// mDNSPlatformClose() tidies up on exit
-//
-// Note: mDNSPlatformMemAllocate/mDNSPlatformMemFree are only required for handling oversized resource records and unicast DNS.
-// If your target platform has a well-defined specialized application, and you know that all the records it uses
-// are InlineCacheRDSize or less, then you can just make a simple mDNSPlatformMemAllocate() stub that always returns
-// NULL. InlineCacheRDSize is a compile-time constant, which is set by default to 68. If you need to handle records
-// a little larger than this and you don't want to have to implement run-time allocation and freeing, then you
-// can raise the value of this constant to a suitable value (at the expense of increased memory usage).
-//
-// USE CAUTION WHEN CALLING mDNSPlatformRawTime: The m->timenow_adjust correction factor needs to be added
-// Generally speaking:
-// Code that's protected by the main mDNS lock should just use the m->timenow value
-// Code outside the main mDNS lock should use mDNS_TimeNow(m) to get properly adjusted time
-// In certain cases there may be reasons why it's necessary to get the time without taking the lock first
-// (e.g. inside the routines that are doing the locking and unlocking, where a call to get the lock would result in a
-// recursive loop); in these cases use mDNS_TimeNow_NoLock(m) to get mDNSPlatformRawTime with the proper correction factor added.
-//
-// mDNSPlatformUTC returns the time, in seconds, since Jan 1st 1970 UTC and is required for generating TSIG records
-
-extern mStatus  mDNSPlatformInit        (mDNS *const m);
-extern void     mDNSPlatformClose       (mDNS *const m);
-extern mStatus  mDNSPlatformSendUDP(const mDNS *const m, const void *const msg, const mDNSu8 *const end,
-mDNSInterfaceID InterfaceID, UDPSocket *src, const mDNSAddr *dst, mDNSIPPort dstport);
-
-extern void     mDNSPlatformLock        (const mDNS *const m);
-extern void     mDNSPlatformUnlock      (const mDNS *const m);
-
-extern void     mDNSPlatformStrCopy     (      void *dst, const void *src);
-extern mDNSu32  mDNSPlatformStrLen      (                 const void *src);
-extern void     mDNSPlatformMemCopy     (      void *dst, const void *src, mDNSu32 len);
-extern mDNSBool mDNSPlatformMemSame     (const void *dst, const void *src, mDNSu32 len);
-extern void     mDNSPlatformMemZero     (      void *dst,                  mDNSu32 len);
-#if APPLE_OSX_mDNSResponder && MACOSX_MDNS_MALLOC_DEBUGGING
-#define         mDNSPlatformMemAllocate(X) mallocL(#X, X)
-#else
-extern void *   mDNSPlatformMemAllocate (mDNSu32 len);
-#endif
-extern void     mDNSPlatformMemFree     (void *mem);
-
-// If the platform doesn't have a strong PRNG, we define a naive multiply-and-add based on a seed
-// from the platform layer.  Long-term, we should embed an arc4 implementation, but the strength
-// will still depend on the randomness of the seed.
-#if !defined(_PLATFORM_HAS_STRONG_PRNG_) && (_BUILDING_XCODE_PROJECT_ || defined(_WIN32))
-#define _PLATFORM_HAS_STRONG_PRNG_ 1
-#endif
-#if _PLATFORM_HAS_STRONG_PRNG_
-extern mDNSu32  mDNSPlatformRandomNumber(void);
-#else
-extern mDNSu32  mDNSPlatformRandomSeed  (void);
-#endif // _PLATFORM_HAS_STRONG_PRNG_
-
-extern mStatus  mDNSPlatformTimeInit    (void);
-extern mDNSs32  mDNSPlatformRawTime     (void);
-extern mDNSs32  mDNSPlatformUTC         (void);
-#define mDNS_TimeNow_NoLock(m) (mDNSPlatformRawTime() + (m)->timenow_adjust)
-
-#if MDNS_DEBUGMSGS
-extern void	mDNSPlatformWriteDebugMsg(const char *msg);
-#endif
-extern void	mDNSPlatformWriteLogMsg(const char *ident, const char *msg, mDNSLogLevel_t loglevel);
-
-#if APPLE_OSX_mDNSResponder
-// Utility function for ASL logging
-mDNSexport void mDNSASLLog(uuid_t *uuid, const char *subdomain, const char *result, const char *signature, const char *fmt, ...);
-#endif
-
-// Platform support modules should provide the following functions to map between opaque interface IDs
-// and interface indexes in order to support the DNS-SD API. If your target platform does not support
-// multiple interfaces and/or does not support the DNS-SD API, these functions can be empty.
-extern mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(mDNS *const m, mDNSu32 ifindex);
-extern mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(mDNS *const m, mDNSInterfaceID id, mDNSBool suppressNetworkChange);
-
-// Every platform support module must provide the following functions if it is to support unicast DNS
-// and Dynamic Update.
-// All TCP socket operations implemented by the platform layer MUST NOT BLOCK.
-// mDNSPlatformTCPConnect initiates a TCP connection with a peer, adding the socket descriptor to the
-// main event loop.  The return value indicates whether the connection succeeded, failed, or is pending
-// (i.e. the call would block.)  On return, the descriptor parameter is set to point to the connected socket.
-// The TCPConnectionCallback is subsequently invoked when the connection
-// completes (in which case the ConnectionEstablished parameter is true), or data is available for
-// reading on the socket (indicated by the ConnectionEstablished parameter being false.)  If the connection
-// asynchronously fails, the TCPConnectionCallback should be invoked as usual, with the error being
-// returned in subsequent calls to PlatformReadTCP or PlatformWriteTCP.  (This allows for platforms
-// with limited asynchronous error detection capabilities.)  PlatformReadTCP and PlatformWriteTCP must
-// return the number of bytes read/written, 0 if the call would block, and -1 if an error.  PlatformReadTCP
-// should set the closed argument if the socket has been closed.
-// PlatformTCPCloseConnection must close the connection to the peer and remove the descriptor from the
-// event loop.  CloseConnectin may be called at any time, including in a ConnectionCallback.
-
-typedef enum
-	{
-	kTCPSocketFlags_Zero   = 0,
-	kTCPSocketFlags_UseTLS = (1 << 0)
-	} TCPSocketFlags;
-
-typedef void (*TCPConnectionCallback)(TCPSocket *sock, void *context, mDNSBool ConnectionEstablished, mStatus err);
-extern TCPSocket *mDNSPlatformTCPSocket(mDNS *const m, TCPSocketFlags flags, mDNSIPPort *port);	// creates a TCP socket
-extern TCPSocket *mDNSPlatformTCPAccept(TCPSocketFlags flags, int sd);
-extern int        mDNSPlatformTCPGetFD(TCPSocket *sock);
-extern mStatus    mDNSPlatformTCPConnect(TCPSocket *sock, const mDNSAddr *dst, mDNSOpaque16 dstport, domainname *hostname,
-										mDNSInterfaceID InterfaceID, TCPConnectionCallback callback, void *context);
-extern void       mDNSPlatformTCPCloseConnection(TCPSocket *sock);
-extern long       mDNSPlatformReadTCP(TCPSocket *sock, void *buf, unsigned long buflen, mDNSBool *closed);
-extern long       mDNSPlatformWriteTCP(TCPSocket *sock, const char *msg, unsigned long len);
-extern UDPSocket *mDNSPlatformUDPSocket(mDNS *const m, const mDNSIPPort requestedport);
-extern void       mDNSPlatformUDPClose(UDPSocket *sock);
-extern void       mDNSPlatformReceiveBPF_fd(mDNS *const m, int fd);
-extern void       mDNSPlatformUpdateProxyList(mDNS *const m, const mDNSInterfaceID InterfaceID);
-extern void       mDNSPlatformSendRawPacket(const void *const msg, const mDNSu8 *const end, mDNSInterfaceID InterfaceID);
-extern void       mDNSPlatformSetLocalAddressCacheEntry(mDNS *const m, const mDNSAddr *const tpa, const mDNSEthAddr *const tha, mDNSInterfaceID InterfaceID);
-extern void       mDNSPlatformSourceAddrForDest(mDNSAddr *const src, const mDNSAddr *const dst);
-
-// mDNSPlatformTLSSetupCerts/mDNSPlatformTLSTearDownCerts used by dnsextd
-extern mStatus    mDNSPlatformTLSSetupCerts(void);
-extern void       mDNSPlatformTLSTearDownCerts(void);
-
-// Platforms that support unicast browsing and dynamic update registration for clients who do not specify a domain
-// in browse/registration calls must implement these routines to get the "default" browse/registration list.
-
-extern void       mDNSPlatformSetDNSConfig(mDNS *const m, mDNSBool setservers, mDNSBool setsearch, domainname *const fqdn, DNameListElem **RegDomains, DNameListElem **BrowseDomains);
-extern mStatus    mDNSPlatformGetPrimaryInterface(mDNS *const m, mDNSAddr *v4, mDNSAddr *v6, mDNSAddr *router);
-extern void       mDNSPlatformDynDNSHostNameStatusChanged(const domainname *const dname, const mStatus status);
-
-extern void       mDNSPlatformSetAllowSleep(mDNS *const m, mDNSBool allowSleep, const char *reason);
-extern void       mDNSPlatformSendWakeupPacket(mDNS *const m, mDNSInterfaceID InterfaceID, char *EthAddr, char *IPAddr, int iteration);
-extern mDNSBool   mDNSPlatformValidRecordForInterface(AuthRecord *rr, const NetworkInterfaceInfo *intf);
-
-#ifdef _LEGACY_NAT_TRAVERSAL_
-// Support for legacy NAT traversal protocols, implemented by the platform layer and callable by the core.
-extern void     LNT_SendDiscoveryMsg(mDNS *m);
-extern void     LNT_ConfigureRouterInfo(mDNS *m, const mDNSInterfaceID InterfaceID, const mDNSu8 *const data, const mDNSu16 len);
-extern mStatus  LNT_GetExternalAddress(mDNS *m);
-extern mStatus  LNT_MapPort(mDNS *m, NATTraversalInfo *n);
-extern mStatus  LNT_UnmapPort(mDNS *m, NATTraversalInfo *n);
-extern void     LNT_ClearState(mDNS *const m);
-#endif // _LEGACY_NAT_TRAVERSAL_
-
-// The core mDNS code provides these functions, for the platform support code to call at appropriate times
-//
-// mDNS_SetFQDN() is called once on startup (typically from mDNSPlatformInit())
-// and then again on each subsequent change of the host name.
-//
-// mDNS_RegisterInterface() is used by the platform support layer to inform mDNSCore of what
-// physical and/or logical interfaces are available for sending and receiving packets.
-// Typically it is called on startup for each available interface, but register/deregister may be
-// called again later, on multiple occasions, to inform the core of interface configuration changes.
-// If set->Advertise is set non-zero, then mDNS_RegisterInterface() also registers the standard
-// resource records that should be associated with every publicised IP address/interface:
-// -- Name-to-address records (A/AAAA)
-// -- Address-to-name records (PTR)
-// -- Host information (HINFO)
-// IMPORTANT: The specified mDNSInterfaceID MUST NOT be 0, -1, or -2; these values have special meaning
-// mDNS_RegisterInterface does not result in the registration of global hostnames via dynamic update -
-// see mDNS_SetPrimaryInterfaceInfo, mDNS_AddDynDNSHostName, etc. for this purpose.
-// Note that the set may be deallocated immediately after it is deregistered via mDNS_DeegisterInterface.
-//
-// mDNS_RegisterDNS() is used by the platform support layer to provide the core with the addresses of
-// available domain name servers for unicast queries/updates.  RegisterDNS() should be called once for
-// each name server, typically at startup, or when a new name server becomes available.  DeregiterDNS()
-// must be called whenever a registered name server becomes unavailable.  DeregisterDNSList deregisters
-// all registered servers.  mDNS_DNSRegistered() returns true if one or more servers are registered in the core.
-//
-// mDNSCoreInitComplete() is called when the platform support layer is finished.
-// Typically this is at the end of mDNSPlatformInit(), but may be later
-// (on platforms like OT that allow asynchronous initialization of the networking stack).
-//
-// mDNSCoreReceive() is called when a UDP packet is received
-//
-// mDNSCoreMachineSleep() is called when the machine sleeps or wakes
-// (This refers to heavyweight laptop-style sleep/wake that disables network access,
-// not lightweight second-by-second CPU power management modes.)
-
-extern void     mDNS_SetFQDN(mDNS *const m);
-extern void     mDNS_ActivateNetWake_internal  (mDNS *const m, NetworkInterfaceInfo *set);
-extern void     mDNS_DeactivateNetWake_internal(mDNS *const m, NetworkInterfaceInfo *set);
-extern mStatus  mDNS_RegisterInterface  (mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping);
-extern void     mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set, mDNSBool flapping);
-extern void     mDNSCoreInitComplete(mDNS *const m, mStatus result);
-extern void     mDNSCoreReceive(mDNS *const m, void *const msg, const mDNSu8 *const end,
-								const mDNSAddr *const srcaddr, const mDNSIPPort srcport,
-								const mDNSAddr *dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID);
-extern void		mDNSCoreRestartQueries(mDNS *const m);
-typedef void    (*FlushCache)(mDNS *const m);
-typedef void    (*CallbackBeforeStartQuery)(mDNS *const m, void *context);
-extern void		mDNSCoreRestartAddressQueries(mDNS *const m, mDNSBool SearchDomainsChanged, FlushCache flushCacheRecords,
-											  CallbackBeforeStartQuery beforeQueryStart, void *context);
-extern mDNSBool mDNSCoreHaveAdvertisedMulticastServices(mDNS *const m);
-extern void     mDNSCoreMachineSleep(mDNS *const m, mDNSBool wake);
-extern mDNSBool mDNSCoreReadyForSleep(mDNS *m, mDNSs32 now);
-extern mDNSs32  mDNSCoreIntervalToNextWake(mDNS *const m, mDNSs32 now);
-
-extern void     mDNSCoreReceiveRawPacket  (mDNS *const m, const mDNSu8 *const p, const mDNSu8 *const end, const mDNSInterfaceID InterfaceID);
-
-extern mDNSBool mDNSAddrIsDNSMulticast(const mDNSAddr *ip);
-
-extern CacheRecord *CreateNewCacheEntry(mDNS *const m, const mDNSu32 slot, CacheGroup *cg, mDNSs32 delay);
-extern void ScheduleNextCacheCheckTime(mDNS *const m, const mDNSu32 slot, const mDNSs32 event);
-extern void GrantCacheExtensions(mDNS *const m, DNSQuestion *q, mDNSu32 lease);
-extern void MakeNegativeCacheRecord(mDNS *const m, CacheRecord *const cr,
-	const domainname *const name, const mDNSu32 namehash, const mDNSu16 rrtype, const mDNSu16 rrclass, mDNSu32 ttl_seconds,
-	mDNSInterfaceID InterfaceID, DNSServer *dnsserver);
-extern void CompleteDeregistration(mDNS *const m, AuthRecord *rr);
-extern void AnswerCurrentQuestionWithResourceRecord(mDNS *const m, CacheRecord *const rr, const QC_result AddRecord);
-extern char *InterfaceNameForID(mDNS *const m, const mDNSInterfaceID InterfaceID);
-extern void DNSServerChangeForQuestion(mDNS *const m, DNSQuestion *q, DNSServer *newServer);
-extern void ActivateUnicastRegistration(mDNS *const m, AuthRecord *const rr);
-extern void CheckSuppressUnusableQuestions(mDNS *const m);
-extern void RetrySearchDomainQuestions(mDNS *const m);
-
-// Used only in logging to restrict the number of /etc/hosts entries printed
-extern void FreeEtcHosts(mDNS *const m, AuthRecord *const rr, mStatus result);
-// exported for using the hash for /etc/hosts AuthRecords
-extern AuthGroup *AuthGroupForName(AuthHash *r, const mDNSu32 slot, const mDNSu32 namehash, const domainname *const name);
-extern AuthGroup *AuthGroupForRecord(AuthHash *r, const mDNSu32 slot, const ResourceRecord *const rr);
-extern AuthGroup *InsertAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr);
-extern AuthGroup *RemoveAuthRecord(mDNS *const m, AuthHash *r, AuthRecord *rr);
-
-// For now this AutoTunnel stuff is specific to Mac OS X.
-// In the future, if there's demand, we may see if we can abstract it out cleanly into the platform layer
-#if APPLE_OSX_mDNSResponder
-extern void AutoTunnelCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, QC_result AddRecord);
-extern void AddNewClientTunnel(mDNS *const m, DNSQuestion *const q);
-extern void SetupLocalAutoTunnelInterface_internal(mDNS *const m, mDNSBool servicesStarting);
-extern void UpdateAutoTunnelDomainStatuses(const mDNS *const m);
-extern mStatus ActivateLocalProxy(mDNS *const m, char *ifname);
-extern void RemoveAutoTunnel6Record(mDNS *const m);
-extern mDNSBool RecordReadyForSleep(mDNS *const m, AuthRecord *rr);
-#endif
-
-// ***************************************************************************
-#if 0
-#pragma mark -
-#pragma mark - Sleep Proxy
-#endif
-
-// Sleep Proxy Server Property Encoding
-//
-// Sleep Proxy Servers are advertised using a structured service name, consisting of four
-// metrics followed by a human-readable name. The metrics assist clients in deciding which
-// Sleep Proxy Server(s) to use when multiple are available on the network. Each metric
-// is a two-digit decimal number in the range 10-99. Lower metrics are generally better.
-//
-//   AA-BB-CC-DD Name
-//
-// Metrics:
-//
-// AA = Intent
-// BB = Portability
-// CC = Marginal Power
-// DD = Total Power
-//
-//
-// ** Intent Metric **
-//
-// 20 = Dedicated Sleep Proxy Server -- a device, permanently powered on,
-//      installed for the express purpose of providing Sleep Proxy Service.
-//
-// 30 = Primary Network Infrastructure Hardware -- a router, DHCP server, NAT gateway,
-//      or similar permanently installed device which is permanently powered on.
-//      This is hardware designed for the express purpose of being network
-//      infrastructure, and for most home users is typically a single point
-//      of failure for the local network -- e.g. most home users only have
-//      a single NAT gateway / DHCP server. Even though in principle the
-//      hardware might technically be capable of running different software,
-//      a typical user is unlikely to do that. e.g. AirPort base station.
-//
-// 40 = Primary Network Infrastructure Software -- a general-purpose computer
-//      (e.g. Mac, Windows, Linux, etc.) which is currently running DHCP server
-//      or NAT gateway software, but the user could choose to turn that off
-//      fairly easily. e.g. iMac running Internet Sharing
-//
-// 50 = Secondary Network Infrastructure Hardware -- like primary infrastructure
-//      hardware, except not a single point of failure for the entire local network.
-//      For example, an AirPort base station in bridge mode. This may have clients
-//      associated with it, and if it goes away those clients will be inconvenienced,
-//      but unlike the NAT gateway / DHCP server, the entire local network is not
-//      dependent on it.
-//
-// 60 = Secondary Network Infrastructure Software -- like 50, but in a general-
-//      purpose CPU.
-//
-// 70 = Incidentally Available Hardware -- a device which has no power switch
-//      and is generally left powered on all the time. Even though it is not a
-//      part of what we conventionally consider network infrastructure (router,
-//      DHCP, NAT, DNS, etc.), and the rest of the network can operate fine
-//      without it, since it's available and unlikely to be turned off, it is a
-//      reasonable candidate for providing Sleep Proxy Service e.g. Apple TV,
-//      or an AirPort base station in client mode, associated with an existing
-//      wireless network (e.g. AirPort Express connected to a music system, or
-//      being used to share a USB printer).
-//
-// 80 = Incidentally Available Software -- a general-purpose computer which
-//      happens at this time to be set to "never sleep", and as such could be
-//      useful as a Sleep Proxy Server, but has not been intentionally provided
-//      for this purpose. Of all the Intent Metric categories this is the
-//      one most likely to be shut down or put to sleep without warning.
-//      However, if nothing else is availalable, it may be better than nothing.
-//      e.g. Office computer in the workplace which has been set to "never sleep"
-//
-//
-// ** Portability Metric **
-//
-// Inversely related to mass of device, on the basis that, all other things
-// being equal, heavier devices are less likely to be moved than lighter devices.
-// E.g. A MacBook running Internet Sharing is probably more likely to be
-// put to sleep and taken away than a Mac Pro running Internet Sharing.
-// The Portability Metric is a logarithmic decibel scale, computed by taking the
-// (approximate) mass of the device in milligrammes, taking the base 10 logarithm
-// of that, multiplying by 10, and subtracting the result from 100:
-//
-//   Portability Metric = 100 - (log10(mg) * 10)
-//
-// The Portability Metric is not necessarily computed literally from the actual
-// mass of the device; the intent is just that lower numbers indicate more
-// permanent devices, and higher numbers indicate devices more likely to be
-// removed from the network, e.g., in order of increasing portability:
-//
-// Mac Pro < iMac < Laptop < iPhone
-//
-// Example values:
-//
-// 10 = 1 metric tonne
-// 40 = 1kg
-// 70 = 1g
-// 90 = 10mg
-//
-//
-// ** Marginal Power and Total Power Metrics **
-//
-// The Marginal Power Metric is the power difference between sleeping and staying awake
-// to be a Sleep Proxy Server.
-//
-// The Total Power Metric is the total power consumption when being Sleep Proxy Server.
-//
-// The Power Metrics use a logarithmic decibel scale, computed as ten times the
-// base 10 logarithm of the (approximate) power in microwatts:
-//
-//   Power Metric = log10(uW) * 10
-//
-// Higher values indicate higher power consumption. Example values:
-//
-// 10 =  10 uW
-// 20 = 100 uW
-// 30 =   1 mW
-// 60 =   1 W
-// 90 =   1 kW
-
-typedef enum
-	{
-	mDNSSleepProxyMetric_Dedicated          = 20,
-	mDNSSleepProxyMetric_PrimaryHardware    = 30,
-	mDNSSleepProxyMetric_PrimarySoftware    = 40,
-	mDNSSleepProxyMetric_SecondaryHardware  = 50,
-	mDNSSleepProxyMetric_SecondarySoftware  = 60,
-	mDNSSleepProxyMetric_IncidentalHardware = 70,
-	mDNSSleepProxyMetric_IncidentalSoftware = 80
-	} mDNSSleepProxyMetric;
-
-extern void mDNSCoreBeSleepProxyServer_internal(mDNS *const m, mDNSu8 sps, mDNSu8 port, mDNSu8 marginalpower, mDNSu8 totpower);
-#define mDNSCoreBeSleepProxyServer(M,S,P,MP,TP) \
-	do { mDNS_Lock(m); mDNSCoreBeSleepProxyServer_internal((M),(S),(P),(MP),(TP)); mDNS_Unlock(m); } while(0)
-
-extern void FindSPSInCache(mDNS *const m, const DNSQuestion *const q, const CacheRecord *sps[3]);
-#define PrototypeSPSName(X) ((X)[0] >= 11 && (X)[3] == '-' && (X)[ 4] == '9' && (X)[ 5] == '9' && \
-                                             (X)[6] == '-' && (X)[ 7] == '9' && (X)[ 8] == '9' && \
-                                             (X)[9] == '-' && (X)[10] == '9' && (X)[11] == '9'    )
-#define ValidSPSName(X) ((X)[0] >= 5 && mDNSIsDigit((X)[1]) && mDNSIsDigit((X)[2]) && mDNSIsDigit((X)[4]) && mDNSIsDigit((X)[5]))
-#define SPSMetric(X) (!ValidSPSName(X) || PrototypeSPSName(X) ? 1000000 : \
-	((X)[1]-'0') * 100000 + ((X)[2]-'0') * 10000 + ((X)[4]-'0') * 1000 + ((X)[5]-'0') * 100 + ((X)[7]-'0') * 10 + ((X)[8]-'0'))
-
-// ***************************************************************************
-#if 0
-#pragma mark -
-#pragma mark - Compile-Time assertion checks
-#endif
-
-// Some C compiler cleverness. We can make the compiler check certain things for
-// us, and report compile-time errors if anything is wrong. The usual way to do
-// this would be to use a run-time "if" statement, but then you don't find out
-// what's wrong until you run the software. This way, if the assertion condition
-// is false, the array size is negative, and the complier complains immediately.
-
-struct CompileTimeAssertionChecks_mDNS
-	{
-	// Check that the compiler generated our on-the-wire packet format structure definitions
-	// properly packed, without adding padding bytes to align fields on 32-bit or 64-bit boundaries.
-	char assert0[(sizeof(rdataSRV)         == 262                          ) ? 1 : -1];
-	char assert1[(sizeof(DNSMessageHeader) ==  12                          ) ? 1 : -1];
-	char assert2[(sizeof(DNSMessage)       ==  12+AbsoluteMaxDNSMessageData) ? 1 : -1];
-	char assert3[(sizeof(mDNSs8)           ==   1                          ) ? 1 : -1];
-	char assert4[(sizeof(mDNSu8)           ==   1                          ) ? 1 : -1];
-	char assert5[(sizeof(mDNSs16)          ==   2                          ) ? 1 : -1];
-	char assert6[(sizeof(mDNSu16)          ==   2                          ) ? 1 : -1];
-	char assert7[(sizeof(mDNSs32)          ==   4                          ) ? 1 : -1];
-	char assert8[(sizeof(mDNSu32)          ==   4                          ) ? 1 : -1];
-	char assert9[(sizeof(mDNSOpaque16)     ==   2                          ) ? 1 : -1];
-	char assertA[(sizeof(mDNSOpaque32)     ==   4                          ) ? 1 : -1];
-	char assertB[(sizeof(mDNSOpaque128)    ==  16                          ) ? 1 : -1];
-	char assertC[(sizeof(CacheRecord  )    ==  sizeof(CacheGroup)          ) ? 1 : -1];
-	char assertD[(sizeof(int)              >=  4                           ) ? 1 : -1];
-	char assertE[(StandardAuthRDSize       >=  256                         ) ? 1 : -1];
-	char assertF[(sizeof(EthernetHeader)   ==   14                         ) ? 1 : -1];
-	char assertG[(sizeof(ARP_EthIP     )   ==   28                         ) ? 1 : -1];
-	char assertH[(sizeof(IPv4Header    )   ==   20                         ) ? 1 : -1];
-	char assertI[(sizeof(IPv6Header    )   ==   40                         ) ? 1 : -1];
-	char assertJ[(sizeof(IPv6NDP       )   ==   24                         ) ? 1 : -1];
-	char assertK[(sizeof(UDPHeader     )   ==    8                         ) ? 1 : -1];
-	char assertL[(sizeof(IKEHeader     )   ==   28                         ) ? 1 : -1];
-	char assertM[(sizeof(TCPHeader     )   ==   20                         ) ? 1 : -1];
-
-	// Check our structures are reasonable sizes. Including overly-large buffers, or embedding
-	// other overly-large structures instead of having a pointer to them, can inadvertently
-	// cause structure sizes (and therefore memory usage) to balloon unreasonably.
-	char sizecheck_RDataBody           [(sizeof(RDataBody)            ==   264) ? 1 : -1];
-	char sizecheck_ResourceRecord      [(sizeof(ResourceRecord)       <=    64) ? 1 : -1];
-	char sizecheck_AuthRecord          [(sizeof(AuthRecord)           <=  1208) ? 1 : -1];
-	char sizecheck_CacheRecord         [(sizeof(CacheRecord)          <=   184) ? 1 : -1];
-	char sizecheck_CacheGroup          [(sizeof(CacheGroup)           <=   184) ? 1 : -1];
-	char sizecheck_DNSQuestion         [(sizeof(DNSQuestion)          <=   786) ? 1 : -1];
-	char sizecheck_ZoneData            [(sizeof(ZoneData)             <=  1624) ? 1 : -1];
-	char sizecheck_NATTraversalInfo    [(sizeof(NATTraversalInfo)     <=   192) ? 1 : -1];
-	char sizecheck_HostnameInfo        [(sizeof(HostnameInfo)         <=  3050) ? 1 : -1];
-	char sizecheck_DNSServer           [(sizeof(DNSServer)            <=   320) ? 1 : -1];
-	char sizecheck_NetworkInterfaceInfo[(sizeof(NetworkInterfaceInfo) <=  6850) ? 1 : -1];
-	char sizecheck_ServiceRecordSet    [(sizeof(ServiceRecordSet)     <=  5500) ? 1 : -1];
-	char sizecheck_DomainAuthInfo      [(sizeof(DomainAuthInfo)       <=  7808) ? 1 : -1];
-	char sizecheck_ServiceInfoQuery    [(sizeof(ServiceInfoQuery)     <=  3200) ? 1 : -1];
-#if APPLE_OSX_mDNSResponder
-	char sizecheck_ClientTunnel        [(sizeof(ClientTunnel)         <=  1148) ? 1 : -1];
-#endif
-	};
-
-// ***************************************************************************
-
-#ifdef __cplusplus
-	}
-#endif
-
-#endif

+ 0 - 89
src/app/mDNS/mDNSCore/mDNSPlatformFunctions.h

@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
-
-    Change History (most recent first):
-
-$Log: mDNSPlatformFunctions.h,v $
-Revision 1.1.1.1  2005/07/23 13:57:05  shiro
-raop_play project
-
-Revision 1.1.2.1  2004/09/18 03:29:20  shiro
-*** empty log message ***
-
-Revision 1.22.2.1  2003/12/05 00:03:34  cheshire
-<rdar://problem/3487869> Use buffer size MAX_ESCAPED_DOMAIN_NAME instead of 256
-
-Revision 1.22  2003/08/18 22:53:37  cheshire
-<rdar://problem/3382647> mDNSResponder divide by zero in mDNSPlatformTimeNow()
-
-Revision 1.21  2003/08/15 20:16:57  cheshire
-Update comment for <rdar://problem/3366590> mDNSResponder takes too much RPRVT
-
-Revision 1.20  2003/08/12 19:56:24  cheshire
-Update to APSL 2.0
-
-Revision 1.19  2003/08/05 22:20:15  cheshire
-<rdar://problem/3330324> Need to check IP TTL on responses
-
-Revision 1.18  2003/07/22 23:57:20  cheshire
-Move platform-layer function prototypes from mDNSClientAPI.h to mDNSPlatformFunctions.h where they belong
-
-Revision 1.17  2003/07/19 03:15:15  cheshire
-Add generic MemAllocate/MemFree prototypes to mDNSPlatformFunctions.h,
-and add the obvious trivial implementations to each platform support layer
-
-Revision 1.16  2003/07/02 21:19:46  cheshire
-<rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
-Revision 1.15  2003/05/23 22:39:45  cheshire
-<rdar://problem/3268151> Need to adjust maximum packet size for IPv6
-
-Revision 1.14  2003/04/28 21:54:57  cheshire
-Fix compiler warning
-
-Revision 1.13  2003/03/15 04:40:36  cheshire
-Change type called "mDNSOpaqueID" to the more descriptive name "mDNSInterfaceID"
-
-Revision 1.12  2003/02/21 01:54:08  cheshire
-Bug #: 3099194 mDNSResponder needs performance improvements
-Switched to using new "mDNS_Execute" model (see "Implementer Notes.txt")
-
-Revision 1.11  2002/12/23 22:13:29  jgraessl
-
-Reviewed by: Stuart Cheshire
-Initial IPv6 support for mDNSResponder.
-
-Revision 1.10  2002/09/21 20:44:49  zarzycki
-Added APSL info
-
-Revision 1.9  2002/09/19 04:20:43  cheshire
-Remove high-ascii characters that confuse some systems
-
-Revision 1.8  2002/09/16 23:12:14  cheshire
-Minor code tidying
-
-Revision 1.7  2002/09/16 18:41:42  cheshire
-Merge in license terms from Quinn's copy, in preparation for Darwin release
-
-*/
-
-// Note: All moved to mDNSClientAPI.h

+ 0 - 1118
src/app/mDNS/mDNSPosix/mDNSPosix.c

@@ -1,1118 +0,0 @@
-/*
- * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
- *
- * Formatting notes:
- * This code follows the "Whitesmiths style" C indentation rules. Plenty of discussion
- * on C indentation can be found on the web, such as <http://www.kafejo.com/komp/1tbs.htm>,
- * but for the sake of brevity here I will say just this: Curly braces are not syntactially
- * part of an "if" statement; they are the beginning and ending markers of a compound statement;
- * therefore common sense dictates that if they are part of a compound statement then they
- * should be indented to the same level as everything else in that compound statement.
- * Indenting curly braces at the same level as the "if" implies that curly braces are
- * part of the "if", which is false. (This is as misleading as people who write "char* x,y;"
- * thinking that variables x and y are both of type "char*" -- and anyone who doesn't
- * understand why variable y is not of type "char*" just proves the point that poor code
- * layout leads people to unfortunate misunderstandings about how the C language really works.)
-
- Change History (most recent first):
-
- $Log: mDNSPosix.c,v $
- Revision 1.2  2005/11/21 13:51:48  shiro
- *** empty log message ***
-
- Revision 1.1.1.1  2005/07/23 13:57:05  shiro
- raop_play project
-
- Revision 1.1.2.1  2004/09/18 03:29:20  shiro
- *** empty log message ***
-
- Revision 1.25.2.1  2004/04/09 17:57:31  cheshire
- Make sure to set the TxAndRx field so that duplicate suppression works correctly
-
- Revision 1.25  2003/10/30 19:25:49  cheshire
- Fix signed/unsigned warning on certain compilers
-
- Revision 1.24  2003/08/18 23:12:23  cheshire
- <rdar://problem/3382647> mDNSResponder divide by zero in mDNSPlatformTimeNow()
-
- Revision 1.23  2003/08/12 19:56:26  cheshire
- Update to APSL 2.0
-
- Revision 1.22  2003/08/06 18:46:15  cheshire
- LogMsg() errors are serious -- always report them to stderr, regardless of debugging level
-
- Revision 1.21  2003/08/06 18:20:51  cheshire
- Makefile cleanup
-
- Revision 1.20  2003/08/05 23:56:26  cheshire
- Update code to compile with the new mDNSCoreReceive() function that requires a TTL
- (Right now mDNSPosix.c just reports 255 -- we should fix this)
-
- Revision 1.19  2003/07/19 03:15:16  cheshire
- Add generic MemAllocate/MemFree prototypes to mDNSPlatformFunctions.h,
- and add the obvious trivial implementations to each platform support layer
-
- Revision 1.18  2003/07/14 18:11:54  cheshire
- Fix stricter compiler warnings
-
- Revision 1.17  2003/07/13 01:08:38  cheshire
- There's not much point running mDNS over a point-to-point link; exclude those
-
- Revision 1.16  2003/07/02 21:19:59  cheshire
- <rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
- Revision 1.15  2003/06/18 05:48:41  cheshire
- Fix warnings
-
- Revision 1.14  2003/05/26 03:21:30  cheshire
- Tidy up address structure naming:
- mDNSIPAddr         => mDNSv4Addr (for consistency with mDNSv6Addr)
- mDNSAddr.addr.ipv4 => mDNSAddr.ip.v4
- mDNSAddr.addr.ipv6 => mDNSAddr.ip.v6
-
- Revision 1.13  2003/05/26 03:01:28  cheshire
- <rdar://problem/3268904> sprintf/vsprintf-style functions are unsafe; use snprintf/vsnprintf instead
-
- Revision 1.12  2003/05/21 03:49:18  cheshire
- Fix warning
-
- Revision 1.11  2003/05/06 00:00:50  cheshire
- <rdar://problem/3248914> Rationalize naming of domainname manipulation functions
-
- Revision 1.10  2003/04/25 01:45:57  cheshire
- <rdar://problem/3240002> mDNS_RegisterNoSuchService needs to include a host name
-
- Revision 1.9  2003/03/20 21:10:31  cheshire
- Fixes done at IETF 56 to make mDNSProxyResponderPosix run on Solaris
-
- Revision 1.8  2003/03/15 04:40:38  cheshire
- Change type called "mDNSOpaqueID" to the more descriptive name "mDNSInterfaceID"
-
- Revision 1.7  2003/03/13 03:46:21  cheshire
- Fixes to make the code build on Linux
-
- Revision 1.6  2003/03/08 00:35:56  cheshire
- Switched to using new "mDNS_Execute" model (see "mDNSCore/Implementer Notes.txt")
-
- Revision 1.5  2002/12/23 22:13:31  jgraessl
- Reviewed by: Stuart Cheshire
- Initial IPv6 support for mDNSResponder.
-
- Revision 1.4  2002/09/27 01:47:45  cheshire
- Workaround for Linux 2.0 systems that don't have IP_PKTINFO
-
- Revision 1.3  2002/09/21 20:44:53  zarzycki
- Added APSL info
-
- Revision 1.2  2002/09/19 21:25:36  cheshire
- mDNS_snprintf() doesn't need to be in a separate file
-
- Revision 1.1  2002/09/17 06:24:34  cheshire
- First checkin
-*/
-
-#include "mDNSClientAPI.h"           // Defines the interface provided to the client layer above
-#include "mDNSPlatformFunctions.h"   // Defines the interface to the supporting layer below
-#include "mDNSPosix.h"				 // Defines the specific types needed to run mDNS on this platform
-#include <assert.h>
-//#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-//#include <unistd.h>
-#include <stdarg.h>
-//#include <fcntl.h>
-//#include <sys/types.h>
-//#include <sys/socket.h>
-//#include <sys/uio.h>
-//#include <netinet/in.h>
-#include "utils.h"
-#include "APSCommonServices.h"
-#include "lwip/sockets.h"
-#include "wm_sockets.h"
-#include "wm_netif.h"
-#include "lwip/inet.h"
-#include "lwip/igmp.h"
-#include <time.h>                   // platform support for UTC time
-#include "wm_osal.h"
-#include "utils.h"
-//#include "wm_overlay_common.h"
-
-//#include "mDNSUNP.h"
-
-// ***************************************************************************
-// Structures
-
-// PosixNetworkInterface is a record extension of the core NetworkInterfaceInfo
-// type that supports extra fields needed by the Posix platform.
-//
-// IMPORTANT: coreIntf must be the first field in the structure because
-// we cast between pointers to the two different types regularly.
-
-typedef struct PosixNetworkInterface PosixNetworkInterface;
-
-struct PosixNetworkInterface
-{
-	NetworkInterfaceInfo    coreIntf;
-	const char *            intfName;
-	PosixNetworkInterface * aliasIntf;
-	int                     index;
-	int                     multicastSocket;
-	int                     multicastSocketv6;
-};
-
-// ***************************************************************************
-// Globals (for debugging)
-
-static int num_registered_interfaces = 0;
-//static int num_pkts_accepted = 0;
-//static int num_pkts_rejected = 0;
-
-// ***************************************************************************
-// Functions
-
-int gMDNSPlatformPosixVerboseLevel = 2;
-
-extern u8 *wpa_supplicant_get_mac(void);
-#if 1
-// Note, this uses mDNS_vsnprintf instead of standard "vsnprintf", because mDNS_vsnprintf knows
-// how to print special data types like IP addresses and length-prefixed domain names
-mDNSexport void debugf_(const char *format, ...)
-{
-	unsigned char buffer[512];
-	va_list ptr;
-	va_start(ptr,format);
-	buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
-	va_end(ptr);
-	if (gMDNSPlatformPosixVerboseLevel >= 1)
-		printf("%s\n", buffer);
-	//fflush(stderr);
-}
-
-mDNSexport void verbosedebugf_(const char *format, ...)
-{
-	unsigned char buffer[512];
-	va_list ptr;
-	va_start(ptr,format);
-	buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
-	va_end(ptr);
-	if (gMDNSPlatformPosixVerboseLevel >= 2)
-		printf("%s\n", buffer);
-	//fflush(stderr);
-}
-
-mDNSexport void LogMsg_(const char *format, ...)
-{
-	unsigned char buffer[512];
-	va_list ptr;
-	va_start(ptr,format);
-	buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0;
-	va_end(ptr);
-	printf("%s\n", buffer);
-	//fflush(stderr);
-}
-#endif
-#define PosixErrorToStatus(errNum) ((errNum) == 0 ? mStatus_NoError : mStatus_UnknownErr)
-
-static int gethostname(char * hostname, int len)
-{
-	u8* mac = wpa_supplicant_get_mac();
-	snprintf(hostname, len, "WM_Hos_%02X%02X", mac[4], mac[5]);
-	return 0;//random_get_bytes(hostname, len);
-}
-static void SockAddrTomDNSAddr(const struct sockaddr *const sa, mDNSAddr *ipAddr, mDNSIPPort *ipPort)
-{
-	//LOG("SockAddrTomDNSAddr: sa_family %d\n", sa->sa_family);
-	switch (sa->sa_family)
-	{
-	case AF_INET:
-	{
-		struct sockaddr_in* sin          = (struct sockaddr_in*)sa;
-		ipAddr->type                     = mDNSAddrType_IPv4;
-		ipAddr->ip.v4.NotAnInteger       = sin->sin_addr.s_addr;
-		if (ipPort) ipPort->NotAnInteger = sin->sin_port;
-		break;
-	}
-
-#ifdef mDNSIPv6Support
-	case AF_INET6:
-	{
-		struct sockaddr_in6* sin6        = (struct sockaddr_in6*)sa;
-#ifndef NOT_HAVE_SA_LEN
-		assert(sin6->sin6_len == sizeof(*sin6));
-#endif		
-		ipAddr->type                     = mDNSAddrType_IPv6;
-		ipAddr->ip.v6                    = *(mDNSv6Addr*)&sin6->sin6_addr;
-		if (ipPort) ipPort->NotAnInteger = sin6->sin6_port;
-		break;
-	}
-#endif
-
-	default:
-		LOG("SockAddrTomDNSAddr: Uknown address family %d\n", sa->sa_family);
-		ipAddr->type = mDNSAddrType_None;
-		if (ipPort) ipPort->NotAnInteger = 0;
-		break;
-	}
-}
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark ***** Send and Receive
-#endif
-
-// mDNS core calls this routine when it needs to send a packet.
-mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end,
-				       mDNSInterfaceID InterfaceID, mDNSIPPort srcPort, const mDNSAddr *dst, mDNSIPPort dstPort)
-{
-	int                     err;
-	struct sockaddr_storage to;
-	PosixNetworkInterface * thisIntf;
-
-	assert(m != NULL);
-	assert(msg != NULL);
-	assert(end != NULL);
-	assert( (((char *) end) - ((char *) msg)) > 0 );
-	assert(InterfaceID != 0); // Can't send from zero source address
-	assert(srcPort.NotAnInteger != 0);     // Nor from a zero source port
-	assert(dstPort.NotAnInteger != 0);     // Nor from a zero source port
-
-	if (dst->type == mDNSAddrType_IPv4)
-	{
-		struct sockaddr_in *sin = (struct sockaddr_in*)&to;
-#ifndef NOT_HAVE_SA_LEN
-		sin->sin_len            = sizeof(*sin);
-#endif
-		sin->sin_family         = AF_INET;
-		sin->sin_port           = dstPort.NotAnInteger;
-		sin->sin_addr.s_addr    = dst->ip.v4.NotAnInteger;
-	}
-
-#ifdef mDNSIPv6Support
-	else if (dst->type == mDNSAddrType_IPv6)
-	{
-		struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&to;
-		mDNSPlatformMemZero(sin6, sizeof(*sin6));
-#ifndef NOT_HAVE_SA_LEN
-		sin6->sin6_len            = sizeof(*sin6);
-#endif
-		sin6->sin6_family         = AF_INET6;
-		sin6->sin6_port           = dstPort.NotAnInteger;
-		sin6->sin6_addr           = *(struct in6_addr*)&dst->ip.v6;
-	}
-#endif
-
-	err = 0;
-	thisIntf = (PosixNetworkInterface *)(InterfaceID);
-	if (dst->type == mDNSAddrType_IPv4)
-		err = sendto(thisIntf->multicastSocket, msg, (char*)end - (char*)msg, 0, (struct sockaddr *)&to, GET_SA_LEN(to));
-
-#ifdef mDNSIPv6Support
-	else if (dst->type == mDNSAddrType_IPv6)
-		err = sendto(thisIntf->multicastSocketv6, msg, (char*)end - (char*)msg, 0, (struct sockaddr *)&to, GET_SA_LEN(to));
-#endif
-
-	if (err > 0) err = 0;
-	else if (err < 0)
-	{
-		//LOG("mDNSPlatformSendUDP got error %d (%s) sending packet to %#a on interface %#a/%s/%d",
-		//	      errno, strerror(errno), dst, &thisIntf->coreIntf.ip, thisIntf->intfName, thisIntf->index);
-		LOG("mDNSPlatformSendUDP got err %d, dst->type %ld\n", err, dst->type);
-	}
-	return PosixErrorToStatus(err);
-}
-
-DNSMessage packet;
-// This routine is called when the main loop detects that data is available on a socket.
-static void SocketDataReady(mDNS *const m, PosixNetworkInterface *intf, int skt)
-{
-	mDNSAddr   senderAddr, destAddr;
-	mDNSIPPort senderPort;
-	ssize_t                 packetLen = 0;
-	//struct my_in_pktinfo    packetInfo;
-	struct sockaddr_storage from;
-	socklen_t               fromLen;
-	int                     flags;
-//	mDNSu8					ttl;
-//	mDNSBool                reject;
-//	const mDNSInterfaceID InterfaceID = intf ? intf->coreIntf.InterfaceID : NULL;
-
-	assert(m    != NULL);
-	assert(intf != NULL);
-	assert(skt  >= 0);
-
-	fromLen = sizeof(from);
-	flags   = 0;
-	memset(&packet, 0, sizeof(DNSMessage));
-#if 0
-	packetLen = recvfrom_flags(skt, &packet, sizeof(packet), &flags, (struct sockaddr *) &from, &fromLen, &packetInfo);
-
-#else
-	packetLen = recvfrom(skt, &packet, sizeof(DNSMessage), flags, (struct sockaddr *) &from, &fromLen);
-#endif
-	if (packetLen >= 0)
-	{
-		SockAddrTomDNSAddr((struct sockaddr*)&from, &senderAddr, &senderPort);
-#if 0
-		SockAddrTomDNSAddr((struct sockaddr*)&packetInfo.ipi_addr, &destAddr, NULL);
-#else
-		{
-			struct tls_ethif * ethif = tls_netif_get_ethif();
-			destAddr.type = mDNSAddrType_IPv4;
-			destAddr.ip.v4.NotAnInteger = ip_addr_get_ip4_u32(&ethif->ip_addr);
-		}
-#endif
-
-		// If we have broken IP_RECVDSTADDR functionality (so far
-		// I've only seen this on OpenBSD) then apply a hack to
-		// convince mDNS Core that this isn't a spoof packet.
-		// Basically what we do is check to see whether the
-		// packet arrived as a multicast and, if so, set its
-		// destAddr to the mDNS address.
-		//
-		// I must admit that I could just be doing something
-		// wrong on OpenBSD and hence triggering this problem
-		// but I'm at a loss as to how.
-		//
-		// If this platform doesn't have IP_PKTINFO or IP_RECVDSTADDR, then we have
-		// no way to tell the destination address or interface this packet arrived on,
-		// so all we can do is just assume it's a multicast
-
-#if 0//HAVE_BROKEN_RECVDSTADDR || (!defined(IP_PKTINFO) && !defined(IP_RECVDSTADDR))
-		if ( (destAddr.NotAnInteger == 0) && (flags & MSG_MCAST) )
-		{
-			destAddr.type = senderAddr.type;
-			if      (senderAddr.type == mDNSAddrType_IPv4) destAddr.ip.v4 = AllDNSLinkGroup;
-			else if (senderAddr.type == mDNSAddrType_IPv6) destAddr.ip.v6 = AllDNSLinkGroupv6;
-		}
-#endif
-
-		// We only accept the packet if the interface on which it came
-		// in matches the interface associated with this socket.
-		// We do this match by name or by index, depending on which
-		// information is available.  recvfrom_flags sets the name
-		// to "" if the name isn't available, or the index to -1
-		// if the index is available.  This accomodates the various
-		// different capabilities of our target platforms.
-
-#if 0
-		reject = mDNSfalse;
-		if      ( packetInfo.ipi_ifname[0] != 0 ) reject = (strcmp(packetInfo.ipi_ifname, intf->intfName) != 0);
-		else if ( packetInfo.ipi_ifindex != -1 )  reject = (packetInfo.ipi_ifindex != intf->index);
-
-		if (reject)
-		{
-			LOG("SocketDataReady ignored a packet from %#a to %#a on interface %s/%d expecting %#a/%s/%d",
-				      &senderAddr, &destAddr, packetInfo.ipi_ifname, packetInfo.ipi_ifindex,
-				      &intf->coreIntf.ip, intf->intfName, intf->index);
-			packetLen = -1;
-			num_pkts_rejected++;
-			if (num_pkts_rejected > (num_pkts_accepted + 1) * (num_registered_interfaces + 1) * 2)
-			{
-				fprintf(stderr,
-					"*** WARNING: Received %d packets; Accepted %d packets; Rejected %d packets because of interface mismatch\n",
-					num_pkts_accepted + num_pkts_rejected, num_pkts_accepted, num_pkts_rejected);
-				num_pkts_accepted = 0;
-				num_pkts_rejected = 0;
-			}
-		}
-		else
-#endif
-		{
-#if 0
-			int i;
-			mDNSu8 * ptr = (mDNSu8 *)&packet;
-			//LOG("SocketDataReady got a packet from %#a to %#a on interface %#a/%s/%d",
-			//	      &senderAddr, &destAddr, &intf->coreIntf.ip, intf->intfName, intf->index);
-			LOG("packetLen=%d\n", packetLen);
-			for(i = 0; i < packetLen; i++)
-			{
-				if(ptr[i] < 127 && ptr[i] > 31)
-					LOG("%c", ptr[i]);
-				else
-					LOG("%02X ", ptr[i]);
-			}
-			LOG("\n");
-#endif
-//			num_pkts_accepted++;
-		}
-	}
-
-	if (packetLen >= 0 && packetLen < (ssize_t)sizeof(DNSMessageHeader))
-	{
-		LOG("SocketDataReady packet length (%d) too short", packetLen);
-		packetLen = -1;
-	}
-
-	if (packetLen >= 0)
-		mDNSCoreReceive(m, &packet, (mDNSu8 *)&packet + packetLen,
-				&senderAddr, senderPort, &destAddr, MulticastDNSPort, intf->coreIntf.InterfaceID, 255);
-}
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark ***** Init and Term
-#endif
-
-// On OS X this gets the text of the field labelled "Computer Name" in the Sharing Prefs Control Panel
-// Other platforms can either get the information from the appropriate place,
-// or they can alternatively just require all registering services to provide an explicit name
-mDNSlocal void GetUserSpecifiedFriendlyComputerName(domainlabel *const namelabel)
-{
-	MakeDomainLabelFromLiteralString(namelabel, "Fill in Default Service Name Here");
-}
-
-// This gets the current hostname, truncating it at the first dot if necessary
-mDNSlocal void GetUserSpecifiedRFC1034ComputerName(domainlabel *const namelabel)
-{
-	int len = 0;
-	gethostname((char *)(&namelabel->c[1]), MAX_DOMAIN_LABEL);
-	while (len < MAX_DOMAIN_LABEL && namelabel->c[len+1] && namelabel->c[len+1] != '.') len++;
-	namelabel->c[0] = len;
-}
-
-// Searches the interface list looking for the named interface.
-// Returns a pointer to if it found, or NULL otherwise.
-static PosixNetworkInterface *SearchForInterfaceByName(mDNS *const m, const char *intfName)
-{
-	PosixNetworkInterface *intf;
-
-	assert(m != NULL);
-	assert(intfName != NULL);
-
-	intf = (PosixNetworkInterface*)(m->HostInterfaces);
-	while ( (intf != NULL) && (strcmp(intf->intfName, intfName) != 0) )
-		intf = (PosixNetworkInterface *)(intf->coreIntf.next);
-
-	return intf;
-}
-
-// Frees the specified PosixNetworkInterface structure. The underlying
-// interface must have already been deregistered with the mDNS core.
-static void FreePosixNetworkInterface(PosixNetworkInterface *intf)
-{
-	assert(intf != NULL);
-	if (intf->intfName != NULL)        tls_mem_free((void *)intf->intfName);
-	if (intf->multicastSocket   != -1) assert(close(intf->multicastSocket) == 0);
-	if (intf->multicastSocketv6 != -1) assert(close(intf->multicastSocketv6) == 0);
-	tls_mem_free(intf);
-}
-
-// Grab the first interface, deregister it, free it, and repeat until done.
-static void ClearInterfaceList(mDNS *const m)
-{
-	assert(m != NULL);
-
-	while (m->HostInterfaces)
-	{
-		PosixNetworkInterface *intf = (PosixNetworkInterface*)(m->HostInterfaces);
-		mDNS_DeregisterInterface(m, &intf->coreIntf);
-		if (gMDNSPlatformPosixVerboseLevel > 0) LOG("Deregistered interface %s\n", intf->intfName);
-		FreePosixNetworkInterface(intf);
-	}
-	num_registered_interfaces = 0;
-//	num_pkts_accepted = 0;
-//	num_pkts_rejected = 0;
-}
-
-// Sets up a multicast send/receive socket for the specified
-// port on the interface specified by the IP addrelss intfAddr.
-static int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interfaceIndex, int *sktPtr)
-{
-	int err = 0;
-	static const int kOn = 1;
-	static const int kIntTwoFiveFive = 255;
-	static const unsigned char kByteTwoFiveFive = 255;
-	
-	(void) interfaceIndex;	// Unused
-	assert(intfAddr != NULL);
-	assert(sktPtr != NULL);
-	assert(*sktPtr == -1);
-
-	// Open the socket...
-	if       (intfAddr->sa_family == AF_INET) *sktPtr = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
-#ifdef mDNSIPv6Support
-	else if (intfAddr->sa_family == AF_INET6) *sktPtr = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
-#endif
-	else return EINVAL;
-
-	if (*sktPtr < 0) { err = errno; LOG("socket"); }
-
-	// ... with a shared UDP port
-	if (err == 0)
-	{
-#if defined(SO_REUSEPORT)
-		err = setsockopt(*sktPtr, SOL_SOCKET, SO_REUSEPORT, &kOn, sizeof(kOn));
-#elif defined(SO_REUSEADDR)
-		err = setsockopt(*sktPtr, SOL_SOCKET, SO_REUSEADDR, &kOn, sizeof(kOn));
-#else
-#error This platform has no way to avoid address busy errors on multicast.
-#endif
-		if (err < 0) { err = errno; LOG("setsockopt - SO_REUSExxxx err %d intfAddr->sa_family %d\n", err, intfAddr->sa_family); }
-	}
-
-	// We want to receive destination addresses and interface identifiers.
-	if (intfAddr->sa_family == AF_INET)
-	{
-		struct ip_mreq imr;
-		struct sockaddr_in bindAddr;
-		if (err == 0)
-		{
-#if defined(IP_PKTINFO)									// Linux
-			err = setsockopt(*sktPtr, IPPROTO_IP, IP_PKTINFO, &kOn, sizeof(kOn));
-			if (err < 0) { err = errno; LOG("setsockopt - IP_PKTINFO"); }
-#elif defined(IP_RECVDSTADDR) || defined(IP_RECVIF)		// BSD and Solaris
-#if defined(IP_RECVDSTADDR)
-			err = setsockopt(*sktPtr, IPPROTO_IP, IP_RECVDSTADDR, &kOn, sizeof(kOn));
-			if (err < 0) { err = errno; LOG("setsockopt - IP_RECVDSTADDR"); }
-#endif
-#if defined(IP_RECVIF)
-			if (err == 0)
-			{
-				err = setsockopt(*sktPtr, IPPROTO_IP, IP_RECVIF, &kOn, sizeof(kOn));
-				if (err < 0) { err = errno; LOG("setsockopt - IP_RECVIF"); }
-			}
-#endif
-#else
-//#warning This platform has no way to get the destination interface information -- will only work for single-homed hosts
-#endif
-		}
-
-		// Add multicast group membership on this interface
-		if (err == 0)
-		{
-			imr.imr_multiaddr.s_addr = AllDNSLinkGroup.NotAnInteger;
-			imr.imr_interface        = ((struct sockaddr_in*)intfAddr)->sin_addr;
-			err = setsockopt(*sktPtr, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr));
-			if (err < 0) { err = errno; LOG("setsockopt - IP_ADD_MEMBERSHIP"); }
-		}
-
-		// Specify outgoing interface too
-		if (err == 0)
-		{
-			err = setsockopt(*sktPtr, IPPROTO_IP, IP_MULTICAST_IF, &((struct sockaddr_in*)intfAddr)->sin_addr, sizeof(struct in_addr));
-			if (err < 0) { err = errno; LOG("setsockopt - IP_MULTICAST_IF"); }
-		}
-
-		// Per the mDNS spec, send unicast packets with TTL 255
-		if (err == 0)
-		{
-			err = setsockopt(*sktPtr, IPPROTO_IP, IP_TTL, &kIntTwoFiveFive, sizeof(kIntTwoFiveFive));
-			if (err < 0) { err = errno; LOG("setsockopt - IP_TTL"); }
-		}
-
-		// and multicast packets with TTL 255 too
-		// There's some debate as to whether IP_MULTICAST_TTL is an int or a byte so we just try both.
-		if (err == 0)
-		{
-			err = setsockopt(*sktPtr, IPPROTO_IP, IP_MULTICAST_TTL, &kByteTwoFiveFive, sizeof(kByteTwoFiveFive));
-			if (err < 0 && errno == EINVAL)
-				err = setsockopt(*sktPtr, IPPROTO_IP, IP_MULTICAST_TTL, &kIntTwoFiveFive, sizeof(kIntTwoFiveFive));
-			if (err < 0) { err = errno; LOG("setsockopt - IP_MULTICAST_TTL"); }
-		}
-
-		// And start listening for packets
-		if (err == 0)
-		{
-			bindAddr.sin_family      = AF_INET;
-			bindAddr.sin_port        = port.NotAnInteger;
-			bindAddr.sin_addr.s_addr = INADDR_ANY; // Want to receive multicasts AND unicasts on this socket
-			err = bind(*sktPtr, (struct sockaddr *) &bindAddr, sizeof(bindAddr));
-			if (err < 0) { err = errno; LOG("bind"); /*fflush(stderr); */}
-		}
-	} // endif (intfAddr->sa_family == AF_INET)
-
-#ifdef mDNSIPv6Support
-	else if (intfAddr->sa_family == AF_INET6)
-	{
-#if 1
-		struct ipv6_mreq imr6;
-		struct sockaddr_in6 bindAddr6;
-		if (err == 0)
-		{
-#if defined(IPV6_PKTINFO)
-			err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_PKTINFO, &kOn, sizeof(kOn));
-			if (err < 0) { err = errno; LOG("setsockopt - IPV6_PKTINFO"); }
-#else
-//#warning This platform has no way to get the destination interface information for IPv6 -- will only work for single-homed hosts
-#endif
-		}
-		// Add multicast group membership on this interface
-		if (err == 0)
-		{
-			imr6.ipv6mr_multiaddr       = *(const struct in6_addr*)&AllDNSLinkGroupv6;
-			imr6.ipv6mr_interface       = interfaceIndex;
-			err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_JOIN_GROUP, &imr6, sizeof(imr6));
-			if (err < 0)
-			{
-				err = errno;
-				LOG("setsockopt - IPV6_JOIN_GROUP err %d\n", err);
-			}
-		}
-#if 0
-		// Specify outgoing interface too
-		if (err == 0)
-		{
-			u_int	multicast_if = interfaceIndex;
-			err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_MULTICAST_IF, &multicast_if, sizeof(multicast_if));
-			if (err < 0) { err = errno; LOG("setsockopt - IPV6_MULTICAST_IF"); }
-		}
-#endif
-#else
-
-		struct sockaddr_in6 bindAddr6;
-		struct sockaddr_in6 ipv6_multiaddr;
-
-		ipv6_multiaddr.sin6_addr = *(const struct in6_addr*)&AllDNSLinkGroupv6;
-#endif
-		// We want to receive only IPv6 packets on this socket.
-		// Without this option, we may get IPv4 addresses as mapped addresses.
-		if (err == 0)
-		{
-			err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_V6ONLY, &kOn, sizeof(kOn));
-			if (err < 0) { err = errno; LOG("setsockopt - IPV6_V6ONLY"); }
-		}
-#if 0
-		// Per the mDNS spec, send unicast packets with TTL 255
-		if (err == 0)
-		{
-			err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &kIntTwoFiveFive, sizeof(kIntTwoFiveFive));
-			if (err < 0) { err = errno; LOG("setsockopt - IPV6_UNICAST_HOPS"); }
-		}
-
-		// and multicast packets with TTL 255 too
-		// There's some debate as to whether IPV6_MULTICAST_HOPS is an int or a byte so we just try both.
-		if (err == 0)
-		{
-			err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &kByteTwoFiveFive, sizeof(kByteTwoFiveFive));
-			if (err < 0 && errno == EINVAL)
-				err = setsockopt(*sktPtr, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &kIntTwoFiveFive, sizeof(kIntTwoFiveFive));
-			if (err < 0) { err = errno; LOG("setsockopt - IPV6_MULTICAST_HOPS"); }
-		}
-#endif
-		// And start listening for packets
-		if (err == 0)
-		{
-			mDNSPlatformMemZero(&bindAddr6, sizeof(bindAddr6));
-#ifndef NOT_HAVE_SA_LEN
-			bindAddr6.sin6_len         = sizeof(bindAddr6);
-#endif			
-			bindAddr6.sin6_family      = AF_INET6;
-			bindAddr6.sin6_port        = port.NotAnInteger;
-			bindAddr6.sin6_flowinfo    = 0;
-//			bindAddr6.sin6_addr.s_addr = IN6ADDR_ANY_INIT; // Want to receive multicasts AND unicasts on this socket
-			bindAddr6.sin6_addr = in6addr_any; // Want to receive multicasts AND unicasts on this socket
-			bindAddr6.sin6_scope_id    = 0;
-			err = bind(*sktPtr, (struct sockaddr *) &bindAddr6, sizeof(bindAddr6));
-			if (err < 0) { err = errno; LOG("bind"); /*fflush(stderr); */}
-		}
-	} // endif (intfAddr->sa_family == AF_INET6)
-#endif
-
-	// Set the socket to non-blocking.
-	if (err == 0)
-	{
-		err = fcntl(*sktPtr, F_GETFL, 0);
-		if (err < 0) err = errno;
-		else
-		{
-			err = fcntl(*sktPtr, F_SETFL, err | O_NONBLOCK);
-			if (err < 0) err = errno;
-		}
-	}
-
-	// Clean up
-	if (err != 0 && *sktPtr != -1) { assert(close(*sktPtr) == 0); *sktPtr = -1; }
-	assert( (err == 0) == (*sktPtr != -1) );
-	return err;
-}
-
-// Creates a PosixNetworkInterface for the interface whose IP address is
-// intfAddr and whose name is intfName and registers it with mDNS core.
-static int SetupOneInterface(mDNS *const m, struct sockaddr *intfAddr, const char *intfName)
-{
-	int err = 0;
-	PosixNetworkInterface *intf;
-	PosixNetworkInterface *alias = NULL;
-
-	assert(m != NULL);
-	assert(intfAddr != NULL);
-	assert(intfName != NULL);
-
-	// Allocate the interface structure itself.
-	intf = tls_mem_alloc(sizeof(*intf));
-	if (intf == NULL) { assert(0); err = ENOMEM; }
-
-	// And make a copy of the intfName.
-	if (err == 0)
-	{
-		intf->intfName = (char *)strdup(intfName);
-		if (intf->intfName == NULL) { assert(0); err = ENOMEM; }
-	}
-
-	if (err == 0)
-	{
-		// Set up the fields required by the mDNS core.
-		SockAddrTomDNSAddr(intfAddr, &intf->coreIntf.ip, NULL);
-		intf->coreIntf.Advertise = m->AdvertiseLocalAddresses;
-		intf->coreIntf.TxAndRx   = mDNStrue;
-
-		// Set up the extra fields in PosixNetworkInterface.
-		assert(intf->intfName != NULL);         // intf->intfName already set up above
-		intf->index                = 0;//if_nametoindex(intf->intfName);
-		intf->multicastSocket      = -1;
-		intf->multicastSocketv6    = -1;
-		alias                      = SearchForInterfaceByName(m, intf->intfName);
-		if (alias == NULL) alias   = intf;
-		intf->coreIntf.InterfaceID = (mDNSInterfaceID)alias;
-
-		if (alias != intf)
-			LOG("SetupOneInterface: %s %#a is an alias of %#a", intfName, (double)(int)&intf->coreIntf.ip, (double)(int)&alias->coreIntf.ip);
-	}
-	// Set up the multicast socket
-	if (err == 0)
-	{
-		if (alias->multicastSocket == -1 && intfAddr->sa_family == AF_INET)
-			err = SetupSocket(intfAddr, MulticastDNSPort, intf->index, &alias->multicastSocket);
-#ifdef mDNSIPv6Support
-		else if (alias->multicastSocketv6 == -1 && intfAddr->sa_family == AF_INET6)
-			err = SetupSocket(intfAddr, MulticastDNSPort, intf->index, &alias->multicastSocketv6);
-#endif
-	}
-
-	// The interface is all ready to go, let's register it with the mDNS core.
-	if (err == 0)
-		err = mDNS_RegisterInterface(m, &intf->coreIntf);
-
-	// Clean up.
-	if (err == 0)
-	{
-		num_registered_interfaces++;
-		LOG("SetupOneInterface: %s %#a Registered", intf->intfName, (double)(int)&intf->coreIntf.ip);
-		if (gMDNSPlatformPosixVerboseLevel > 0)
-			LOG("Registered interface %s\n", intf->intfName);
-	}
-	else
-	{
-		// Use intfName instead of intf->intfName in the next line to avoid dereferencing NULL.
-		LOG("SetupOneInterface: %s %#a failed to register %d", intfName, (double)(int)&intf->coreIntf.ip, err);
-		if (intf) { FreePosixNetworkInterface(intf); intf = NULL; }
-	}
-
-	assert( (err == 0) == (intf != NULL) );
-
-	return err;
-}
-
-static int SetupInterfaceList(mDNS *const m)
-{
-	int             err            = 0;
-#if 0
-	mDNSBool        foundav4       = mDNSfalse;
-	struct ifi_info *intfList      = get_ifi_info(AF_INET, mDNStrue);
-	struct ifi_info *firstLoopback = NULL;
-
-	assert(m != NULL);
-	LOG("SetupInterfaceList");
-
-	if (intfList == NULL) err = ENOENT;
-
-#ifdef mDNSIPv6Support
-	if (err == 0)		/* Link the IPv6 list to the end of the IPv4 list */
-	{
-		struct ifi_info **p = &intfList;
-		while (*p) p = &(*p)->ifi_next;
-		*p = get_ifi_info(AF_INET6, mDNStrue);
-	}
-#endif
-
-	if (err == 0)
-	{
-		struct ifi_info *i = intfList;
-		while (i)
-		{
-			if (     ((i->ifi_addr->sa_family == AF_INET)
-#ifdef mDNSIPv6Support
-				  || (i->ifi_addr->sa_family == AF_INET6)
-#endif
-					 ) &&  (i->ifi_flags & IFF_UP) && !(i->ifi_flags & IFF_POINTOPOINT) )
-			{
-				if (i->ifi_flags & IFF_LOOPBACK)
-				{
-					if (firstLoopback == NULL)
-						firstLoopback = i;
-				}
-				else
-				{
-					if (SetupOneInterface(m, i->ifi_addr, i->ifi_name) == 0)
-						if (i->ifi_addr->sa_family == AF_INET)
-							foundav4 = mDNStrue;
-				}
-			}
-			i = i->ifi_next;
-		}
-
-		// If we found no normal interfaces but we did find a loopback interface, register the
-		// loopback interface.  This allows self-discovery if no interfaces are configured.
-		// Temporary workaround: Multicast loopback on IPv6 interfaces appears not to work.
-		// In the interim, we skip loopback interface only if we found at least one v4 interface to use
-		// if ( (m->HostInterfaces == NULL) && (firstLoopback != NULL) )
-		if ( !foundav4 && firstLoopback )
-			(void) SetupOneInterface(m, firstLoopback->ifi_addr, firstLoopback->ifi_name);
-	}
-
-	// Clean up.
-	if (intfList != NULL) free_ifi_info(intfList);
-#else
-	struct tls_ethif * ethif = tls_netif_get_ethif();
-	if(ethif->status){
-		struct sockaddr_in sin_ip; 
-		struct sockaddr_in sin_mask;
-		memset(&sin_ip, 0, sizeof(struct sockaddr_in));
-		memset(&sin_mask, 0, sizeof(struct sockaddr_in));
-		sin_ip.sin_family = AF_INET;
-		sin_ip.sin_addr.s_addr = ip_addr_get_ip4_u32(&ethif->ip_addr);
-		
-		sin_mask.sin_family = AF_INET;
-		sin_mask.sin_addr.s_addr = ip_addr_get_ip4_u32(&ethif->netmask);
-		
-		err = SetupOneInterface(m, (struct sockaddr*)&sin_ip, "netif0");
-#ifdef mDNSIPv6Support
-	{
-		struct sockaddr_in6 sin6_ip; 
-		memset(&sin6_ip, 0, sizeof(struct sockaddr_in6));
-		sin6_ip.sin6_family = AF_INET6;
-#ifndef NOT_HAVE_SA_LEN
-		sin6_ip.sin6_len = sizeof(struct sockaddr_in6);
-#endif
-		MEMCPY((char *)&sin6_ip.sin6_addr.un.u32_addr, (char *)&ethif->ip6_addr[0], 16);
-		LOG("start setup ipv6 interface\n");
-		err = SetupOneInterface(m, (struct sockaddr*)&sin6_ip, "netif0");
-		LOG("setup ipv6 interface err %d\n", err);
-	}
-#endif
-	}
-#endif
-	return err;
-}
-
-// mDNS core calls this routine to initialise the platform-specific data.
-mDNSexport mStatus mDNSPlatformInit(mDNS *const m)
-{
-	int err;
-	assert(m != NULL);
-
-	// Tell mDNS core the names of this machine.
-
-	// Set up the nice label
-	m->nicelabel.c[0] = 0;
-	GetUserSpecifiedFriendlyComputerName(&m->nicelabel);
-	if (m->nicelabel.c[0] == 0) MakeDomainLabelFromLiteralString(&m->nicelabel, "Macintosh");
-
-	// Set up the RFC 1034-compliant label
-	m->hostlabel.c[0] = 0;
-	GetUserSpecifiedRFC1034ComputerName(&m->hostlabel);
-	if (m->hostlabel.c[0] == 0) MakeDomainLabelFromLiteralString(&m->hostlabel, "Macintosh");
-
-	mDNS_GenerateFQDN(m);
-
-	// Tell mDNS core about the network interfaces on this machine.
-	err = SetupInterfaceList(m);
-
-	// We don't do asynchronous initialization on the Posix platform, so by the time
-	// we get here the setup will already have succeeded or failed.  If it succeeded,
-	// we should just call mDNSCoreInitComplete() immediately.
-	if (err == 0)
-		mDNSCoreInitComplete(m, mStatus_NoError);
-
-	return PosixErrorToStatus(err);
-}
-
-// mDNS core calls this routine to clean up the platform-specific data.
-// In our case all we need to do is to tear down every network interface.
-mDNSexport void mDNSPlatformClose(mDNS *const m)
-{
-	assert(m != NULL);
-	ClearInterfaceList(m);
-}
-
-extern mStatus mDNSPlatformPosixRefreshInterfaceList(mDNS *const m)
-{
-	int err;
-	ClearInterfaceList(m);
-	err = SetupInterfaceList(m);
-	return PosixErrorToStatus(err);
-}
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark ***** Locking
-#endif
-
-// On the Posix platform, locking is a no-op because we only ever enter
-// mDNS core on the main thread.
-
-// mDNS core calls this routine when it wants to prevent
-// the platform from reentering mDNS core code.
-mDNSexport void    mDNSPlatformLock   (const mDNS *const m)
-{
-	(void) m;	// Unused
-}
-
-// mDNS core calls this routine when it release the lock taken by
-// mDNSPlatformLock and allow the platform to reenter mDNS core code.
-mDNSexport void    mDNSPlatformUnlock (const mDNS *const m)
-{
-	(void) m;	// Unused
-}
-
-#if COMPILER_LIKES_PRAGMA_MARK
-#pragma mark ***** Strings
-#endif
-
-// mDNS core calls this routine to copy C strings.
-// On the Posix platform this maps directly to the ANSI C strcpy.
-mDNSexport void    mDNSPlatformStrCopy(const void *src,       void *dst)
-{
-	strcpy((char *)dst, (char *)src);
-}
-
-// mDNS core calls this routine to get the length of a C string.
-// On the Posix platform this maps directly to the ANSI C strlen.
-mDNSexport mDNSu32  mDNSPlatformStrLen (const void *src)
-{
-	return strlen((char*)src);
-}
-
-// mDNS core calls this routine to copy memory.
-// On the Posix platform this maps directly to the ANSI C memcpy.
-mDNSexport void    mDNSPlatformMemCopy(const void *src,       void *dst, mDNSu32 len)
-{
-	memcpy(dst, src, len);
-}
-
-// mDNS core calls this routine to test whether blocks of memory are byte-for-byte
-// identical. On the Posix platform this is a simple wrapper around ANSI C memcmp.
-mDNSexport mDNSBool mDNSPlatformMemSame(const void *src, const void *dst, mDNSu32 len)
-{
-	return memcmp(dst, src, len) == 0;
-}
-
-// mDNS core calls this routine to clear blocks of memory.
-// On the Posix platform this is a simple wrapper around ANSI C memset.
-mDNSexport void    mDNSPlatformMemZero(                       void *dst, mDNSu32 len)
-{
-	memset(dst, 0, len);
-}
-
-mDNSexport void *  mDNSPlatformMemAllocate(mDNSu32 len) { return(tls_mem_alloc(len)); }
-mDNSexport void    mDNSPlatformMemFree    (void *mem)   { tls_mem_free(mem); }
-
-mDNSexport mDNSs32  mDNSPlatformOneSecond = 1024;
-
-mDNSexport mStatus mDNSPlatformTimeInit(mDNSs32 *timenow)
-{
-	// No special setup is required on Posix -- we just use gettimeofday();
-	// This is not really safe, because gettimeofday can go backwards if the user manually changes the date or time
-	// We should find a better way to do this
-	*timenow = mDNSPlatformTimeNow();
-	return(mStatus_NoError);
-}
-mDNSexport mDNSs32  mDNSPlatformTimeNow()
-{
-	struct timeval tv;
-
-	gettimeofday(&tv, NULL);
-	// tv.tv_sec is seconds since 1st January 1970 (GMT, with no adjustment for daylight savings time)
-	// tv.tv_usec is microseconds since the start of this second (i.e. values 0 to 999999)
-	// We use the lower 22 bits of tv.tv_sec for the top 22 bits of our result
-	// and we multiply tv.tv_usec by 16 / 15625 to get a value in the range 0-1023 to go in the bottom 10 bits.
-	// This gives us a proper modular (cyclic) counter that has a resolution of roughly 1ms (actually 1/1024 second)
-	// and correctly cycles every 2^22 seconds (4194304 seconds = approx 48 days).
-	return( (tv.tv_sec << 10) | (tv.tv_usec * 16 / 15625) );
-}
-static mDNSs32 last_report_time = 0;
-mDNSexport void mDNSPosixGetFDSet(mDNS *const m, int *nfds, fd_set *readfds, struct timeval *timeout)
-{
-	mDNSs32 ticks;
-	struct timeval interval;
-
-	// 1. Call mDNS_Execute() to let mDNSCore do what it needs to do
-	mDNSs32 nextevent = mDNS_Execute(m);
-
-	// 2. Build our list of active file descriptors
-	PosixNetworkInterface *info = (PosixNetworkInterface *)(m->HostInterfaces);
-	while (info)
-	{
-		if (info->multicastSocket != -1)
-		{
-			if (*nfds < info->multicastSocket + 1)
-				*nfds = info->multicastSocket + 1;
-			FD_SET(info->multicastSocket, readfds);
-		}
-		if (info->multicastSocketv6 != -1)
-		{
-			if (*nfds < info->multicastSocketv6 + 1)
-				*nfds = info->multicastSocketv6 + 1;
-			FD_SET(info->multicastSocketv6, readfds);
-		}
-		info = (PosixNetworkInterface *)(info->coreIntf.next);
-	}
-
-	// 3. Calculate the time remaining to the next scheduled event (in struct timeval format)
-	ticks = nextevent - mDNSPlatformTimeNow();
-	if (ticks < 1) ticks = 1;
-	interval.tv_sec  = ticks >> 10;						// The high 22 bits are seconds
-	interval.tv_usec = ((ticks & 0x3FF) * 15625) / 16;	// The low 10 bits are 1024ths
-
-	// 4. If client's proposed timeout is more than what we want, then reduce it
-	if (timeout->tv_sec > interval.tv_sec ||
-	    (timeout->tv_sec == interval.tv_sec && timeout->tv_usec > interval.tv_usec))
-		*timeout = interval;
-	if(timeout->tv_sec == 0 || timeout->tv_sec > 3)
-		timeout->tv_sec = 3;
-	if(tls_os_get_time() - last_report_time > (HZ * 10))
-	{
-		last_report_time = tls_os_get_time();
-		//LOG("\n@@@@@ REPORT GROUPS !!!!!\n");
-		igmp_report_groups(tls_get_netif());
-	}
-}
-
-mDNSexport void mDNSPosixProcessFDSet(mDNS *const m, fd_set *readfds)
-{
-	PosixNetworkInterface *info;
-	assert(m       != NULL);
-	assert(readfds != NULL);
-	info = (PosixNetworkInterface *)(m->HostInterfaces);
-	while (info)
-	{
-		if (info->multicastSocket != -1 && FD_ISSET(info->multicastSocket, readfds))
-		{
-			FD_CLR(info->multicastSocket, readfds);
-			SocketDataReady(m, info, info->multicastSocket);
-		}
-		if (info->multicastSocketv6 != -1 && FD_ISSET(info->multicastSocketv6, readfds))
-		{
-			FD_CLR(info->multicastSocketv6, readfds);
-			SocketDataReady(m, info, info->multicastSocketv6);
-		}
-		info = (PosixNetworkInterface *)(info->coreIntf.next);
-	}
-}

+ 0 - 123
src/app/mDNS/mDNSPosix/mDNSPosix.h

@@ -1,123 +0,0 @@
-/*
- * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
-
-    Change History (most recent first):
-
-$Log: mDNSPosix.h,v $
-Revision 1.1.1.1  2005/07/23 13:57:05  shiro
-raop_play project
-
-Revision 1.1.2.1  2004/09/18 03:29:20  shiro
-*** empty log message ***
-
-Revision 1.9  2003/10/30 19:25:19  cheshire
-Fix warning on certain compilers
-
-Revision 1.8  2003/08/12 19:56:26  cheshire
-Update to APSL 2.0
-
-Revision 1.7  2003/07/02 21:19:59  cheshire
-<rdar://problem/3313413> Update copyright notices, etc., in source code comments
-
-Revision 1.6  2003/03/13 03:46:21  cheshire
-Fixes to make the code build on Linux
-
-Revision 1.5  2003/03/08 00:35:56  cheshire
-Switched to using new "mDNS_Execute" model (see "mDNSCore/Implementer Notes.txt")
-
-Revision 1.4  2002/12/23 22:13:31  jgraessl
-
-Reviewed by: Stuart Cheshire
-Initial IPv6 support for mDNSResponder.
-
-Revision 1.3  2002/09/21 20:44:53  zarzycki
-Added APSL info
-
-Revision 1.2  2002/09/19 04:20:44  cheshire
-Remove high-ascii characters that confuse some systems
-
-Revision 1.1  2002/09/17 06:24:34  cheshire
-First checkin
-
-*/
-
-#ifndef __mDNSPlatformPosix_h
-#define __mDNSPlatformPosix_h
-
-//#include <sys/time.h>
-#include "wm_sockets.h"
-#define HAVE_IPV6 TLS_CONFIG_IPV6
-
-#if HAVE_IPV6
-#define mDNSIPv6Support 1
-#endif
-
-#if HAVE_IPV6
-#define sockaddr_storage sockaddr_in6
-#else
-#define sockaddr_storage sockaddr
-#endif // HAVE_IPV6	
-
-#ifndef ssize_t
-typedef int ssize_t;
-#endif
-
-#ifndef NOT_HAVE_SA_LEN
-#define GET_SA_LEN(X) (sizeof(struct sockaddr) > ((struct sockaddr*)&(X))->sa_len ? \
-                       sizeof(struct sockaddr) : ((struct sockaddr*)&(X))->sa_len   )
-#elif mDNSIPv6Support
-#define GET_SA_LEN(X) (((struct sockaddr*)&(X))->sa_family == AF_INET  ? sizeof(struct sockaddr_in) : \
-                       ((struct sockaddr*)&(X))->sa_family == AF_INET6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr))
-#else
-#define GET_SA_LEN(X) ((X).sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr))
-#endif
-
-#ifdef  __cplusplus
-    extern "C" {
-#endif
-
-// This is a global because debugf_() needs to be able to check its value
-extern int gMDNSPlatformPosixVerboseLevel;
-
-struct mDNS_PlatformSupport_struct
-	{
-    // No additional data required for Posix at this time
-	long dummy[1];	// Some compilers don't like empty structures
-	};
-
-extern mStatus mDNSPlatformPosixRefreshInterfaceList(mDNS *const m);
-    // See comment in implementation.
-
-// Call mDNSPosixGetFDSet before calling select(), to update the parameters
-// as may be necessary to meet the needs of the mDNSCore code.
-// The timeout pointer MUST NOT be NULL.
-// Set timeout->tv_sec to 0x3FFFFFFF if you want to have effectively no timeout
-// After calling mDNSPosixGetFDSet(), call select(nfds, &readfds, NULL, NULL, &timeout); as usual
-// After select() returns, call mDNSPosixProcessFDSet() to let mDNSCore do its work
-extern void mDNSPosixGetFDSet(mDNS *const m, int *nfds, fd_set *readfds, struct timeval *timeout);
-extern void mDNSPosixProcessFDSet(mDNS *const m, fd_set *readfds);
-
-#ifdef  __cplusplus
-    }
-#endif
-
-#endif

+ 2 - 2
src/network/lwip2.1.3/include/lwipopts.h

@@ -118,7 +118,7 @@
 
 #define LWIP_IPV4    TLS_CONFIG_IPV4
 #define LWIP_IPV6    TLS_CONFIG_IPV6
-#define LWIP_DNS      (TLS_CONFIG_SOCKET_RAW || TLS_CONFIG_SOCKET_STD)
+#define LWIP_DNS      0
 #define LWIP_NETIF_STATUS_CALLBACK      1
 #define TCP_LISTEN_BACKLOG              1
 #define TCP_DEFAULT_LISTEN_BACKLOG      8
@@ -126,7 +126,7 @@
 #define SO_REUSE_RXTOALL                1
 #define LWIP_ND6_MAX_MULTICAST_SOLICIT  10
 
-#define LWIP_HAVE_LOOPIF 1
+#define LWIP_HAVE_LOOPIF 0
 #define ETHARP_SUPPORT_STATIC_ENTRIES   1
 #define ETHARP_TABLE_MATCH_NETIF        0
 #define ARP_QUEUEING					1

+ 6 - 6
src/network/lwip2.1.3/netif/wm_ethernet.c

@@ -320,14 +320,14 @@ struct tls_ethif * tls_netif_get_ethif(void)
     }
 #endif
     
-    addr = (ip_addr_t *)dns_getserver(0);
-	dns1 = *addr;
+    // addr = (ip_addr_t *)dns_getserver(0);
+	// dns1 = *addr;
     //MEMCPY(&ethif->dns1.addr, (char *)&dns1.addr, 4);
-    ip_addr_copy(ethif->dns1, dns1);
-    addr = (ip_addr_t *)dns_getserver(1);
-	dns2 = *addr;
+    // ip_addr_copy(ethif->dns1, dns1);
+    // addr = (ip_addr_t *)dns_getserver(1);
+	// dns2 = *addr;
     //MEMCPY(&ethif->dns2.addr, (char *)&dns2.addr, 4);
-    ip_addr_copy(ethif->dns2, dns2);
+    // ip_addr_copy(ethif->dns2, dns2);
 	//ethif->status = nif->flags&NETIF_FLAG_UP;
 #if TLS_CONFIG_IPV6
 	for(i = 0; i < IPV6_ADDR_MAX_NUM; i++)